summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/README25
-rw-r--r--_test/tests/inc/auth_deleteprofile.test.php179
-rw-r--r--_test/tests/inc/auth_encryption.test.php12
-rw-r--r--_test/tests/inc/auth_random.test.php20
-rw-r--r--_test/tests/inc/common_ml.test.php37
-rw-r--r--_test/tests/inc/fulltext_backlinks.test.php77
-rw-r--r--_test/tests/inc/fulltext_mediause.test.php77
-rw-r--r--_test/tests/inc/httpclient_http.test.php55
-rw-r--r--_test/tests/inc/parser/parser_code.test.php72
-rw-r--r--_test/tests/inc/parser/parser_file.test.php56
-rw-r--r--_test/tests/inc/tar.test.php48
-rw-r--r--_test/tests/lib/exe/fetch_imagetoken.test.php44
-rw-r--r--_test/tests/lib/exe/fetch_statuscodes_external.test.php107
-rw-r--r--conf/dokuwiki.php1
-rw-r--r--data/pages/wiki/dokuwiki.txt2
-rw-r--r--inc/HTTPClient.php9
-rw-r--r--inc/PassHash.class.php2
-rw-r--r--inc/actions.php28
-rw-r--r--inc/auth.php230
-rw-r--r--inc/common.php21
-rw-r--r--inc/confutils.php5
-rw-r--r--inc/feedcreator.class.php2
-rw-r--r--inc/fetch.functions.php4
-rw-r--r--inc/fulltext.php60
-rw-r--r--inc/html.php100
-rw-r--r--inc/indexer.php8
-rw-r--r--inc/lang/de-informal/install.html6
-rw-r--r--inc/lang/de-informal/lang.php24
-rw-r--r--inc/lang/de-informal/locked.txt2
-rw-r--r--inc/lang/de-informal/password.txt2
-rw-r--r--inc/lang/de-informal/register.txt4
-rw-r--r--inc/lang/de/install.html4
-rw-r--r--inc/lang/de/lang.php25
-rw-r--r--inc/lang/de/locked.txt2
-rw-r--r--inc/lang/de/password.txt2
-rw-r--r--inc/lang/de/register.txt4
-rw-r--r--inc/lang/en/lang.php9
-rw-r--r--inc/lang/hu/diff.txt2
-rw-r--r--inc/lang/hu/draft.txt2
-rw-r--r--inc/lang/hu/edit.txt2
-rw-r--r--inc/lang/hu/install.html4
-rw-r--r--inc/lang/hu/lang.php168
-rw-r--r--inc/lang/hu/locked.txt2
-rw-r--r--inc/lang/hu/mailwrap.html13
-rw-r--r--inc/lang/hu/norev.txt2
-rw-r--r--inc/lang/hu/preview.txt3
-rw-r--r--inc/lang/hu/pwconfirm.txt4
-rw-r--r--inc/lang/hu/read.txt3
-rw-r--r--inc/lang/hu/register.txt2
-rw-r--r--inc/lang/hu/resendpwd.txt2
-rw-r--r--inc/lang/hu/resetpwd.txt3
-rw-r--r--inc/lang/hu/searchpage.txt2
-rw-r--r--inc/lang/hu/subscr_digest.txt3
-rw-r--r--inc/lang/hu/subscr_list.txt5
-rw-r--r--inc/lang/hu/subscr_single.txt2
-rw-r--r--inc/lang/ko/edit.txt2
-rw-r--r--inc/lang/ko/index.txt2
-rw-r--r--inc/lang/ko/install.html9
-rw-r--r--inc/lang/ko/lang.php8
-rw-r--r--inc/lang/ko/read.txt2
-rw-r--r--inc/lang/ko/register.txt2
-rw-r--r--inc/lang/sv/lang.php15
-rw-r--r--inc/lessc.inc.php3481
-rw-r--r--inc/load.php7
-rw-r--r--inc/media.php4
-rw-r--r--inc/parser/metadata.php30
-rw-r--r--inc/parser/parser.php8
-rw-r--r--inc/phpseclib/Crypt_AES.php188
-rw-r--r--inc/phpseclib/Crypt_Base.php1989
-rw-r--r--inc/phpseclib/Crypt_Hash.php823
-rw-r--r--inc/phpseclib/Crypt_Rijndael.php1374
-rw-r--r--inc/phpseclib/LICENSE21
-rw-r--r--inc/phpseclib/Math_BigInteger.php3651
-rwxr-xr-xinc/phpseclib/update.sh8
-rw-r--r--inc/plugin.php6
-rw-r--r--inc/search.php39
-rw-r--r--inc/template.php92
-rw-r--r--install.php4
-rw-r--r--lib/exe/css.php84
-rw-r--r--lib/exe/fetch.php1
-rw-r--r--lib/exe/js.php22
-rw-r--r--lib/exe/opensearch.php2
-rw-r--r--lib/plugins/acl/lang/de-informal/lang.php5
-rw-r--r--lib/plugins/acl/lang/de/help.txt2
-rw-r--r--lib/plugins/acl/lang/de/lang.php6
-rw-r--r--lib/plugins/acl/lang/hu/lang.php15
-rw-r--r--lib/plugins/acl/lang/ko/help.txt2
-rw-r--r--lib/plugins/acl/lang/sv/lang.php7
-rw-r--r--lib/plugins/acl/remote.php30
-rw-r--r--lib/plugins/acl/script.js1
-rw-r--r--lib/plugins/authad/lang/de-informal/settings.php1
-rw-r--r--lib/plugins/authad/lang/hu/settings.php18
-rw-r--r--lib/plugins/authad/lang/pl/settings.php10
-rw-r--r--lib/plugins/authad/lang/pt-br/settings.php3
-rw-r--r--lib/plugins/authad/lang/sv/settings.php5
-rw-r--r--lib/plugins/authldap/lang/de-informal/settings.php6
-rw-r--r--lib/plugins/authldap/lang/en/settings.php2
-rw-r--r--lib/plugins/authldap/lang/hu/settings.php26
-rw-r--r--lib/plugins/authldap/lang/ko/settings.php5
-rw-r--r--lib/plugins/authldap/lang/pl/settings.php7
-rw-r--r--lib/plugins/authldap/lang/pt-br/settings.php10
-rw-r--r--lib/plugins/authldap/lang/sv/settings.php5
-rw-r--r--lib/plugins/authmysql/lang/de-informal/settings.php1
-rw-r--r--lib/plugins/authmysql/lang/hu/settings.php41
-rw-r--r--lib/plugins/authmysql/lang/pl/settings.php10
-rw-r--r--lib/plugins/authmysql/lang/pt-br/settings.php1
-rw-r--r--lib/plugins/authmysql/lang/sv/settings.php5
-rw-r--r--lib/plugins/authpgsql/lang/de-informal/settings.php1
-rw-r--r--lib/plugins/authpgsql/lang/hu/settings.php37
-rw-r--r--lib/plugins/authpgsql/lang/pl/settings.php5
-rw-r--r--lib/plugins/authpgsql/lang/pt-br/settings.php1
-rw-r--r--lib/plugins/authpgsql/lang/sv/settings.php5
-rw-r--r--lib/plugins/config/admin.php4
-rw-r--r--lib/plugins/config/lang/ar/lang.php3
-rw-r--r--lib/plugins/config/lang/bg/lang.php7
-rw-r--r--lib/plugins/config/lang/ca-valencia/lang.php3
-rw-r--r--lib/plugins/config/lang/ca/lang.php3
-rw-r--r--lib/plugins/config/lang/cs/lang.php3
-rw-r--r--lib/plugins/config/lang/da/lang.php3
-rw-r--r--lib/plugins/config/lang/de-informal/lang.php45
-rw-r--r--lib/plugins/config/lang/de/lang.php59
-rw-r--r--lib/plugins/config/lang/el/lang.php3
-rw-r--r--lib/plugins/config/lang/en/lang.php37
-rw-r--r--lib/plugins/config/lang/eo/lang.php3
-rw-r--r--lib/plugins/config/lang/es/lang.php3
-rw-r--r--lib/plugins/config/lang/et/lang.php2
-rw-r--r--lib/plugins/config/lang/eu/lang.php3
-rw-r--r--lib/plugins/config/lang/fa/lang.php3
-rw-r--r--lib/plugins/config/lang/fi/lang.php3
-rw-r--r--lib/plugins/config/lang/fr/lang.php3
-rw-r--r--lib/plugins/config/lang/gl/lang.php3
-rw-r--r--lib/plugins/config/lang/he/lang.php3
-rw-r--r--lib/plugins/config/lang/hu/lang.php122
-rw-r--r--lib/plugins/config/lang/ia/lang.php3
-rw-r--r--lib/plugins/config/lang/is/lang.php1
-rw-r--r--lib/plugins/config/lang/it/lang.php3
-rw-r--r--lib/plugins/config/lang/ja/lang.php3
-rw-r--r--lib/plugins/config/lang/ko/intro.txt6
-rw-r--r--lib/plugins/config/lang/ko/lang.php7
-rw-r--r--lib/plugins/config/lang/la/lang.php3
-rw-r--r--lib/plugins/config/lang/lv/lang.php3
-rw-r--r--lib/plugins/config/lang/mr/lang.php3
-rw-r--r--lib/plugins/config/lang/ne/lang.php2
-rw-r--r--lib/plugins/config/lang/nl/lang.php3
-rw-r--r--lib/plugins/config/lang/no/lang.php3
-rw-r--r--lib/plugins/config/lang/pl/lang.php3
-rw-r--r--lib/plugins/config/lang/pt-br/lang.php2
-rw-r--r--lib/plugins/config/lang/pt/lang.php3
-rw-r--r--lib/plugins/config/lang/ro/lang.php3
-rw-r--r--lib/plugins/config/lang/ru/lang.php3
-rw-r--r--lib/plugins/config/lang/sk/lang.php3
-rw-r--r--lib/plugins/config/lang/sl/lang.php3
-rw-r--r--lib/plugins/config/lang/sq/lang.php3
-rw-r--r--lib/plugins/config/lang/sr/lang.php3
-rw-r--r--lib/plugins/config/lang/sv/lang.php3
-rw-r--r--lib/plugins/config/lang/th/lang.php1
-rw-r--r--lib/plugins/config/lang/tr/lang.php3
-rw-r--r--lib/plugins/config/lang/uk/lang.php3
-rw-r--r--lib/plugins/config/lang/zh-tw/lang.php3
-rw-r--r--lib/plugins/config/lang/zh/lang.php3
-rw-r--r--lib/plugins/config/settings/config.class.php163
-rw-r--r--lib/plugins/config/settings/config.metadata.php62
-rw-r--r--lib/plugins/plugin/lang/de-informal/lang.php1
-rw-r--r--lib/plugins/plugin/lang/hu/lang.php29
-rw-r--r--lib/plugins/plugin/lang/ko/admin_plugin.txt2
-rw-r--r--lib/plugins/plugin/lang/ko/lang.php4
-rw-r--r--lib/plugins/plugin/lang/sv/lang.php7
-rw-r--r--lib/plugins/popularity/helper.php2
-rw-r--r--lib/plugins/popularity/lang/de-informal/intro.txt2
-rw-r--r--lib/plugins/popularity/lang/de-informal/lang.php1
-rw-r--r--lib/plugins/popularity/lang/de/intro.txt2
-rw-r--r--lib/plugins/popularity/lang/hu/lang.php1
-rw-r--r--lib/plugins/popularity/lang/ko/intro.txt2
-rw-r--r--lib/plugins/popularity/lang/sv/lang.php8
-rw-r--r--lib/plugins/revert/admin.php2
-rw-r--r--lib/plugins/revert/lang/de-informal/intro.txt4
-rw-r--r--lib/plugins/revert/lang/de-informal/lang.php14
-rw-r--r--lib/plugins/revert/lang/de/intro.txt4
-rw-r--r--lib/plugins/revert/lang/de/lang.php9
-rw-r--r--lib/plugins/revert/lang/hu/lang.php3
-rw-r--r--lib/plugins/revert/lang/sv/lang.php9
-rw-r--r--lib/plugins/usermanager/admin.php19
-rw-r--r--lib/plugins/usermanager/lang/de-informal/lang.php1
-rw-r--r--lib/plugins/usermanager/lang/de/lang.php8
-rw-r--r--lib/plugins/usermanager/lang/hu/lang.php9
-rw-r--r--lib/plugins/usermanager/lang/sv/lang.php8
-rw-r--r--lib/plugins/usermanager/style.css4
-rw-r--r--lib/scripts/behaviour.js2
-rw-r--r--lib/scripts/edit.js9
-rw-r--r--lib/scripts/editor.js1
-rw-r--r--lib/scripts/helpers.js34
-rw-r--r--lib/scripts/jquery/jquery.cookie.js59
-rw-r--r--lib/scripts/media.js19
-rw-r--r--lib/scripts/page.js6
-rw-r--r--lib/scripts/toolbar.js29
-rw-r--r--lib/scripts/tree.js20
-rw-r--r--lib/scripts/tw-sack.js1
-rw-r--r--lib/tpl/dokuwiki/css/_admin.css2
-rw-r--r--lib/tpl/dokuwiki/css/_diff.css2
-rw-r--r--lib/tpl/dokuwiki/css/_edit.css12
-rw-r--r--lib/tpl/dokuwiki/css/_fileuploader.css8
-rw-r--r--lib/tpl/dokuwiki/css/_footnotes.css2
-rw-r--r--lib/tpl/dokuwiki/css/_forms.css7
-rw-r--r--lib/tpl/dokuwiki/css/_media_fullscreen.css40
-rw-r--r--lib/tpl/dokuwiki/css/_media_popup.css12
-rw-r--r--lib/tpl/dokuwiki/css/_modal.css10
-rw-r--r--lib/tpl/dokuwiki/css/_search.css6
-rw-r--r--lib/tpl/dokuwiki/css/_tabs.css14
-rw-r--r--lib/tpl/dokuwiki/css/_toc.css2
-rw-r--r--lib/tpl/dokuwiki/css/basic.less (renamed from lib/tpl/dokuwiki/css/basic.css)50
-rw-r--r--lib/tpl/dokuwiki/css/content.less (renamed from lib/tpl/dokuwiki/css/content.css)337
-rw-r--r--lib/tpl/dokuwiki/css/design.css405
-rw-r--r--lib/tpl/dokuwiki/css/design.less439
-rw-r--r--lib/tpl/dokuwiki/css/includes.css4
-rw-r--r--lib/tpl/dokuwiki/css/mixins.less10
-rw-r--r--lib/tpl/dokuwiki/css/mobile.less (renamed from lib/tpl/dokuwiki/css/mobile.css)62
-rw-r--r--lib/tpl/dokuwiki/css/pagetools.less (renamed from lib/tpl/dokuwiki/css/pagetools.css)143
-rw-r--r--lib/tpl/dokuwiki/css/structure.css81
-rw-r--r--lib/tpl/dokuwiki/css/structure.less89
-rw-r--r--lib/tpl/dokuwiki/detail.php30
-rw-r--r--lib/tpl/dokuwiki/images/pagetools-sprite.pngbin5931 -> 11325 bytes
-rw-r--r--lib/tpl/dokuwiki/images/pagetools/00_default.pngbin0 -> 616 bytes
-rw-r--r--lib/tpl/dokuwiki/main.php32
-rw-r--r--lib/tpl/dokuwiki/style.ini52
224 files changed, 14756 insertions, 1791 deletions
diff --git a/_test/README b/_test/README
index a4206f489..5220248b2 100644
--- a/_test/README
+++ b/_test/README
@@ -1,6 +1,6 @@
====== DokuWiki Test Suite ======
-This is the test suit to automatically test various parts of DokuWiki.
+This is the test suite to automatically test various parts of DokuWiki.
===== Requirements =====
@@ -9,22 +9,33 @@ This is the test suit to automatically test various parts of DokuWiki.
===== PHPUnit Installation ======
-via PEAR:
+==== via PEAR installer ====
pear config-set auto_discover 1
- pear upgrade
pear install pear.phpunit.de/PHPUnit
-on Windows:
+==== via Composer ====
- FIXME
+Include a composer.json file in your project, which can be as minimal as:
+
+<code>
+{
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*"
+ }
+}
+</code>
+
+==== via PHP archive (PHAR) ====
+
+Download http://pear.phpunit.de/get/phpunit.phar and make it executable on your system.
-===== Running all Tests =====
+===== Running all tests =====
Just change to the ''_test'' directory and run phpunit:
- cd _testing/
+ cd _test/
phpunit
PHPUnit will fail on some systems with a //headers already sent// error.
diff --git a/_test/tests/inc/auth_deleteprofile.test.php b/_test/tests/inc/auth_deleteprofile.test.php
new file mode 100644
index 000000000..dc38fcd16
--- /dev/null
+++ b/_test/tests/inc/auth_deleteprofile.test.php
@@ -0,0 +1,179 @@
+<?php
+
+class Mock_Auth_Plugin extends DokuWiki_Auth_Plugin {
+
+ public $loggedOff = false;
+
+ public function __construct($canDeleteUser = true) {
+ $this->cando['delUser'] = $canDeleteUser;
+ }
+
+ public function checkPass($user, $pass) {
+ return $pass == 'password';
+ }
+
+ public function deleteUsers($users) {
+ return in_array($_SERVER['REMOTE_USER'], $users);
+ }
+
+ public function logoff() {
+ $this->loggedOff = true;
+ }
+
+}
+
+class auth_deleteprofile_test extends DokuWikiTest {
+
+ /*
+ * Tests:
+ *
+ * 1. It works and the user is logged off
+ * 2. Password matches when config requires it
+ * 3,4. Auth plugin can prevent & wiki config can prevent
+ * 5. Any of invalid security token, missing/not set 'delete' flag, missing/unchecked 'confirm_delete'
+ *
+ */
+
+ function test_success() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ $this->assertTrue(auth_deleteprofile());
+ $this->assertTrue($auth->loggedOff);
+ }
+
+ function test_confirmation_required() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = true;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ 'oldpass' => 'wrong',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ // password check required - it fails, so don't delete profile
+ $this->assertFalse(auth_deleteprofile());
+
+ // now it passes, we're good to go
+ $INPUT->set('oldpass','password');
+ $INPUT->post->set('oldpass','password');
+ $this->assertTrue(auth_deleteprofile());
+ }
+
+ function test_authconfig_prevents() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin(false);
+ $conf['disableactions'] = '';
+ $this->assertFalse(auth_deleteprofile());
+ }
+
+ function test_wikiconfig_prevents() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+ $conf['disableactions'] = 'profile_delete';
+
+ $this->assertFalse(actionOK('profile_delete'));
+ $this->assertTrue($auth->canDo('delUser'));
+
+ $this->assertFalse(auth_deleteprofile());
+ }
+
+ function test_basic_parameters() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = true;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ 'oldpass' => 'password',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $input_foundation = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ $INPUT = clone $input_foundation;
+ $INPUT->remove('delete');
+ $this->assertFalse(auth_deleteprofile());
+
+ $INPUT = clone $input_foundation;
+ $INPUT->set('sectok','wrong');
+ $this->assertFalse(auth_deleteprofile());
+
+ $INPUT = clone $input_foundation;
+ $INPUT->remove('confirm_delete');
+ $this->assertFalse(auth_deleteprofile());
+ }
+} \ No newline at end of file
diff --git a/_test/tests/inc/auth_encryption.test.php b/_test/tests/inc/auth_encryption.test.php
new file mode 100644
index 000000000..041eba00e
--- /dev/null
+++ b/_test/tests/inc/auth_encryption.test.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Tests the auth_decrypt and auth_encrypt-functions
+ */
+class auth_encryption_test extends DokuWikiTest {
+ function testDeEncrypt() {
+ $data = "OnA28asdfäakgß*+!\"+*";
+ $secret = "oeaf1öasdöflk§";
+ $this->assertEquals($data, auth_decrypt(auth_encrypt($data, $secret), $secret));
+ }
+}
diff --git a/_test/tests/inc/auth_random.test.php b/_test/tests/inc/auth_random.test.php
new file mode 100644
index 000000000..f380eba53
--- /dev/null
+++ b/_test/tests/inc/auth_random.test.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Tests the random generator functions
+ */
+class auth_random_test extends DokuWikiTest {
+ function testRandomRange() {
+ $rand = auth_random(300, 2000);
+ $this->assertTrue($rand <= 2000, 'The generated number was above the limit');
+ $this->assertTrue($rand >= 300, 'The generate number was too low');
+ }
+
+ function testLargeRandoms() {
+ $min = (1 << 30);
+ $max = $min + (1 << 33) + 17;
+ $rand = auth_random($min, $max);
+ $this->assertTrue($rand >= $min, 'The generated number was too low');
+ $this->assertTrue($rand <= $max, 'The generated number was too high');
+ }
+}
diff --git a/_test/tests/inc/common_ml.test.php b/_test/tests/inc/common_ml.test.php
index 6f3b71db4..415c0a88d 100644
--- a/_test/tests/inc/common_ml.test.php
+++ b/_test/tests/inc/common_ml.test.php
@@ -90,6 +90,25 @@ class common_ml_test extends DokuWikiTest {
$this->assertEquals($expect, ml($id, $args));
}
+ function test_ml_img_external() {
+ global $conf;
+ $conf['useslash'] = 0;
+ $conf['userewrite'] = 0;
+
+ $ids = array(
+ 'https://example.com/lib/tpl/dokuwiki/images/logo.png',
+ 'http://example.com/lib/tpl/dokuwiki/images/logo.png',
+ 'ftp://example.com/lib/tpl/dokuwiki/images/logo.png'
+ );
+
+ foreach($ids as $id) {
+ $tok = media_get_token($id, 0, 0);
+
+ $expect = DOKU_BASE.$this->script.'?tok='.$tok.'&amp;media='.rawurlencode($id);
+ $this->assertEquals($expect, ml($id));
+ }
+ }
+
function test_ml_imgresize_array_external() {
global $conf;
$conf['useslash'] = 0;
@@ -107,8 +126,24 @@ class common_ml_test extends DokuWikiTest {
$tok = media_get_token($id, $w, 0);
$hash = substr(PassHash::hmac('md5', $id, auth_cookiesalt()), 0, 6);
- $expect = DOKU_BASE.$this->script.'?hash='.$hash.'&amp;w='.$w.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
+ $expect = DOKU_BASE.$this->script.'?w='.$w.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
$this->assertEquals($expect, ml($id, $args));
}
+
+ $h = 50;
+ $args = array('h' => $h);
+ $tok = media_get_token($id, $h, 0);
+
+ $expect = DOKU_BASE.$this->script.'?h='.$h.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
+ $this->assertEquals($expect, ml($id, $args));
+
+ $w = 80;
+ $h = 50;
+ $args = array('w' => $w, 'h' => $h);
+ $tok = media_get_token($id, $w, $h);
+
+ $expect = DOKU_BASE.$this->script.'?w='.$w.'&amp;h='.$h.'&amp;tok='.$tok.'&amp;media='.rawurlencode($id);
+ $this->assertEquals($expect, ml($id, $args));
+
}
}
diff --git a/_test/tests/inc/fulltext_backlinks.test.php b/_test/tests/inc/fulltext_backlinks.test.php
new file mode 100644
index 000000000..058e13498
--- /dev/null
+++ b/_test/tests/inc/fulltext_backlinks.test.php
@@ -0,0 +1,77 @@
+<?php
+
+// must be run within Dokuwiki
+if (!defined('DOKU_INC')) die();
+
+/**
+ * Test cases for the link index
+ *
+ * @author Michael Hamann <michael@content-space.de>
+ */
+class fultext_backlinks_test extends DokuWikiTest {
+
+ public function test_internallink() {
+ saveWikiText('test:internallinks', '[[internälLink]] [[..:internal link]]', 'Test initialization');
+ idx_addPage('test:internallinks');
+
+ $this->assertEquals(array('test:internallinks'), ft_backlinks('internal_link'));
+ $this->assertEquals(array('test:internallinks'), ft_backlinks('test:internaellink'));
+ }
+
+ public function test_links_in_footnotes() {
+ saveWikiText('test:link_footnotes', '(([[footnote]] [[:foÖtnotel]]))', 'Test initialization');
+ idx_addPage('test:link_footnotes');
+
+ $this->assertEquals(array('test:link_footnotes'), ft_backlinks('test:footnote'));
+ $this->assertEquals(array('test:link_footnotes'), ft_backlinks('fooetnotel'));
+ }
+
+ public function test_links_in_hidden_pages() {
+ global $conf;
+ $conf['hidepages'] = 'hidden:.*';
+ saveWikiText('hidden:links', '[[wiki:hiddenlink|linktitle]]', 'Test initialization');
+ idx_addPage('hidden:links');
+ saveWikiText('visible:links', '[[wiki:hiddenlink]]', 'Test initialization');
+ idx_addPage('visible:links');
+
+ $this->assertEquals(array('visible:links'), ft_backlinks('wiki:hiddenlink'));
+ $this->assertEquals(array('visible:links'), ft_backlinks('wiki:hiddenlink', false));
+ $this->assertEquals(array('hidden:links', 'visible:links'), ft_backlinks('wiki:hiddenlink', true));
+ }
+
+ public function test_links_in_protected_pages() {
+ global $conf;
+ global $AUTH_ACL;
+ $conf['superuser'] = 'alice';
+ $conf['useacl'] = 1;
+
+ $AUTH_ACL = array(
+ '* @ALL 8',
+ 'secret:* @ALL 0',
+ );
+
+ $_SERVER['REMOTE_USER'] = 'eve';
+
+ saveWikiText('secret:links', '[[wiki:secretlink]]', 'Test initialization');
+ idx_addPage('secret:links');
+ saveWikiText('public:links', '[[wiki:secretlink]]', 'Test initialization');
+ idx_addPage('public:links');
+
+ $this->assertEquals(array('public:links'), ft_backlinks('wiki:secretlink'));
+ $this->assertEquals(array('public:links'), ft_backlinks('wiki:secretlink', false));
+ $this->assertEquals(array('public:links', 'secret:links'), ft_backlinks('wiki:secretlink', true));
+ }
+
+ public function test_links_in_deleted_pages() {
+ saveWikiText('test:internallinks', '[[internallink]] [[..:internal link]]', 'Test initialization');
+ idx_addPage('test:internallinks');
+
+ $this->assertEquals(array('test:internallinks'), ft_backlinks('test:internallink'));
+ $this->assertEquals(array('test:internallinks'), ft_backlinks('internal_link'));
+
+ saveWikiText('test:internallinks', '', 'Deleted');
+
+ $this->assertEquals(array(), ft_backlinks('test:internallink'));
+ $this->assertEquals(array(), ft_backlinks('internal_link'));
+ }
+}
diff --git a/_test/tests/inc/fulltext_mediause.test.php b/_test/tests/inc/fulltext_mediause.test.php
new file mode 100644
index 000000000..9d5b2dc84
--- /dev/null
+++ b/_test/tests/inc/fulltext_mediause.test.php
@@ -0,0 +1,77 @@
+<?php
+
+// must be run within Dokuwiki
+if (!defined('DOKU_INC')) die();
+
+/**
+ * Test cases for the media usage index
+ *
+ * @author Michael Hamann <michael@content-space.de>
+ */
+class fultext_mediause_test extends DokuWikiTest {
+
+ public function test_internalmedia() {
+ saveWikiText('test:internalmedia_usage', '{{internalmedia.png}} {{..:internal media.png}}', 'Test initialization');
+ idx_addPage('test:internalmedia_usage');
+
+ $this->assertEquals(array('test:internalmedia_usage'), ft_mediause('internal_media.png'));
+ $this->assertEquals(array('test:internalmedia_usage'), ft_mediause('test:internalmedia.png'));
+ }
+
+ public function test_media_in_links() {
+ saveWikiText('test:medialinks', '[[doku>wiki:dokuwiki|{{wiki:logo.png}}]] [[http://www.example.com|{{example.png?200x800}}]]', 'Test init');
+ idx_addPage('test:medialinks');
+
+ $this->assertEquals(array('test:medialinks'), ft_mediause('wiki:logo.png'));
+ $this->assertEquals(array('test:medialinks'), ft_mediause('test:example.png'));
+ }
+
+ public function test_media_in_footnotes() {
+ saveWikiText('test:media_footnotes', '(({{footnote.png?20x50}} [[foonote|{{:footlink.png}}]]))', 'Test initialization');
+ idx_addPage('test:media_footnotes');
+
+ $this->assertEquals(array('test:media_footnotes'), ft_mediause('test:footnote.png'));
+ $this->assertEquals(array('test:media_footnotes'), ft_mediause('footlink.png'));
+ }
+
+ public function test_media_in_hidden_pages() {
+ global $conf;
+ $conf['hidepages'] = 'hidden:.*';
+ saveWikiText('hidden:medias', '[[doku>wiki:dokuwiki|{{wiki:hiddenlogo.png}}]]', 'Test initialization');
+ idx_addPage('hidden:medias');
+
+ $this->assertEquals(array(), ft_mediause('wiki:hiddenlogo.png'));
+ $this->assertEquals(array(), ft_mediause('wiki:hiddenlogo.png', false));
+ $this->assertEquals(array('hidden:medias'), ft_mediause('wiki:hiddenlogo.png', true));
+ }
+
+ public function test_media_in_protected_pages() {
+ global $conf;
+ global $AUTH_ACL;
+ $conf['superuser'] = 'alice';
+ $conf['useacl'] = 1;
+
+ $AUTH_ACL = array(
+ '* @ALL 8',
+ 'secret:* @ALL 0',
+ );
+
+ $_SERVER['REMOTE_USER'] = 'eve';
+
+ saveWikiText('secret:medias', '[[doku>wiki:dokuwiki|{{wiki:secretlogo.png}}]]', 'Test initialization');
+ idx_addPage('secret:medias');
+
+ $this->assertEquals(array(), ft_mediause('wiki:secretlogo.png'));
+ $this->assertEquals(array(), ft_mediause('wiki:secretlogo.png', false));
+ $this->assertEquals(array('secret:medias'), ft_mediause('wiki:secretlogo.png', true));
+ }
+
+ public function test_media_in_deleted_pages() {
+ saveWikiText('test:internalmedia_usage', '{{internalmedia.png}} {{..:internal media.png}}', 'Test initialization');
+ idx_addPage('test:internalmedia_usage');
+ saveWikiText('test:internalmedia_usage', '', 'Deleted');
+
+ $this->assertEquals(array(), ft_mediause('internal_media.png'));
+ $this->assertEquals(array(), ft_mediause('test:internalmedia.png'));
+ }
+}
diff --git a/_test/tests/inc/httpclient_http.test.php b/_test/tests/inc/httpclient_http.test.php
index 387eb53aa..43dd4478f 100644
--- a/_test/tests/inc/httpclient_http.test.php
+++ b/_test/tests/inc/httpclient_http.test.php
@@ -122,9 +122,14 @@ class httpclient_http_test extends DokuWikiTest {
function test_maxbody(){
$http = new HTTPClient();
$http->max_bodysize = 250;
+
+ // this should abort completely
$data = $http->get($this->server.'/stream/30');
$this->assertTrue($data === false, 'HTTP response');
+
+ // this should read just the needed bytes
$http->max_bodysize_abort = false;
+ $http->keep_alive = false;
$data = $http->get($this->server.'/stream/30');
$this->assertFalse($data === false, 'HTTP response');
/* should read no more than max_bodysize+1 */
@@ -215,5 +220,55 @@ class httpclient_http_test extends DokuWikiTest {
$data = $http->get('http://www.wikimatrix.org/cfeed/dokuwiki/-/-');
$this->assertTrue($data !== false, $http->error);
}
+
+ function test_postencode(){
+ $http = new HTTPClient();
+
+
+ // check simple data
+ $data = array(
+ 'öä?' => 'öä?',
+ 'foo' => 'bang'
+ );
+ $this->assertEquals(
+ '%C3%B6%C3%A4%3F=%C3%B6%C3%A4%3F&foo=bang',
+ $http->_postEncode($data),
+ 'simple'
+ );
+
+ // check first level numeric array
+ $data = array(
+ 'foo' => 'bang',
+ 'ärr' => array('ö', 'b', 'c')
+ );
+ $this->assertEquals(
+ 'foo=bang&%C3%A4rr%5B0%5D=%C3%B6&%C3%A4rr%5B1%5D=b&%C3%A4rr%5B2%5D=c',
+ $http->_postEncode($data),
+ 'onelevelnum'
+ );
+
+ // check first level associative array
+ $data = array(
+ 'foo' => 'bang',
+ 'ärr' => array('ö'=>'ä', 'b' => 'c')
+ );
+ $this->assertEquals(
+ 'foo=bang&%C3%A4rr%5B%C3%B6%5D=%C3%A4&%C3%A4rr%5Bb%5D=c',
+ $http->_postEncode($data),
+ 'onelevelassoc'
+ );
+
+
+ // check first level associative array
+ $data = array(
+ 'foo' => 'bang',
+ 'ärr' => array('ö'=>'ä', 'ä' => array('ö'=>'ä'))
+ );
+ $this->assertEquals(
+ 'foo=bang&%C3%A4rr%5B%C3%B6%5D=%C3%A4&%C3%A4rr%5B%C3%A4%5D%5B%C3%B6%5D=%C3%A4',
+ $http->_postEncode($data),
+ 'twolevelassoc'
+ );
+ }
}
//Setup VIM: ex: et ts=4 :
diff --git a/_test/tests/inc/parser/parser_code.test.php b/_test/tests/inc/parser/parser_code.test.php
new file mode 100644
index 000000000..c50d2d328
--- /dev/null
+++ b/_test/tests/inc/parser/parser_code.test.php
@@ -0,0 +1,72 @@
+<?php
+require_once 'parser.inc.php';
+
+class TestOfDoku_Parser_Code extends TestOfDoku_Parser {
+
+ function setUp() {
+ parent::setUp();
+ $this->P->addMode('code',new Doku_Parser_Mode_Code());
+ }
+
+ function testCode() {
+ $this->P->parse('Foo <code>Test</code> Bar');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo ')),
+ array('p_close',array()),
+ array('code',array('Test',null,null)),
+ array('p_open',array()),
+ array('cdata',array(' Bar')),
+ array('p_close',array()),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
+ function testCodeBash() {
+ $this->P->parse('Foo <code bash>Test</code> Bar');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo ')),
+ array('p_close',array()),
+ array('code',array('Test','bash',null)),
+ array('p_open',array()),
+ array('cdata',array(' Bar')),
+ array('p_close',array()),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
+ function testCodeDownload() {
+ $this->P->parse('Foo <code bash script.sh>Test</code> Bar');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo ')),
+ array('p_close',array()),
+ array('code',array('Test','bash','script.sh')),
+ array('p_open',array()),
+ array('cdata',array(' Bar')),
+ array('p_close',array()),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
+ function testCodeToken() {
+ $this->P->parse('Foo <code2>Bar</code2><code>Test</code>');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo <code2>Bar</code2>')),
+ array('p_close',array()),
+ array('code',array('Test',null,null)),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+}
+
diff --git a/_test/tests/inc/parser/parser_file.test.php b/_test/tests/inc/parser/parser_file.test.php
new file mode 100644
index 000000000..39bda8a58
--- /dev/null
+++ b/_test/tests/inc/parser/parser_file.test.php
@@ -0,0 +1,56 @@
+<?php
+require_once 'parser.inc.php';
+
+class TestOfDoku_Parser_File extends TestOfDoku_Parser {
+
+ function setUp() {
+ parent::setUp();
+ $this->P->addMode('file',new Doku_Parser_Mode_File());
+ }
+
+ function testFile() {
+ $this->P->parse('Foo <file>Test</file> Bar');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo ')),
+ array('p_close',array()),
+ array('file',array('Test',null,null)),
+ array('p_open',array()),
+ array('cdata',array(' Bar')),
+ array('p_close',array()),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
+ function testFileHighlightDownload() {
+ $this->P->parse('Foo <file txt test.txt>Test</file> Bar');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo ')),
+ array('p_close',array()),
+ array('file',array('Test','txt','test.txt')),
+ array('p_open',array()),
+ array('cdata',array(' Bar')),
+ array('p_close',array()),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
+ function testFileToken() {
+ $this->P->parse('Foo <file2>Test</file2> Bar');
+ $calls = array (
+ array('document_start',array()),
+ array('p_open',array()),
+ array('cdata',array("\n".'Foo <file2>Test</file2> Bar')),
+ array('p_close',array()),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
+}
+
diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php
index 90bc2e49e..9801ca1e0 100644
--- a/_test/tests/inc/tar.test.php
+++ b/_test/tests/inc/tar.test.php
@@ -11,7 +11,8 @@ class Tar_TestCase extends DokuWikiTest {
public function test_createdynamic() {
$tar = new Tar();
- $dir = dirname(__FILE__).'/tar';
+ $dir = dirname(__FILE__).'/tar';
+ $tdir = ltrim($dir,'/');
$tar->create();
$tar->AddFile("$dir/testdata1.txt");
@@ -24,11 +25,17 @@ class Tar_TestCase extends DokuWikiTest {
$this->assertTrue(strpos($data, 'testcontent2') !== false, 'Content in TAR');
$this->assertTrue(strpos($data, 'testcontent3') !== false, 'Content in TAR');
- $this->assertTrue(strpos($data, "$dir/testdata1.txt") !== false, 'Path in TAR');
+ // fullpath might be too long to be stored as full path FS#2802
+ $this->assertTrue(strpos($data, "$tdir") !== false, 'Path in TAR');
+ $this->assertTrue(strpos($data, "testdata1.txt") !== false, 'File in TAR');
+
$this->assertTrue(strpos($data, 'noway/testdata2.txt') !== false, 'Path in TAR');
$this->assertTrue(strpos($data, 'another/testdata3.txt') !== false, 'Path in TAR');
- $this->assertTrue(strpos($data, "$dir/foobar/testdata2.txt") === false, 'Path not in TAR');
+ // fullpath might be too long to be stored as full path FS#2802
+ $this->assertTrue(strpos($data, "$tdir/foobar") === false, 'Path not in TAR');
+ $this->assertTrue(strpos($data, "foobar.txt") === false, 'File not in TAR');
+
$this->assertTrue(strpos($data, "foobar") === false, 'Path not in TAR');
}
@@ -42,6 +49,7 @@ class Tar_TestCase extends DokuWikiTest {
$tar = new Tar();
$dir = dirname(__FILE__).'/tar';
+ $tdir = ltrim($dir,'/');
$tmp = tempnam(sys_get_temp_dir(), 'dwtartest');
$tar->create($tmp, Tar::COMPRESS_NONE);
@@ -57,11 +65,17 @@ class Tar_TestCase extends DokuWikiTest {
$this->assertTrue(strpos($data, 'testcontent2') !== false, 'Content in TAR');
$this->assertTrue(strpos($data, 'testcontent3') !== false, 'Content in TAR');
- $this->assertTrue(strpos($data, "$dir/testdata1.txt") !== false, 'Path in TAR');
+ // fullpath might be too long to be stored as full path FS#2802
+ $this->assertTrue(strpos($data, "$tdir") !== false, 'Path in TAR');
+ $this->assertTrue(strpos($data, "testdata1.txt") !== false, 'File in TAR');
+
$this->assertTrue(strpos($data, 'noway/testdata2.txt') !== false, 'Path in TAR');
$this->assertTrue(strpos($data, 'another/testdata3.txt') !== false, 'Path in TAR');
- $this->assertTrue(strpos($data, "$dir/foobar/testdata2.txt") === false, 'Path not in TAR');
+ // fullpath might be too long to be stored as full path FS#2802
+ $this->assertTrue(strpos($data, "$tdir/foobar") === false, 'Path not in TAR');
+ $this->assertTrue(strpos($data, "foobar.txt") === false, 'File not in TAR');
+
$this->assertTrue(strpos($data, "foobar") === false, 'Path not in TAR');
@unlink($tmp);
@@ -248,6 +262,28 @@ class Tar_TestCase extends DokuWikiTest {
}
}
+ // FS#1442
+ public function test_createlongfile() {
+ $tar = new Tar();
+ $tmp = tempnam(sys_get_temp_dir(), 'dwtartest');
+
+ $path = '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt';
+
+ $tar->create($tmp, Tar::COMPRESS_NONE);
+ $tar->addData($path, 'testcontent1');
+ $tar->close();
+
+ $this->assertTrue(filesize($tmp) > 30); //arbitrary non-zero number
+ $data = file_get_contents($tmp);
+
+ // We should find the complete path and a longlink entry
+ $this->assertTrue(strpos($data, 'testcontent1') !== false, 'content in TAR');
+ $this->assertTrue(strpos($data, $path) !== false, 'path in TAR');
+ $this->assertTrue(strpos($data, '@LongLink') !== false, '@LongLink in TAR');
+
+ @unlink($tmp);
+ }
+
public function test_createlongpathustar() {
$tar = new Tar();
$tmp = tempnam(sys_get_temp_dir(), 'dwtartest');
@@ -360,4 +396,4 @@ class Tar_TestCase extends DokuWikiTest {
$this->assertEquals(512*4, strlen($file)); // 1 header block + data block + 2 footer blocks
}
-} \ No newline at end of file
+}
diff --git a/_test/tests/lib/exe/fetch_imagetoken.test.php b/_test/tests/lib/exe/fetch_imagetoken.test.php
index 9e5b6e4a2..99e642557 100644
--- a/_test/tests/lib/exe/fetch_imagetoken.test.php
+++ b/_test/tests/lib/exe/fetch_imagetoken.test.php
@@ -23,10 +23,10 @@ class fetch_imagetoken_test extends DokuWikiTest {
parent::setUp();
global $conf;
- $conf['sendfile'] = 0;
+ $conf['xsendfile'] = 0;
global $MIME, $EXT, $CACHE, $INPUT; // variables fetch creates in global scope -- should this be in fetch?
- }
+ }
function getUri() {
$w = $this->width ? 'w='.$this->width.'&' : '';
@@ -39,14 +39,14 @@ class fetch_imagetoken_test extends DokuWikiTest {
$request = new TestRequest();
return $request->get(array(),str_replace('{%token%}',$token,$this->getUri()));
}
-
- /**
+
+ /**
* modified image request with valid token
* expect: header with mime-type
* expect: content
* expect: no error response
- */
- function test_valid_token(){
+ */
+ function test_valid_token(){
$valid_token = 'tok='.media_get_token($this->media, $this->width, $this->height).'&';
$response = $this->fetchResponse($valid_token);
$this->assertTrue((bool)$response->getHeader('Content-Type'));
@@ -54,24 +54,24 @@ class fetch_imagetoken_test extends DokuWikiTest {
$status_code = $response->getStatusCode();
$this->assertTrue(is_null($status_code) || (200 == $status_code));
- }
-
- /**
+ }
+
+ /**
* modified image request with invalid token
- * expect: 412 status code
- */
- function test_invalid_token(){
- $invalid_token = 'tok='.media_get_token('junk',200,100).'&';
- $this->assertEquals(412,$this->fetchResponse($invalid_token)->getStatusCode());
- }
-
- /**
- * modified image request with no token
* expect: 412 status code
- */
- function test_missing_token(){
- $no_token = '';
- $this->assertEquals(412,$this->fetchResponse($notoken)->getStatusCode());
+ */
+ function test_invalid_token(){
+ $invalid_token = 'tok='.media_get_token('junk',200,100).'&';
+ $this->assertEquals(412,$this->fetchResponse($invalid_token)->getStatusCode());
+ }
+
+ /**
+ * modified image request with no token
+ * expect: 412 status code
+ */
+ function test_missing_token(){
+ $no_token = '';
+ $this->assertEquals(412,$this->fetchResponse($no_token)->getStatusCode());
}
/**
diff --git a/_test/tests/lib/exe/fetch_statuscodes_external.test.php b/_test/tests/lib/exe/fetch_statuscodes_external.test.php
new file mode 100644
index 000000000..79a45ec93
--- /dev/null
+++ b/_test/tests/lib/exe/fetch_statuscodes_external.test.php
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * @group internet
+ */
+class fetch_statuscodes_external_test extends DokuWikiTest {
+
+ private $media = 'http://www.google.com/images/srpr/logo3w.png'; //used in media_get_from_url test too
+ private $width = 200;
+ private $height = 0;
+
+ function setUp() {
+
+ header('X-Test: check headers working');
+ $header_check = function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list();
+ if(empty($header_check)) {
+ $this->markTestSkipped('headers not returned, perhaps your sapi does not return headers, try xdebug');
+ } else {
+ header_remove('X-Test');
+ }
+
+ parent::setUp();
+
+ global $conf;
+ $conf['fetchsize'] = 500 * 1024; //500kb
+ $conf['xsendfile'] = 0;
+
+ global $MIME, $EXT, $CACHE, $INPUT; // variables fetch creates in global scope -- should this be in fetch?
+ }
+
+ function getUri() {
+ $w = $this->width ? 'w='.$this->width.'&' : '';
+ $h = $this->height ? 'h='.$this->height.'&' : '';
+ return '/lib/exe/fetch.php?'.$w.$h.'{%token%}media='.rawurlencode($this->media);
+ }
+
+ function fetchResponse($token) {
+ $request = new TestRequest();
+ return $request->get(array(), str_replace('{%token%}', $token, $this->getUri()));
+ }
+
+ /**
+ * modified image request with valid token
+ * and not-modified image request with valid token
+ *
+ * expect: header with mime-type
+ * expect: content
+ * expect: no error response
+ */
+ function test_valid_token() {
+ $valid_token_resize = 'tok='.media_get_token($this->media, $this->width, $this->height).'&';
+
+ $this->handlevalidresponse($valid_token_resize);
+
+ //original size
+ $this->width = $this->height = 0;
+ $valid_token_original = 'tok='.media_get_token($this->media, $this->width, $this->height).'&';
+
+ $this->handlevalidresponse($valid_token_original);
+
+ }
+
+ /**
+ * Performs asserts for valid request
+ *
+ * @param $valid_token
+ */
+ private function handlevalidresponse($valid_token){
+ $response = $this->fetchResponse($valid_token);
+ $this->assertTrue((bool) $response->getHeader('Content-Type'));
+ $this->assertTrue((bool) ($response->getContent()));
+
+ $status_code = $response->getStatusCode();
+ $this->assertTrue(is_null($status_code) || (200 == $status_code));
+ }
+
+ /**
+ * modified image request with invalid token
+ * expect: 412 status code
+ */
+ function test_invalid_token() {
+ $invalid_tokens = array(
+ 'invalid_token_wrongid' => media_get_token('junk', 200, 100),
+ 'invalid_token_wrongh' => media_get_token($this->media, 200, 10),
+ 'invalid_token_wrongw' => media_get_token($this->media, 20, 100),
+ 'invalid_token_wrongwh' => media_get_token($this->media, 20, 10)
+ );
+ foreach($invalid_tokens as $invalid_token)
+ $this->assertEquals(412, $this->fetchResponse('tok='.$invalid_token.'&')->getStatusCode());
+
+ }
+
+ /**
+ * modified image request with no token
+ * and not modified image with no token
+ * expect: 412 status code
+ */
+ function test_missing_token() {
+ $no_token = '';
+
+ $this->assertEquals(412, $this->fetchResponse($no_token)->getStatusCode());
+
+ $this->width = $this->height = 0;
+ $this->assertEquals(412, $this->fetchResponse($no_token)->getStatusCode());
+ }
+}
+//Setup VIM: ex: et ts=4 :
diff --git a/conf/dokuwiki.php b/conf/dokuwiki.php
index f5524de6b..bdc9739d1 100644
--- a/conf/dokuwiki.php
+++ b/conf/dokuwiki.php
@@ -96,7 +96,6 @@ $conf['target']['windows'] = '';
/* Media Settings */
$conf['mediarevisions'] = 1; //enable/disable media revisions
$conf['refcheck'] = 1; //check for references before deleting media files
-$conf['refshow'] = 0; //how many references should be shown, 5 is a good value
$conf['gdlib'] = 2; //the GDlib version (0, 1 or 2) 2 tries to autodetect
$conf['im_convert'] = ''; //path to ImageMagicks convert (will be used instead of GD)
$conf['jpg_quality'] = '70'; //quality of compression when scaling jpg images (0-100)
diff --git a/data/pages/wiki/dokuwiki.txt b/data/pages/wiki/dokuwiki.txt
index 2db4dbef3..808aea68a 100644
--- a/data/pages/wiki/dokuwiki.txt
+++ b/data/pages/wiki/dokuwiki.txt
@@ -1,6 +1,6 @@
====== DokuWiki ======
-[[doku>wiki:dokuwiki|{{wiki:dokuwiki-128.png }}]] DokuWiki is a standards compliant, simple to use [[wp>Wiki]], mainly aimed at creating documentation of any kind. It is targeted at developer teams, workgroups and small companies. It has a simple but powerful [[wiki:syntax]] which makes sure the datafiles remain readable outside the Wiki and eases the creation of structured texts. All data is stored in plain text files -- no database is required.
+[[doku>wiki:dokuwiki|{{wiki:dokuwiki-128.png }}]] DokuWiki is a simple to use and highly versatile Open Source [[wp>wiki]] software that doesn't require a database. It is loved by users for its clean and readable [[wiki:syntax]]. The ease of maintenance, backup and integration makes it an administrator's favorite. Built in [[doku>acl|access controls]] and [[doku>auth|authentication connectors]] make DokuWiki especially useful in the enterprise context and the large number of [[doku>plugins]] contributed by its vibrant community allow for a broad range of use cases beyond a traditional wiki.
Read the [[doku>manual|DokuWiki Manual]] to unleash the full power of DokuWiki.
diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index 0d7b80cf8..b2621bdbb 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -463,6 +463,8 @@ class HTTPClient {
}
$r_body = $this->_readData($socket, $length, 'response (content-length limited)', true);
+ }elseif( !isset($this->resp_headers['transfer-encoding']) && $this->max_bodysize && !$this->keep_alive){
+ $r_body = $this->_readData($socket, $this->max_bodysize, 'response (content-length limited)', true);
}else{
// read entire socket
$r_size = 0;
@@ -806,12 +808,7 @@ class HTTPClient {
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _postEncode($data){
- $url = '';
- foreach($data as $key => $val){
- if($url) $url .= '&';
- $url .= urlencode($key).'='.urlencode($val);
- }
- return $url;
+ return http_build_query($data,'','&');
}
/**
diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php
index 61bd74939..607661a22 100644
--- a/inc/PassHash.class.php
+++ b/inc/PassHash.class.php
@@ -98,7 +98,7 @@ class PassHash {
$salt = '';
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
for($i = 0; $i < $len; $i++) {
- $salt .= $chars[mt_rand(0, 61)];
+ $salt .= $chars[auth_random(0, 61)];
}
return $salt;
}
diff --git a/inc/actions.php b/inc/actions.php
index da3414eb2..bf124c887 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -92,14 +92,26 @@ function act_dispatch(){
$ACT = 'login';
}
- //update user profile
- if ($ACT == 'profile') {
+ // user profile changes
+ if (in_array($ACT, array('profile','profile_delete'))) {
if(!$_SERVER['REMOTE_USER']) {
$ACT = 'login';
} else {
- if(updateprofile()) {
- msg($lang['profchanged'],1);
- $ACT = 'show';
+ switch ($ACT) {
+ case 'profile' :
+ if(updateprofile()) {
+ msg($lang['profchanged'],1);
+ $ACT = 'show';
+ }
+ break;
+ case 'profile_delete' :
+ if(auth_deleteprofile()){
+ msg($lang['profdeleted'],1);
+ $ACT = 'show';
+ } else {
+ $ACT = 'profile';
+ }
+ break;
}
}
}
@@ -247,7 +259,7 @@ function act_validate($act) {
//disable all acl related commands if ACL is disabled
if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
'subscribe','unsubscribe','profile','revert',
- 'resendpwd'))){
+ 'resendpwd','profile_delete'))){
msg('Command unavailable: '.htmlspecialchars($act),-1);
return 'show';
}
@@ -258,7 +270,7 @@ function act_validate($act) {
if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
'preview','search','show','check','index','revisions',
'diff','recent','backlink','admin','subscribe','revert',
- 'unsubscribe','profile','resendpwd','recover',
+ 'unsubscribe','profile','profile_delete','resendpwd','recover',
'draftdel','sitemap','media')) && substr($act,0,7) != 'export_' ) {
msg('Command unknown: '.htmlspecialchars($act),-1);
return 'show';
@@ -287,7 +299,7 @@ function act_permcheck($act){
}else{
$permneed = AUTH_CREATE;
}
- }elseif(in_array($act,array('login','search','recent','profile','index', 'sitemap'))){
+ }elseif(in_array($act,array('login','search','recent','profile','profile_delete','index', 'sitemap'))){
$permneed = AUTH_NONE;
}elseif($act == 'revert'){
$permneed = AUTH_ADMIN;
diff --git a/inc/auth.php b/inc/auth.php
index 47b29eff7..be6b7ebbe 100644
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -40,7 +40,7 @@ function auth_setup() {
global $INPUT;
global $AUTH_ACL;
global $lang;
- global $config_cascade;
+ /* @var Doku_Plugin_Controller $plugin_controller */
global $plugin_controller;
$AUTH_ACL = array();
@@ -207,7 +207,7 @@ function auth_login($user, $pass, $sticky = false, $silent = false) {
global $USERINFO;
global $conf;
global $lang;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
$sticky ? $sticky = true : $sticky = false; //sanity check
@@ -219,8 +219,8 @@ function auth_login($user, $pass, $sticky = false, $silent = false) {
if($auth->checkPass($user, $pass)) {
// make logininfo globally available
$_SERVER['REMOTE_USER'] = $user;
- $secret = auth_cookiesalt(!$sticky); //bind non-sticky to session
- auth_setCookie($user, PMA_blowfish_encrypt($pass, $secret), $sticky);
+ $secret = auth_cookiesalt(!$sticky, true); //bind non-sticky to session
+ auth_setCookie($user, auth_encrypt($pass, $secret), $sticky);
return true;
} else {
//invalid credentials - log off
@@ -250,8 +250,8 @@ function auth_login($user, $pass, $sticky = false, $silent = false) {
return true;
}
// no we don't trust it yet - recheck pass but silent
- $secret = auth_cookiesalt(!$sticky); //bind non-sticky to session
- $pass = PMA_blowfish_decrypt($pass, $secret);
+ $secret = auth_cookiesalt(!$sticky, true); //bind non-sticky to session
+ $pass = auth_decrypt($pass, $secret);
return auth_login($user, $pass, $sticky, true);
}
}
@@ -294,7 +294,7 @@ function auth_validateToken($token) {
* @return string The auth token
*/
function auth_createToken() {
- $token = md5(mt_rand());
+ $token = md5(auth_randombytes(16));
@session_start(); // reopen the session if needed
$_SESSION[DOKU_COOKIE]['auth']['token'] = $token;
session_write_close();
@@ -333,14 +333,18 @@ function auth_browseruid() {
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param bool $addsession if true, the sessionid is added to the salt
+ * @param bool $secure if security is more important than keeping the old value
* @return string
*/
-function auth_cookiesalt($addsession = false) {
+function auth_cookiesalt($addsession = false, $secure = false) {
global $conf;
$file = $conf['metadir'].'/_htcookiesalt';
+ if ($secure || !file_exists($file)) {
+ $file = $conf['metadir'].'/_htcookiesalt2';
+ }
$salt = io_readFile($file);
if(empty($salt)) {
- $salt = uniqid(rand(), true);
+ $salt = bin2hex(auth_randombytes(64));
io_saveFile($file, $salt);
}
if($addsession) {
@@ -350,6 +354,143 @@ function auth_cookiesalt($addsession = false) {
}
/**
+ * Return truly (pseudo) random bytes if available, otherwise fall back to mt_rand
+ *
+ * @author Mark Seecof
+ * @author Michael Hamann <michael@content-space.de>
+ * @link http://www.php.net/manual/de/function.mt-rand.php#83655
+ * @param int $length number of bytes to get
+ * @return string binary random strings
+ */
+function auth_randombytes($length) {
+ $strong = false;
+ $rbytes = false;
+
+ if (function_exists('openssl_random_pseudo_bytes')
+ && (version_compare(PHP_VERSION, '5.3.4') >= 0
+ || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
+ ) {
+ $rbytes = openssl_random_pseudo_bytes($length, $strong);
+ }
+
+ if (!$strong && function_exists('mcrypt_create_iv')
+ && (version_compare(PHP_VERSION, '5.3.7') >= 0
+ || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
+ ) {
+ $rbytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
+ if ($rbytes !== false && strlen($rbytes) === $length) {
+ $strong = true;
+ }
+ }
+
+
+ // If no strong randoms available, try OS the specific ways
+ if(!$strong) {
+ // Unix/Linux platform
+ $fp = @fopen('/dev/urandom', 'rb');
+ if($fp !== false) {
+ $rbytes = fread($fp, $length);
+ fclose($fp);
+ }
+
+ // MS-Windows platform
+ if(class_exists('COM')) {
+ // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
+ try {
+ $CAPI_Util = new COM('CAPICOM.Utilities.1');
+ $rbytes = $CAPI_Util->GetRandom($length, 0);
+
+ // if we ask for binary data PHP munges it, so we
+ // request base64 return value.
+ if($rbytes) $rbytes = base64_decode($rbytes);
+ } catch(Exception $ex) {
+ // fail
+ }
+ }
+ }
+ if(strlen($rbytes) < $length) $rbytes = false;
+
+ // still no random bytes available - fall back to mt_rand()
+ if($rbytes === false) {
+ $rbytes = '';
+ for ($i = 0; $i < $length; ++$i) {
+ $rbytes .= chr(mt_rand(0, 255));
+ }
+ }
+
+ return $rbytes;
+}
+
+/**
+ * Random number generator using the best available source
+ *
+ * @author Michael Samuel
+ * @author Michael Hamann <michael@content-space.de>
+ * @param int $min
+ * @param int $max
+ * @return int
+ */
+function auth_random($min, $max) {
+ $abs_max = $max - $min;
+
+ $nbits = 0;
+ for ($n = $abs_max; $n > 0; $n >>= 1) {
+ ++$nbits;
+ }
+
+ $mask = (1 << $nbits) - 1;
+ do {
+ $bytes = auth_randombytes(PHP_INT_SIZE);
+ $integers = unpack('Inum', $bytes);
+ $integer = $integers["num"] & $mask;
+ } while ($integer > $abs_max);
+
+ return $min + $integer;
+}
+
+/**
+ * Encrypt data using the given secret using AES
+ *
+ * The mode is CBC with a random initialization vector, the key is derived
+ * using pbkdf2.
+ *
+ * @param string $data The data that shall be encrypted
+ * @param string $secret The secret/password that shall be used
+ * @return string The ciphertext
+ */
+function auth_encrypt($data, $secret) {
+ $iv = auth_randombytes(16);
+ $cipher = new Crypt_AES();
+ $cipher->setPassword($secret);
+
+ /*
+ this uses the encrypted IV as IV as suggested in
+ http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, Appendix C
+ for unique but necessarily random IVs. The resulting ciphertext is
+ compatible to ciphertext that was created using a "normal" IV.
+ */
+ return $cipher->encrypt($iv.$data);
+}
+
+/**
+ * Decrypt the given AES ciphertext
+ *
+ * The mode is CBC, the key is derived using pbkdf2
+ *
+ * @param string $ciphertext The encrypted data
+ * @param string $secret The secret/password that shall be used
+ * @return string The decrypted data
+ */
+function auth_decrypt($ciphertext, $secret) {
+ $iv = substr($ciphertext, 0, 16);
+ $cipher = new Crypt_AES();
+ $cipher->setPassword($secret);
+ $cipher->setIV($iv);
+
+ return $cipher->decrypt(substr($ciphertext, 16));
+}
+
+/**
* Log out the current user
*
* This clears all authentication data and thus log the user
@@ -361,7 +502,7 @@ function auth_cookiesalt($addsession = false) {
function auth_logoff($keepbc = false) {
global $conf;
global $USERINFO;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
// make sure the session is writable (it usually is)
@@ -407,7 +548,7 @@ function auth_logoff($keepbc = false) {
function auth_ismanager($user = null, $groups = null, $adminonly = false) {
global $conf;
global $USERINFO;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
if(!$auth) return false;
@@ -460,7 +601,7 @@ function auth_isadmin($user = null, $groups = null) {
* @return bool true for membership acknowledged
*/
function auth_isMember($memberlist, $user, array $groups) {
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
if(!$auth) return false;
@@ -526,7 +667,7 @@ function auth_quickaclcheck($id) {
function auth_aclcheck($id, $user, $groups) {
global $conf;
global $AUTH_ACL;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
// if no ACL is used always return upload rights
@@ -703,12 +844,12 @@ function auth_pwgen($foruser = '') {
//use thre syllables...
for($i = 0; $i < 3; $i++) {
- $data['password'] .= $c[mt_rand(0, strlen($c) - 1)];
- $data['password'] .= $v[mt_rand(0, strlen($v) - 1)];
- $data['password'] .= $a[mt_rand(0, strlen($a) - 1)];
+ $data['password'] .= $c[auth_random(0, strlen($c) - 1)];
+ $data['password'] .= $v[auth_random(0, strlen($v) - 1)];
+ $data['password'] .= $a[auth_random(0, strlen($a) - 1)];
}
//... and add a nice number and special
- $data['password'] .= mt_rand(10, 99).$s[mt_rand(0, strlen($s) - 1)];
+ $data['password'] .= auth_random(10, 99).$s[auth_random(0, strlen($s) - 1)];
}
$evt->advise_after();
@@ -725,7 +866,7 @@ function auth_pwgen($foruser = '') {
*/
function auth_sendPassword($user, $password) {
global $lang;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
if(!$auth) return false;
@@ -759,7 +900,7 @@ function auth_sendPassword($user, $password) {
function register() {
global $lang;
global $conf;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
global $INPUT;
@@ -828,7 +969,7 @@ function register() {
function updateprofile() {
global $conf;
global $lang;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
/* @var Input $INPUT */
global $INPUT;
@@ -883,7 +1024,7 @@ function updateprofile() {
if($conf['profileconfirm']) {
if(!$auth->checkPass($_SERVER['REMOTE_USER'], $INPUT->post->str('oldpass'))) {
- msg($lang['badlogin'], -1);
+ msg($lang['badpassconfirm'], -1);
return false;
}
}
@@ -892,7 +1033,7 @@ function updateprofile() {
// update cookie and session with the changed data
if($changes['pass']) {
list( /*user*/, $sticky, /*pass*/) = auth_getCookie();
- $pass = PMA_blowfish_encrypt($changes['pass'], auth_cookiesalt(!$sticky));
+ $pass = auth_encrypt($changes['pass'], auth_cookiesalt(!$sticky, true));
auth_setCookie($_SERVER['REMOTE_USER'], $pass, (bool) $sticky);
}
return true;
@@ -901,6 +1042,45 @@ function updateprofile() {
return false;
}
+function auth_deleteprofile(){
+ global $conf;
+ global $lang;
+ /* @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+ /* @var Input $INPUT */
+ global $INPUT;
+
+ if(!$INPUT->post->bool('delete')) return false;
+ if(!checkSecurityToken()) return false;
+
+ // action prevented or auth module disallows
+ if(!actionOK('profile_delete') || !$auth->canDo('delUser')) {
+ msg($lang['profnodelete'], -1);
+ return false;
+ }
+
+ if(!$INPUT->post->bool('confirm_delete')){
+ msg($lang['profconfdeletemissing'], -1);
+ return false;
+ }
+
+ if($conf['profileconfirm']) {
+ if(!$auth->checkPass($_SERVER['REMOTE_USER'], $INPUT->post->str('oldpass'))) {
+ msg($lang['badpassconfirm'], -1);
+ return false;
+ }
+ }
+
+ $deleted[] = $_SERVER['REMOTE_USER'];
+ if($auth->triggerUserMod('delete', array($deleted))) {
+ // force and immediate logout including removing the sticky cookie
+ auth_logoff();
+ return true;
+ }
+
+ return false;
+}
+
/**
* Send a new password
*
@@ -918,7 +1098,7 @@ function updateprofile() {
function act_resendpwd() {
global $lang;
global $conf;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
/* @var Input $INPUT */
global $INPUT;
@@ -1007,7 +1187,7 @@ function act_resendpwd() {
}
// generate auth token
- $token = md5(uniqid(mt_rand(), true)); // random secret
+ $token = md5(auth_randombytes(16)); // random secret
$tfile = $conf['cachedir'].'/'.$token{0}.'/'.$token.'.pwauth';
$url = wl('', array('do'=> 'resendpwd', 'pwauth'=> $token), true, '&');
@@ -1084,7 +1264,7 @@ function auth_verifyPassword($clear, $crypt) {
*/
function auth_setCookie($user, $pass, $sticky) {
global $conf;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
global $USERINFO;
diff --git a/inc/common.php b/inc/common.php
index 1b4d9e8e4..3312141c8 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -148,7 +148,7 @@ function pageinfo() {
$info['id'] = $ID;
$info['rev'] = $REV;
- if(isset($_SERVER['REMOTE_USER'])) {
+ if(isset($_SERVER['REMOTE_USER'])) {
$sub = new Subscription();
$info['subscribed'] = $sub->user_subscription();
} else {
@@ -474,7 +474,7 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
if(is_array($more)) {
// add token for resized images
- if($more['w'] || $more['h']){
+ if($more['w'] || $more['h'] || $isexternalimage){
$more['tok'] = media_get_token($id,$more['w'],$more['h']);
}
// strip defaults for shorter URLs
@@ -485,12 +485,13 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
$more = buildURLparams($more, $sep);
} else {
$matches = array();
- if (preg_match_all('/\b(w|h)=(\d*)\b/',$more,$matches,PREG_SET_ORDER)){
+ if (preg_match_all('/\b(w|h)=(\d*)\b/',$more,$matches,PREG_SET_ORDER) || $isexternalimage){
$resize = array('w'=>0, 'h'=>0);
foreach ($matches as $match){
$resize[$match[1]] = $match[2];
}
- $more .= $sep.'tok='.media_get_token($id,$resize['w'],$resize['h']);
+ $more .= $more === '' ? '' : $sep;
+ $more .= 'tok='.media_get_token($id,$resize['w'],$resize['h']);
}
$more = str_replace('cache=cache', '', $more); //skip default
$more = str_replace(',,', ',', $more);
@@ -506,14 +507,8 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
// external URLs are always direct without rewriting
if($isexternalimage) {
$xlink .= 'lib/exe/fetch.php';
- // add hash:
- $xlink .= '?hash='.substr(PassHash::hmac('md5', $id, auth_cookiesalt()), 0, 6);
- if($more) {
- $xlink .= $sep.$more;
- $xlink .= $sep.'media='.rawurlencode($id);
- } else {
- $xlink .= $sep.'media='.rawurlencode($id);
- }
+ $xlink .= '?'.$more;
+ $xlink .= $sep.'media='.rawurlencode($id);
return $xlink;
}
@@ -1130,7 +1125,7 @@ function saveWikiText($id, $text, $summary, $minor = false) {
// if useheading is enabled, purge the cache of all linking pages
if(useHeading('content')) {
- $pages = ft_backlinks($id);
+ $pages = ft_backlinks($id, true);
foreach($pages as $page) {
$cache = new cache_renderer($page, wikiFN($page), 'xhtml');
$cache->removeCache();
diff --git a/inc/confutils.php b/inc/confutils.php
index 404cc6050..0ac003b72 100644
--- a/inc/confutils.php
+++ b/inc/confutils.php
@@ -241,7 +241,7 @@ function getConfigFiles($type) {
*/
function actionOK($action){
static $disabled = null;
- if(is_null($disabled)){
+ if(is_null($disabled) || defined('SIMPLE_TEST')){
global $conf;
/** @var auth_basic $auth */
global $auth;
@@ -261,6 +261,9 @@ function actionOK($action){
if (is_null($auth) || !$auth->canDo('Profile')) {
$disabled[] = 'profile';
}
+ if (is_null($auth) || !$auth->canDo('delUser')) {
+ $disabled[] = 'profile_delete';
+ }
if (is_null($auth)) {
$disabled[] = 'login';
}
diff --git a/inc/feedcreator.class.php b/inc/feedcreator.class.php
index ea8cc7b15..670a1bc29 100644
--- a/inc/feedcreator.class.php
+++ b/inc/feedcreator.class.php
@@ -599,7 +599,7 @@ class FeedCreator extends HtmlDescribable {
header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".utf8_basename($filename));
header("Content-Disposition: inline; filename=".utf8_basename($filename));
- readfile($filename, "r");
+ readfile($filename);
die();
}
diff --git a/inc/fetch.functions.php b/inc/fetch.functions.php
index 53ade3555..207ad9e5f 100644
--- a/inc/fetch.functions.php
+++ b/inc/fetch.functions.php
@@ -101,8 +101,8 @@ function checkFileStatus(&$media, &$file, $rev = '', $width=0, $height=0) {
//media to local file
if(media_isexternal($media)) {
- //check hash
- if(substr(PassHash::hmac('md5', $media, auth_cookiesalt()), 0, 6) !== $INPUT->str('hash')) {
+ //check token for external image and additional for resized and cached images
+ if(media_get_token($media, $width, $height) !== $INPUT->str('tok')) {
return array(412, 'Precondition Failed');
}
//handle external images
diff --git a/inc/fulltext.php b/inc/fulltext.php
index 2f073acea..c03126994 100644
--- a/inc/fulltext.php
+++ b/inc/fulltext.php
@@ -125,17 +125,21 @@ function _ft_pageSearch(&$data) {
* Returns the backlinks for a given page
*
* Uses the metadata index.
+ *
+ * @param string $id The id for which links shall be returned
+ * @param bool $ignore_perms Ignore the fact that pages are hidden or read-protected
+ * @return array The pages that contain links to the given page
*/
-function ft_backlinks($id){
- $result = array();
-
+function ft_backlinks($id, $ignore_perms = false){
$result = idx_get_indexer()->lookupKey('relation_references', $id);
if(!count($result)) return $result;
// check ACL permissions
foreach(array_keys($result) as $idx){
- if(isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ || !page_exists($result[$idx], '', false)){
+ if(($ignore_perms !== true && (
+ isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ
+ )) || !page_exists($result[$idx], '', false)){
unset($result[$idx]);
}
}
@@ -147,42 +151,28 @@ function ft_backlinks($id){
/**
* Returns the pages that use a given media file
*
- * Does a quick lookup with the fulltext index, then
- * evaluates the instructions of the found pages
+ * Uses the relation media metadata property and the metadata index.
*
- * Aborts after $max found results
+ * Note that before 2013-07-31 the second parameter was the maximum number of results and
+ * permissions were ignored. That's why the parameter is now checked to be explicitely set
+ * to true (with type bool) in order to be compatible with older uses of the function.
+ *
+ * @param string $id The media id to look for
+ * @param bool $ignore_perms Ignore hidden pages and acls (optional, default: false)
+ * @return array A list of pages that use the given media file
*/
-function ft_mediause($id,$max){
- if(!$max) $max = 1; // need to find at least one
+function ft_mediause($id, $ignore_perms = false){
+ $result = idx_get_indexer()->lookupKey('relation_media', $id);
- $result = array();
+ if(!count($result)) return $result;
- // quick lookup of the mediafile
- // FIXME use metadata key lookup
- $media = noNS($id);
- $matches = idx_lookup(idx_tokenizer($media));
- $docs = array_keys(ft_resultCombine(array_values($matches)));
- if(!count($docs)) return $result;
-
- // go through all found pages
- $found = 0;
- $pcre = preg_quote($media,'/');
- foreach($docs as $doc){
- $ns = getNS($doc);
- preg_match_all('/\{\{([^|}]*'.$pcre.'[^|}]*)(|[^}]+)?\}\}/i',rawWiki($doc),$matches);
- foreach($matches[1] as $img){
- $img = trim($img);
- if(media_isexternal($img)) continue; // skip external images
- list($img) = explode('?',$img); // remove any parameters
- resolve_mediaid($ns,$img,$exists); // resolve the possibly relative img
-
- if($img == $id){ // we have a match
- $result[] = $doc;
- $found++;
- break;
- }
+ // check ACL permissions
+ foreach(array_keys($result) as $idx){
+ if(($ignore_perms !== true && (
+ isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ
+ )) || !page_exists($result[$idx], '', false)){
+ unset($result[$idx]);
}
- if($found >= $max) break;
}
sort($result);
diff --git a/inc/html.php b/inc/html.php
index fb39fcb3c..96c4eaa1a 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -575,18 +575,18 @@ function html_revisions($first=0, $media_id = false){
if ($info['sum']) {
$form->addElement(form_makeOpenTag('span', array('class' => 'sum')));
if (!$media_id) $form->addElement(' – ');
- $form->addElement(htmlspecialchars($info['sum']));
+ $form->addElement('<bdi>'.htmlspecialchars($info['sum']).'</bdi>');
$form->addElement(form_makeCloseTag('span'));
}
$form->addElement(form_makeOpenTag('span', array('class' => 'user')));
if($info['user']){
- $form->addElement(editorinfo($info['user']));
+ $form->addElement('<bdi>'.editorinfo($info['user']).'</bdi>');
if(auth_ismanager()){
- $form->addElement(' ('.$info['ip'].')');
+ $form->addElement(' <bdo dir="ltr">('.$info['ip'].')</bdo>');
}
}else{
- $form->addElement($info['ip']);
+ $form->addElement('<bdo dir="ltr">'.$info['ip'].'</bdo>');
}
$form->addElement(form_makeCloseTag('span'));
@@ -774,12 +774,12 @@ function html_recent($first=0, $show_changes='both'){
$form->addElement(form_makeOpenTag('span', array('class' => 'user')));
if($recent['user']){
- $form->addElement(editorinfo($recent['user']));
+ $form->addElement('<bdi>'.editorinfo($recent['user']).'</bdi>');
if(auth_ismanager()){
- $form->addElement(' ('.$recent['ip'].')');
+ $form->addElement(' <bdo dir="ltr">('.$recent['ip'].')</bdo>');
}
}else{
- $form->addElement($recent['ip']);
+ $form->addElement('<bdo dir="ltr">'.$recent['ip'].'</bdo>');
}
$form->addElement(form_makeCloseTag('span'));
@@ -854,12 +854,17 @@ function html_index($ns){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function html_list_index($item){
- global $ID;
+ global $ID, $conf;
+
+ // prevent searchbots needlessly following links
+ $nofollow = ($ID != $conf['start'] || $conf['sitemap']) ? ' rel="nofollow"' : '';
+
$ret = '';
$base = ':'.$item['id'];
$base = substr($base,strrpos($base,':')+1);
if($item['type']=='d'){
- $ret .= '<a href="'.wl($ID,'idx='.rawurlencode($item['id'])).'" title="' . $item['id'] . '" class="idx_dir"><strong>';
+ // FS#2766, no need for search bots to follow namespace links in the index
+ $ret .= '<a href="'.wl($ID,'idx='.rawurlencode($item['id'])).'" title="' . $item['id'] . '" class="idx_dir"' . $nofollow . '><strong>';
$ret .= $base;
$ret .= '</strong></a>';
}else{
@@ -1022,52 +1027,52 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
}else{
$l_info = getRevisionInfo($id,$l_rev,true, $media);
if($l_info['user']){
- $l_user = editorinfo($l_info['user']);
- if(auth_ismanager()) $l_user .= ' ('.$l_info['ip'].')';
+ $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>';
+ if(auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>';
} else {
- $l_user = $l_info['ip'];
+ $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>';
}
$l_user = '<span class="user">'.$l_user.'</span>';
- $l_sum = ($l_info['sum']) ? '<span class="sum">'.hsc($l_info['sum']).'</span>' : '';
+ $l_sum = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : '';
if ($l_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"';
$l_head_title = ($media) ? dformat($l_rev) : $id.' ['.dformat($l_rev).']';
- $l_head = '<a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">'.
- $l_head_title.'</a>'.
+ $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">'.
+ $l_head_title.'</a></bdi>'.
$head_separator.$l_user.' '.$l_sum;
}
if($r_rev){
$r_info = getRevisionInfo($id,$r_rev,true, $media);
if($r_info['user']){
- $r_user = editorinfo($r_info['user']);
- if(auth_ismanager()) $r_user .= ' ('.$r_info['ip'].')';
+ $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>';
+ if(auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>';
} else {
- $r_user = $r_info['ip'];
+ $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>';
}
$r_user = '<span class="user">'.$r_user.'</span>';
- $r_sum = ($r_info['sum']) ? '<span class="sum">'.hsc($r_info['sum']).'</span>' : '';
+ $r_sum = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : '';
if ($r_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
$r_head_title = ($media) ? dformat($r_rev) : $id.' ['.dformat($r_rev).']';
- $r_head = '<a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">'.
- $r_head_title.'</a>'.
+ $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">'.
+ $r_head_title.'</a></bdi>'.
$head_separator.$r_user.' '.$r_sum;
}elseif($_rev = @filemtime($media_or_wikiFN($id))){
$_info = getRevisionInfo($id,$_rev,true, $media);
if($_info['user']){
- $_user = editorinfo($_info['user']);
- if(auth_ismanager()) $_user .= ' ('.$_info['ip'].')';
+ $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
+ if(auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
} else {
- $_user = $_info['ip'];
+ $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>';
}
$_user = '<span class="user">'.$_user.'</span>';
- $_sum = ($_info['sum']) ? '<span class="sum">'.hsc($_info['sum']).'</span>' : '';
+ $_sum = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : '';
if ($_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
$r_head_title = ($media) ? dformat($_rev) : $id.' ['.dformat($_rev).']';
- $r_head = '<a class="wikilink1" href="'.$ml_or_wl($id).'">'.
- $r_head_title.'</a> '.
+ $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id).'">'.
+ $r_head_title.'</a></bdi> '.
'('.$lang['current'].')'.
$head_separator.$_user.' '.$_sum;
}else{
@@ -1318,19 +1323,22 @@ function html_register(){
global $conf;
global $INPUT;
+ $base_attrs = array('size'=>50,'required'=>'required');
+ $email_attrs = $base_attrs + array('type'=>'email','class'=>'edit');
+
print p_locale_xhtml('register');
print '<div class="centeralign">'.NL;
$form = new Doku_Form(array('id' => 'dw__register'));
$form->startFieldset($lang['btn_register']);
$form->addHidden('do', 'register');
$form->addHidden('save', '1');
- $form->addElement(form_makeTextField('login', $INPUT->post->str('login'), $lang['user'], '', 'block', array('size'=>'50')));
+ $form->addElement(form_makeTextField('login', $INPUT->post->str('login'), $lang['user'], '', 'block', $base_attrs));
if (!$conf['autopasswd']) {
- $form->addElement(form_makePasswordField('pass', $lang['pass'], '', 'block', array('size'=>'50')));
- $form->addElement(form_makePasswordField('passchk', $lang['passchk'], '', 'block', array('size'=>'50')));
+ $form->addElement(form_makePasswordField('pass', $lang['pass'], '', 'block', $base_attrs));
+ $form->addElement(form_makePasswordField('passchk', $lang['passchk'], '', 'block', $base_attrs));
}
- $form->addElement(form_makeTextField('fullname', $INPUT->post->str('fullname'), $lang['fullname'], '', 'block', array('size'=>'50')));
- $form->addElement(form_makeTextField('email', $INPUT->post->str('email'), $lang['email'], '', 'block', array('size'=>'50')));
+ $form->addElement(form_makeTextField('fullname', $INPUT->post->str('fullname'), $lang['fullname'], '', 'block', $base_attrs));
+ $form->addElement(form_makeField('email','email', $INPUT->post->str('email'), $lang['email'], '', 'block', $email_attrs));
$form->addElement(form_makeButton('submit', '', $lang['btn_register']));
$form->endFieldset();
html_form('register', $form);
@@ -1353,10 +1361,10 @@ function html_updateprofile(){
global $auth;
print p_locale_xhtml('updateprofile');
+ print '<div class="centeralign">'.NL;
$fullname = $INPUT->post->str('fullname', $INFO['userinfo']['name'], true);
$email = $INPUT->post->str('email', $INFO['userinfo']['mail'], true);
- print '<div class="centeralign">'.NL;
$form = new Doku_Form(array('id' => 'dw__register'));
$form->startFieldset($lang['profile']);
$form->addHidden('do', 'profile');
@@ -1365,9 +1373,9 @@ function html_updateprofile(){
$attr = array('size'=>'50');
if (!$auth->canDo('modName')) $attr['disabled'] = 'disabled';
$form->addElement(form_makeTextField('fullname', $fullname, $lang['fullname'], '', 'block', $attr));
- $attr = array('size'=>'50');
+ $attr = array('size'=>'50', 'class'=>'edit');
if (!$auth->canDo('modMail')) $attr['disabled'] = 'disabled';
- $form->addElement(form_makeTextField('email', $email, $lang['email'], '', 'block', $attr));
+ $form->addElement(form_makeField('email','email', $email, $lang['email'], '', 'block', $attr));
$form->addElement(form_makeTag('br'));
if ($auth->canDo('modPass')) {
$form->addElement(form_makePasswordField('newpass', $lang['newpass'], '', 'block', array('size'=>'50')));
@@ -1375,12 +1383,30 @@ function html_updateprofile(){
}
if ($conf['profileconfirm']) {
$form->addElement(form_makeTag('br'));
- $form->addElement(form_makePasswordField('oldpass', $lang['oldpass'], '', 'block', array('size'=>'50')));
+ $form->addElement(form_makePasswordField('oldpass', $lang['oldpass'], '', 'block', array('size'=>'50', 'required' => 'required')));
}
$form->addElement(form_makeButton('submit', '', $lang['btn_save']));
$form->addElement(form_makeButton('reset', '', $lang['btn_reset']));
+
$form->endFieldset();
html_form('updateprofile', $form);
+
+ if ($auth->canDo('delUser') && actionOK('profile_delete')) {
+ $form_profiledelete = new Doku_Form(array('id' => 'dw__profiledelete'));
+ $form_profiledelete->startFieldset($lang['profdeleteuser']);
+ $form_profiledelete->addHidden('do', 'profile_delete');
+ $form_profiledelete->addHidden('delete', '1');
+ $form_profiledelete->addElement(form_makeCheckboxField('confirm_delete', '1', $lang['profconfdelete'],'dw__confirmdelete','', array('required' => 'required')));
+ if ($conf['profileconfirm']) {
+ $form_profiledelete->addElement(form_makeTag('br'));
+ $form_profiledelete->addElement(form_makePasswordField('oldpass', $lang['oldpass'], '', 'block', array('size'=>'50', 'required' => 'required')));
+ }
+ $form_profiledelete->addElement(form_makeButton('submit', '', $lang['btn_deleteuser']));
+ $form_profiledelete->endFieldset();
+
+ html_form('profiledelete', $form_profiledelete);
+ }
+
print '</div>'.NL;
}
@@ -1488,7 +1514,7 @@ function html_edit(){
echo 'textChanged = ' . ($mod ? 'true' : 'false');
echo '/*!]]>*/</script>' . NL;
} ?>
- <div class="editBox">
+ <div class="editBox" role="application">
<div class="toolbar group">
<div id="draft__status"><?php if(!empty($INFO['draft'])) echo $lang['draftdate'].' '.dformat();?></div>
diff --git a/inc/indexer.php b/inc/indexer.php
index 2f3ab25dc..8f0ba7ec6 100644
--- a/inc/indexer.php
+++ b/inc/indexer.php
@@ -10,7 +10,7 @@
if(!defined('DOKU_INC')) die('meh.');
// Version tag used to force rebuild on upgrade
-define('INDEXER_VERSION', 5);
+define('INDEXER_VERSION', 6);
// set the minimum token length to use in the index (note, this doesn't apply to numeric tokens)
if (!defined('IDX_MINWORDLENGTH')) define('IDX_MINWORDLENGTH',2);
@@ -1365,6 +1365,12 @@ function idx_addPage($page, $verbose=false, $force=false) {
$metadata['relation_references'] = array_keys($references);
else
$metadata['relation_references'] = array();
+
+ if (($media = p_get_metadata($page, 'relation media', METADATA_RENDER_UNLIMITED)) !== null)
+ $metadata['relation_media'] = array_keys($media);
+ else
+ $metadata['relation_media'] = array();
+
$data = compact('page', 'body', 'metadata', 'pid');
$evt = new Doku_Event('INDEXER_PAGE_ADD', $data);
if ($evt->advise_before()) $data['body'] = $data['body'] . " " . rawWiki($page);
diff --git a/inc/lang/de-informal/install.html b/inc/lang/de-informal/install.html
index f0473772c..19fae8065 100644
--- a/inc/lang/de-informal/install.html
+++ b/inc/lang/de-informal/install.html
@@ -15,11 +15,11 @@ hostest, über FTP oder ein entsprechendes Werkzeug (z.B. cPanel) durchführen.<
(<abbr title="access control list">ACL</abbr>) von DokuWiki, welcher eine
Administratoranmeldung und damit Zugang zum Administrationsmenü ermöglicht.
Dort kannst du dann weitere Tätigkeiten wie das Installieren von Plugins, dass
-Verwalten von Nutzern und das Ändern von Konfigurationseinstellungen durchführen.
-Das Nutzen der Zugangskontrolle ist nicht zwingend erforderlich, es erleichtert aber
+Verwalten von Benutzern und das Ändern von Konfigurationseinstellungen durchführen.
+Das Benutzen der Zugangskontrolle ist nicht zwingend erforderlich, es erleichtert aber
die Administration von DokuWiki.</p>
-<p>Erfahrene Anwender oder Nutzer mit speziellen Konfigurationsbedürfnissen sollten
+<p>Erfahrene Anwender oder Benutzer mit speziellen Konfigurationsbedürfnissen sollten
die folgenden Links nutzen, um sich über
<a href="http://dokuwiki.org/install">Installation</a>
und <a href="http://dokuwiki.org/config">Konfiguration</a> zu
diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php
index 8a954c0e8..4ee9a0eed 100644
--- a/inc/lang/de-informal/lang.php
+++ b/inc/lang/de-informal/lang.php
@@ -20,6 +20,7 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -63,6 +64,7 @@ $lang['btn_revert'] = 'Wiederherstellen';
$lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
+$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
@@ -73,14 +75,15 @@ $lang['remember'] = 'Angemeldet bleiben';
$lang['fullname'] = 'Voller Name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Benutzerprofil';
-$lang['badlogin'] = 'Nutzername oder Passwort sind falsch.';
+$lang['badlogin'] = 'Benutzername oder Passwort sind falsch.';
+$lang['badpassconfirm'] = 'Das Passwort war falsch.';
$lang['minoredit'] = 'Kleine Änderung';
$lang['draftdate'] = 'Entwurf gespeichert am';
$lang['nosecedit'] = 'Diese Seite wurde in der Zwischenzeit geändert, da das Sektionsinfo veraltet ist. Die ganze Seite wird stattdessen geladen.';
$lang['regmissing'] = 'Alle Felder müssen ausgefüllt werden';
-$lang['reguexists'] = 'Der Nutzername existiert leider schon.';
-$lang['regsuccess'] = 'Der neue Nutzer wurde angelegt und das Passwort per E-Mail versandt.';
-$lang['regsuccess2'] = 'Der neue Nutzer wurde angelegt.';
+$lang['reguexists'] = 'Der Benutzername existiert leider schon.';
+$lang['regsuccess'] = 'Der neue Benutzer wurde angelegt und das Passwort per E-Mail versandt.';
+$lang['regsuccess2'] = 'Der neue Benutzer wurde angelegt.';
$lang['regmailfail'] = 'Offenbar ist ein Fehler beim Versenden der Passwortmail aufgetreten. Bitte wende dich an den Wiki-Admin.';
$lang['regbadmail'] = 'Die angegebene Mail-Adresse scheint ungültig zu sein. Falls dies ein Fehler ist, wende dich bitte an den Wiki-Admin.';
$lang['regbadpass'] = 'Die beiden eingegeben Passwörter stimmen nicht überein. Bitte versuche es noch einmal.';
@@ -90,6 +93,11 @@ $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki n
$lang['profnochange'] = 'Keine Änderungen, nichts zu tun.';
$lang['profnoempty'] = 'Es muss ein Name oder eine E-Mail Adresse angegeben werden.';
$lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.';
+$lang['profnodelete'] = 'Dieses Wiki unterstützt nicht das Löschen von Benutzern.';
+$lang['profdeleteuser'] = 'Benutzerprofil löschen';
+$lang['profdeleted'] = 'Dein Benutzerprofil wurde im Wiki gelöscht.';
+$lang['profconfdelete'] = 'Ich möchte mein Benutzerprofil löschen.<br/> Diese Aktion ist nicht umkehrbar.';
+$lang['profconfdeletemissing'] = 'Bestätigungs-Checkbox wurde nicht angehakt.';
$lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an';
$lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.';
$lang['resendpwd'] = 'Neues Passwort setzen für';
@@ -146,7 +154,7 @@ $lang['js']['media_diff_portions'] = 'Übergang';
$lang['js']['media_select'] = 'Dateien auswählen…';
$lang['js']['media_upload_btn'] = 'Hochladen';
$lang['js']['media_done_btn'] = 'Fertig';
-$lang['js']['media_drop'] = 'Dateien hier draufziehen um sie hochzuladen';
+$lang['js']['media_drop'] = 'Dateien hier hinziehen um sie hochzuladen';
$lang['js']['media_cancel'] = 'Entfernen';
$lang['js']['media_overwrt'] = 'Existierende Dateien überschreiben';
$lang['rssfailed'] = 'Es ist ein Fehler beim Laden des Feeds aufgetreten: ';
@@ -292,9 +300,9 @@ $lang['i_badval'] = '<code>%s</code> - unerlaubter oder leerer Wert
$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Du kannst jetzt die install.php löschen. Dein <a href="doku.php?id=wiki:welcome">neues DokuWiki</a> ist jetzt für dich bereit.';
$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese von Hand beheben, bevor du dein <a href="doku.php?id=wiki:welcome">neues DokuWiki</a> nutzen kannst.';
$lang['i_policy'] = 'Anfangseinstellungen der Zugangskontrolle (ACL)';
-$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben und hochladen für alle Nutzer)';
-$lang['i_pol1'] = 'Öffentliches Wiki (Lesen für alle, Schreiben und Hochladen nur für registrierte Nutzer)';
-$lang['i_pol2'] = 'Geschlossenes Wiki (Lesen, Schreiben und Hochladen nur für registrierte Nutzer)';
+$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben und hochladen für alle Benutzer)';
+$lang['i_pol1'] = 'Öffentliches Wiki (Lesen für alle, Schreiben und Hochladen nur für registrierte Benutzer)';
+$lang['i_pol2'] = 'Geschlossenes Wiki (Lesen, Schreiben und Hochladen nur für registrierte Benutzer)';
$lang['i_retry'] = 'Wiederholen';
$lang['i_license'] = 'Bitte wähle die Lizenz aus unter der die Wiki-Inhalte veröffentlicht werden sollen:';
$lang['i_license_none'] = 'Keine Lizenzinformationen anzeigen';
diff --git a/inc/lang/de-informal/locked.txt b/inc/lang/de-informal/locked.txt
index 4430fc6dd..1cfa089c0 100644
--- a/inc/lang/de-informal/locked.txt
+++ b/inc/lang/de-informal/locked.txt
@@ -1,4 +1,4 @@
====== Seite gesperrt ======
-Diese Seite ist momentan von einem anderen Nutzer gesperrt. Warte, bis dieser mit dem Bearbeiten fertig ist oder die Sperre abläuft.
+Diese Seite ist momentan von einem anderen Benutzer gesperrt. Warte, bis dieser mit dem Bearbeiten fertig ist oder die Sperre abläuft.
diff --git a/inc/lang/de-informal/password.txt b/inc/lang/de-informal/password.txt
index 8ce252966..e17dba4bf 100644
--- a/inc/lang/de-informal/password.txt
+++ b/inc/lang/de-informal/password.txt
@@ -1,6 +1,6 @@
Hallo @FULLNAME@!
-Hier sind deine Nutzerdaten für @TITLE@ auf @DOKUWIKIURL@
+Hier sind deine Benutzerdaten für @TITLE@ auf @DOKUWIKIURL@
Benutzername: @LOGIN@
Passwort : @PASSWORD@
diff --git a/inc/lang/de-informal/register.txt b/inc/lang/de-informal/register.txt
index 8fe4718dc..f6bf6ed85 100644
--- a/inc/lang/de-informal/register.txt
+++ b/inc/lang/de-informal/register.txt
@@ -1,4 +1,4 @@
-====== Als neuer Nutzer registrieren ======
+====== Als neuer Benutzer registrieren ======
-Bitte fülle alle Felder aus, um einen neuen Nutzer-Account in diesem Wiki anzulegen. Stelle sicher, dass eine **gültige E-Mail-Adresse** angegeben wird - das Passwort wird an diese Adresse gesendet. Der Nutzername sollte aus einem Wort ohne Umlaute, Leer- oder Sonderzeichen bestehen.
+Bitte fülle alle Felder aus, um einen neuen Benutzer-Account in diesem Wiki anzulegen. Stelle sicher, dass eine **gültige E-Mail-Adresse** angegeben wird - das Passwort wird an diese Adresse gesendet. Der Benutzername sollte aus einem Wort ohne Umlaute, Leer- oder Sonderzeichen bestehen.
diff --git a/inc/lang/de/install.html b/inc/lang/de/install.html
index 5af3198d4..47dcdf61d 100644
--- a/inc/lang/de/install.html
+++ b/inc/lang/de/install.html
@@ -15,11 +15,11 @@ hosten, über FTP oder ein entsprechendes Werkzeug (z.B. cPanel) durchführen.</
(<abbr title="access control list">ACL</abbr>) von DokuWiki, welcher eine
Administratoranmeldung und damit Zugang zum Administrationsmenu ermöglicht.
Dort können Sie dann weitere Tätigkeiten wie das Installieren von Plugins, dass
-Verwalten von Nutzern und das Ändern von Konfigurationseinstellungen durchführen.
+Verwalten von Benutzern und das Ändern von Konfigurationseinstellungen durchführen.
Das Nutzen der Zugangskontrolle ist nicht zwingend erforderlich, es erleichtert aber
die Administration von DokuWiki.</p>
-<p>Erfahrene Anwender oder Nutzer mit speziellen Konfigurationsbedürfnissen sollten
+<p>Erfahrene Anwender oder Benutzer mit speziellen Konfigurationsbedürfnissen sollten
die folgenden Links nutzen, um sich über
<a href="http://dokuwiki.org/install">Installation</a>
und <a href="http://dokuwiki.org/config">Konfiguration</a> zu
diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php
index af6f32bf4..496eff2e5 100644
--- a/inc/lang/de/lang.php
+++ b/inc/lang/de/lang.php
@@ -65,6 +65,7 @@ $lang['btn_revert'] = 'Wiederherstellen';
$lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
+$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
@@ -75,14 +76,15 @@ $lang['remember'] = 'Angemeldet bleiben';
$lang['fullname'] = 'Voller Name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Benutzerprofil';
-$lang['badlogin'] = 'Nutzername oder Passwort sind falsch.';
+$lang['badlogin'] = 'Benutzername oder Passwort sind falsch.';
+$lang['badpassconfirm'] = 'Das Passwort war falsch.';
$lang['minoredit'] = 'kleine Änderung';
$lang['draftdate'] = 'Entwurf gespeichert am';
$lang['nosecedit'] = 'Diese Seite wurde in der Zwischenzeit geändert, Sektionsinfo ist veraltet, lade stattdessen volle Seite.';
$lang['regmissing'] = 'Alle Felder müssen ausgefüllt werden.';
-$lang['reguexists'] = 'Der Nutzername existiert leider schon.';
-$lang['regsuccess'] = 'Der neue Nutzer wurde angelegt und das Passwort per E-Mail versandt.';
-$lang['regsuccess2'] = 'Der neue Nutzer wurde angelegt.';
+$lang['reguexists'] = 'Der Benutzername existiert leider schon.';
+$lang['regsuccess'] = 'Der neue Benutzer wurde angelegt und das Passwort per E-Mail versandt.';
+$lang['regsuccess2'] = 'Der neue Benutzer wurde angelegt.';
$lang['regmailfail'] = 'Offenbar ist ein Fehler beim Versenden der Passwort-E-Mail aufgetreten. Bitte wenden Sie sich an den Wiki-Admin.';
$lang['regbadmail'] = 'Die angegebene E-Mail-Adresse scheint ungültig zu sein. Falls dies ein Fehler ist, wenden Sie sich bitte an den Wiki-Admin.';
$lang['regbadpass'] = 'Die beiden eingegeben Passwörter stimmen nicht überein. Bitte versuchen Sie es noch einmal.';
@@ -92,6 +94,11 @@ $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki n
$lang['profnochange'] = 'Keine Änderungen, nichts zu tun.';
$lang['profnoempty'] = 'Es muss ein Name und eine E-Mail-Adresse angegeben werden.';
$lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.';
+$lang['profnodelete'] = 'Dieses Wiki unterstützt nicht das Löschen von Benutzern.';
+$lang['profdeleteuser'] = 'Benutzerprofil löschen';
+$lang['profdeleted'] = 'Ihr Benutzerprofil wurde im Wiki gelöscht.';
+$lang['profconfdelete'] = 'Ich möchte mein Benutzerprofil löschen.<br/> Diese Aktion ist nicht umkehrbar.';
+$lang['profconfdeletemissing'] = 'Bestätigungs-Checkbox wurde nicht angehakt.';
$lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an';
$lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.';
$lang['resendpwd'] = 'Neues Passwort setzen für';
@@ -148,7 +155,7 @@ $lang['js']['media_diff_portions'] = 'Übergang';
$lang['js']['media_select'] = 'Dateien auswählen…';
$lang['js']['media_upload_btn'] = 'Hochladen';
$lang['js']['media_done_btn'] = 'Fertig';
-$lang['js']['media_drop'] = 'Dateien hier draufziehen um sie hochzuladen';
+$lang['js']['media_drop'] = 'Dateien hier hinziehen um sie hochzuladen';
$lang['js']['media_cancel'] = 'Entfernen';
$lang['js']['media_overwrt'] = 'Existierende Dateien überschreiben';
$lang['rssfailed'] = 'Es ist ein Fehler beim Laden des Feeds aufgetreten: ';
@@ -235,7 +242,7 @@ $lang['qb_extlink'] = 'Externer Link';
$lang['qb_hr'] = 'Horizontale Linie';
$lang['qb_ol'] = 'Nummerierter Listenpunkt';
$lang['qb_ul'] = 'Listenpunkt';
-$lang['qb_media'] = 'Bilder und andere Dateien hinzufügen';
+$lang['qb_media'] = 'Bilder und andere Dateien hinzufügen (öffnet sich in einem neuen Fenster)';
$lang['qb_sig'] = 'Unterschrift einfügen';
$lang['qb_smileys'] = 'Smileys';
$lang['qb_chars'] = 'Sonderzeichen';
@@ -294,9 +301,9 @@ $lang['i_badval'] = '<code>%s</code> - unerlaubter oder leerer Wert
$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Sie können jetzt die install.php löschen. Ihr <a href="doku.php?id=wiki:welcome">neues DokuWiki</a> ist jetzt für Sie bereit.';
$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese von Hand beheben, bevor Sie Ihr <a href="doku.php?id=wiki:welcome">neues DokuWiki</a> nutzen können.';
$lang['i_policy'] = 'Anfangseinstellungen der Zugangskontrolle (ACL)';
-$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben und hochladen für alle Nutzer)';
-$lang['i_pol1'] = 'Öffentliches Wiki (Lesen für alle, Schreiben und Hochladen nur für registrierte Nutzer)';
-$lang['i_pol2'] = 'Geschlossenes Wiki (Lesen, Schreiben und Hochladen nur für registrierte Nutzer)';
+$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben und hochladen für alle Benutzer)';
+$lang['i_pol1'] = 'Öffentliches Wiki (Lesen für alle, Schreiben und Hochladen nur für registrierte Benutzer)';
+$lang['i_pol2'] = 'Geschlossenes Wiki (Lesen, Schreiben und Hochladen nur für registrierte Benutzer)';
$lang['i_retry'] = 'Wiederholen';
$lang['i_license'] = 'Bitte wählen Sie die Lizenz, unter die Sie Ihre Inhalte stellen möchten:';
$lang['i_license_none'] = 'Lizensierungsinformation nicht anzeigen';
diff --git a/inc/lang/de/locked.txt b/inc/lang/de/locked.txt
index 6656beece..97323ca61 100644
--- a/inc/lang/de/locked.txt
+++ b/inc/lang/de/locked.txt
@@ -1,4 +1,4 @@
====== Seite gesperrt ======
-Diese Seite ist momentan von einem anderen Nutzer gesperrt. Warten Sie, bis dieser mit dem Bearbeiten fertig ist oder die Sperre abläuft.
+Diese Seite ist momentan von einem anderen Benutzer gesperrt. Warten Sie, bis dieser mit dem Bearbeiten fertig ist oder die Sperre abläuft.
diff --git a/inc/lang/de/password.txt b/inc/lang/de/password.txt
index dd10b43e2..cce3b8ea6 100644
--- a/inc/lang/de/password.txt
+++ b/inc/lang/de/password.txt
@@ -1,6 +1,6 @@
Hallo @FULLNAME@!
-Hier sind Ihre Nutzerdaten für @TITLE@ auf @DOKUWIKIURL@
+Hier sind Ihre Benutzerdaten für @TITLE@ auf @DOKUWIKIURL@
Benutzername: @LOGIN@
Passwort : @PASSWORD@
diff --git a/inc/lang/de/register.txt b/inc/lang/de/register.txt
index 83684f500..f1ea30a47 100644
--- a/inc/lang/de/register.txt
+++ b/inc/lang/de/register.txt
@@ -1,4 +1,4 @@
-====== Als neuer Nutzer registrieren ======
+====== Als neuer Benutzer registrieren ======
-Bitte füllen Sie alle Felder aus, um einen neuen Nutzer-Account in diesem Wiki anzulegen. Stellen Sie sicher, dass eine **gültige E-Mail-Adresse** angegeben wird - das Passwort wird an diese Adresse gesendet. Der Nutzername sollte aus einem Wort ohne Umlaute, Leer- oder Sonderzeichen bestehen.
+Bitte füllen Sie alle Felder aus, um einen neuen Benutzer-Account in diesem Wiki anzulegen. Stellen Sie sicher, dass eine **gültige E-Mail-Adresse** angegeben wird - das Passwort wird an diese Adresse gesendet. Der Benutzername sollte aus einem Wort ohne Umlaute, Leer- oder Sonderzeichen bestehen.
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index cdad6c9a6..630ccb3ff 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -51,6 +51,7 @@ $lang['btn_revert'] = 'Restore';
$lang['btn_register'] = 'Register';
$lang['btn_apply'] = 'Apply';
$lang['btn_media'] = 'Media Manager';
+$lang['btn_deleteuser'] = 'Remove My Account';
$lang['loggedinas'] = 'Logged in as';
$lang['user'] = 'Username';
@@ -63,6 +64,7 @@ $lang['fullname'] = 'Real name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'User Profile';
$lang['badlogin'] = 'Sorry, username or password was wrong.';
+$lang['badpassconfirm'] = 'Sorry, the password was wrong';
$lang['minoredit'] = 'Minor Changes';
$lang['draftdate'] = 'Draft autosaved on'; // full dformat date will be added
$lang['nosecedit'] = 'The page was changed in the meantime, section info was out of date loaded full page instead.';
@@ -81,6 +83,11 @@ $lang['profna'] = 'This wiki does not support profile modificatio
$lang['profnochange'] = 'No changes, nothing to do.';
$lang['profnoempty'] = 'An empty name or email address is not allowed.';
$lang['profchanged'] = 'User profile successfully updated.';
+$lang['profnodelete'] = 'This wiki does not support deleting users';
+$lang['profdeleteuser'] = 'Delete Account';
+$lang['profdeleted'] = 'Your user account has been deleted from this wiki';
+$lang['profconfdelete'] = 'I wish to remove my account from this wiki. <br/> This action can not be undone.';
+$lang['profconfdeletemissing'] = 'Confirmation check box not ticked';
$lang['pwdforget'] = 'Forgotten your password? Get a new one';
$lang['resendna'] = 'This wiki does not support password resending.';
@@ -234,7 +241,7 @@ $lang['qb_extlink'] = 'External Link';
$lang['qb_hr'] = 'Horizontal Rule';
$lang['qb_ol'] = 'Ordered List Item';
$lang['qb_ul'] = 'Unordered List Item';
-$lang['qb_media'] = 'Add Images and other files';
+$lang['qb_media'] = 'Add Images and other files (opens in a new window)';
$lang['qb_sig'] = 'Insert Signature';
$lang['qb_smileys'] = 'Smileys';
$lang['qb_chars'] = 'Special Chars';
diff --git a/inc/lang/hu/diff.txt b/inc/lang/hu/diff.txt
index 6a09cdea2..50bd067e9 100644
--- a/inc/lang/hu/diff.txt
+++ b/inc/lang/hu/diff.txt
@@ -1,4 +1,4 @@
====== Különbségek ======
-A kiválasztott változat és az aktuális verzió közötti különbséget mutatjuk.
+A kiválasztott változat és az aktuális verzió közötti különbségek a következők.
diff --git a/inc/lang/hu/draft.txt b/inc/lang/hu/draft.txt
index 4d12e2e0c..cae980aa5 100644
--- a/inc/lang/hu/draft.txt
+++ b/inc/lang/hu/draft.txt
@@ -2,4 +2,4 @@
Az oldal utolsó szerkesztését nem fejezted be rendesen. A DokuWiki elmentette piszkozatként, így most folytathatod a szerkesztést. Lent látható, amit az utolsó szerkesztésből elmentettünk.
-Válassz a //helyreállítás// vagy a //törlés// opciók közül a piszkozat sorsát illetően. \ No newline at end of file
+Válassz a //helyreállítás// vagy a //törlés// opciók közül a piszkozat sorsát illetően vagy //megszakíthatod// a szerkesztési folyamatot. \ No newline at end of file
diff --git a/inc/lang/hu/edit.txt b/inc/lang/hu/edit.txt
index 898387cf2..0992723c1 100644
--- a/inc/lang/hu/edit.txt
+++ b/inc/lang/hu/edit.txt
@@ -1 +1 @@
-Szerkeszd az oldalt majd üsd le a ''Mentés'' gombot. Lásd a [[wiki:syntax|nyelvtan]] oldalt a formázási lehetőségekért. Kérünk, hogy csak akkor szerkeszd az oldalt ha **jobbítani** tudod. Ha ki akarsz próbálni dolgokat akkor az első lépéseid a [[playground:playground|játszótéren]] (playground) tedd.
+Szerkeszd az oldalt majd kattints a ''Mentés'' gombra! Lásd a [[wiki:syntax|formázás]] oldalt a formázási lehetőségekért. Kérünk, hogy csak akkor szerkeszd az oldalt ha **javítani** tudsz rajta. Ha ki akarsz próbálni dolgokat, akkor az első lépéseid a [[playground:playground|játszótéren]] tedd.
diff --git a/inc/lang/hu/install.html b/inc/lang/hu/install.html
index a7d681667..c0373932e 100644
--- a/inc/lang/hu/install.html
+++ b/inc/lang/hu/install.html
@@ -15,12 +15,12 @@ vagy a tárhelyszolgáltató által rendelkezésre bocsátott beállítóeszköz
<p>A Beállító Varázsló felkészíti ezt a DokuWikit a hozzáférési listák
(<abbr title="access control list">ACL</abbr>-ek) használatára. Így
-a Wiki-gazda felhasználóval hozzáférünk az admin menühöz, mellyel
+az Adminisztrátor felhasználóval hozzáférünk az admin menühöz, mellyel
bővítményeket telepíthetünk, felhasználókat és hozzáférési jogokat
kezelhetünk, valamint változtathatunk a konfigurációs beállításokon.
Ez tulajdonképpen nem szükséges a DokuWiki működéséhez, de megkönnyíti
az adminisztrációt.</p>
<p>Szakértők illetve speciális beállítást igénylő felhasználók további információkat
-találnak a következő oldalakon <a href="http://dokuwiki.org/install">telepítéssel</a>
+találnak a következő oldalakon a <a href="http://dokuwiki.org/install">telepítéssel</a>
és <a href="http://dokuwiki.org/config">konfigurálási lehetőségekkel</a> kapcsolatban.</p>
diff --git a/inc/lang/hu/lang.php b/inc/lang/hu/lang.php
index 275fb15d5..b332b9a83 100644
--- a/inc/lang/hu/lang.php
+++ b/inc/lang/hu/lang.php
@@ -10,6 +10,7 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -42,14 +43,17 @@ $lang['btn_delete'] = 'Törlés';
$lang['btn_back'] = 'Vissza';
$lang['btn_backlink'] = 'Hivatkozások';
$lang['btn_backtomedia'] = 'Vissza a médiafájlok kezeléséhez';
-$lang['btn_subscribe'] = 'Oldalváltozások-hírlevél feliratkozás';
+$lang['btn_subscribe'] = 'Feliratkozás az oldalváltozásokra';
$lang['btn_profile'] = 'Személyes beállítások';
$lang['btn_reset'] = 'Alaphelyzet';
+$lang['btn_resendpwd'] = 'Jelszóváltoztatás';
$lang['btn_draft'] = 'Piszkozat szerkesztése';
$lang['btn_recover'] = 'Piszkozat folytatása';
$lang['btn_draftdel'] = 'Piszkozat törlése';
$lang['btn_revert'] = 'Helyreállítás';
$lang['btn_register'] = 'Regisztráció';
+$lang['btn_apply'] = 'Alkalmaz';
+$lang['btn_media'] = 'Médiakezelő';
$lang['loggedinas'] = 'Belépett felhasználó: ';
$lang['user'] = 'Azonosító';
$lang['pass'] = 'Jelszó';
@@ -60,16 +64,16 @@ $lang['remember'] = 'Emlékezz rám';
$lang['fullname'] = 'Teljes név';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Személyes beállítások';
-$lang['badlogin'] = 'Sajnáljuk, az azonosító, vagy a jelszó nem jó.';
+$lang['badlogin'] = 'Sajnáljuk, az azonosító vagy a jelszó nem jó.';
$lang['minoredit'] = 'Apróbb változások';
$lang['draftdate'] = 'Piszkozat elmentve:';
-$lang['nosecedit'] = 'Időközben megváltozott az oldal, emiatt a szakasz nem friss. Töltse újra az egész oldalt!';
+$lang['nosecedit'] = 'Időközben megváltozott az oldal, emiatt a szakasz nem friss. Töltsd újra az egész oldalt!';
$lang['regmissing'] = 'Sajnáljuk, az összes mezőt ki kell töltened.';
$lang['reguexists'] = 'Sajnáljuk, ilyen azonosítójú felhasználónk már van.';
$lang['regsuccess'] = 'A felhasználói azonosítót létrehoztuk. A jelszót postáztuk.';
$lang['regsuccess2'] = 'A felhasználói azonosítót létrehoztuk.';
-$lang['regmailfail'] = 'Úgy tűnik hiba történt a jelszó postázása során. Kérjük lépj kapcsolatba a Wiki-gazdával!!';
-$lang['regbadmail'] = 'A megadott e-mail cím érvénytelennek tűnik. Ha úgy gondolod ez hiba, lépj kapcsolatba Wiki-gazdával!';
+$lang['regmailfail'] = 'Úgy tűnik hiba történt a jelszó postázása során. Kérjük lépj kapcsolatba az Adminisztrátorokkal!';
+$lang['regbadmail'] = 'A megadott e-mail cím érvénytelennek tűnik. Ha úgy gondolod ez hiba, lépj kapcsolatba az Adminisztrátorokkal!';
$lang['regbadpass'] = 'A két megadott jelszó nem egyezik, próbáld újra!';
$lang['regpwmail'] = 'A DokuWiki jelszavad';
$lang['reghere'] = 'Még nincs azonosítód? Itt kérhetsz';
@@ -79,21 +83,23 @@ $lang['profnoempty'] = 'A név és e-mail mező nem maradhat üresen!'
$lang['profchanged'] = 'A személyes beállítások változtatása megtörtént.';
$lang['pwdforget'] = 'Elfelejtetted a jelszavad? Itt kérhetsz újat';
$lang['resendna'] = 'Ez a wiki nem támogatja a jelszó újraküldést.';
+$lang['resendpwd'] = 'Új jelszó beállítása a következőhöz:';
$lang['resendpwdmissing'] = 'Sajnáljuk, az összes mezőt ki kell töltened.';
$lang['resendpwdnouser'] = 'Sajnáljuk, ilyen azonosítójú felhasználónk nem létezik.';
-$lang['resendpwdbadauth'] = 'Sajnáljuk, ez a megerősítő kód nem helyes. Biztos, hogy a teljes megerősítés linket beírtad pontosan?';
-$lang['resendpwdconfirm'] = 'A megerősítés linket e-mailben elküldtük.';
+$lang['resendpwdbadauth'] = 'Sajnáljuk, ez a megerősítő kód nem helyes. Biztos, hogy a teljes megerősítő linket pontosan beírtad?';
+$lang['resendpwdconfirm'] = 'A megerősítő linket e-mailben elküldtük.';
$lang['resendpwdsuccess'] = 'Az új jelszavadat elküldtük e-mailben.';
$lang['license'] = 'Hacsak máshol nincs egyéb rendelkezés, ezen wiki tartalma a következő licenc alatt érhető el:';
$lang['licenseok'] = 'Megjegyzés: az oldal szerkesztésével elfogadja, hogy a tartalom a következő licenc alatt lesz elérhető:';
$lang['searchmedia'] = 'Keresett fájl neve:';
$lang['searchmedia_in'] = 'Keresés a következőben: %s';
$lang['txt_upload'] = 'Válaszd ki a feltöltendő fájlt';
-$lang['txt_filename'] = 'feltöltési név (elhagyható)';
+$lang['txt_filename'] = 'Feltöltési név (elhagyható)';
$lang['txt_overwrt'] = 'Létező fájl felülírása';
+$lang['maxuploadsize'] = 'Maximum %s méretű fájlokat tölthetsz fel.';
$lang['lockedby'] = 'Jelenleg zárolta:';
$lang['lockexpire'] = 'A zárolás lejár:';
-$lang['js']['willexpire'] = 'Az oldalszerkesztési zárolásod körülbelül egy percen belül lejár.\nAz ütközések elkerülése végett használd az előnézet gombot a zárolási időzítés frissítéséhez.';
+$lang['js']['willexpire'] = 'Az oldalszerkesztési zárolásod körülbelül egy percen belül lejár.\nAz ütközések elkerülése végett használd az előnézet gombot a zárolásod frissítéséhez.';
$lang['js']['notsavedyet'] = 'Elmentetlen változások vannak, amelyek el fognak veszni.
Tényleg ezt akarod?';
$lang['js']['searchmedia'] = 'Fájlok keresése';
@@ -103,50 +109,60 @@ $lang['js']['mediatitle'] = 'Link beállítások';
$lang['js']['mediadisplay'] = 'Link típusa';
$lang['js']['mediaalign'] = 'Igazítás';
$lang['js']['mediasize'] = 'Képméret';
-$lang['js']['mediatarget'] = 'Link';
+$lang['js']['mediatarget'] = 'Link célja';
$lang['js']['mediaclose'] = 'Bezárás';
$lang['js']['mediainsert'] = 'Beillesztés';
$lang['js']['mediadisplayimg'] = 'Kép megtekintése.';
$lang['js']['mediadisplaylnk'] = 'Link megtekintése.';
-$lang['js']['mediasmall'] = 'Kisebb méret';
+$lang['js']['mediasmall'] = 'Kis méret';
$lang['js']['mediamedium'] = 'Közepes méret';
-$lang['js']['medialarge'] = 'Nagyobb méret';
-$lang['js']['mediaoriginal'] = 'Eredeti';
+$lang['js']['medialarge'] = 'Nagy méret';
+$lang['js']['mediaoriginal'] = 'Eredeti verzió';
$lang['js']['medialnk'] = 'Link a részletekre';
$lang['js']['mediadirect'] = 'Közvetlen link az eredetire';
-$lang['js']['medianolnk'] = 'Nincsen link';
+$lang['js']['medianolnk'] = 'Nincs link';
$lang['js']['medianolink'] = 'Ne linkelje a képet';
$lang['js']['medialeft'] = 'Kép igazítása balra.';
$lang['js']['mediaright'] = 'Kép igazítása jobbra.';
$lang['js']['mediacenter'] = 'Kép igazítása középre.';
$lang['js']['medianoalign'] = 'Nem legyen igazítás.';
-$lang['js']['nosmblinks'] = 'A Windows megosztott könyvtárak kereszthivatkozása csak Microsoft Internet Explorerben működik közvetlenül.
-A hivatkozást másolni és beszúrni ettől fügetlenül mndig tudod.';
+$lang['js']['nosmblinks'] = 'A Windows megosztott könyvtárak kereszthivatkozása csak Microsoft Internet Explorerben működik közvetlenül.\nA hivatkozást másolni és beszúrni ettől függetlenül mindig tudod.';
$lang['js']['linkwiz'] = 'Hivatkozás varázsló';
$lang['js']['linkto'] = 'Hivatkozás erre:';
$lang['js']['del_confirm'] = 'Valóban törölni akarod a kiválasztott elem(ek)et?';
-$lang['rssfailed'] = 'Hiba történt ennek a betöltésekor: ';
-$lang['nothingfound'] = 'Semmit sem találtam.';
+$lang['js']['restore_confirm'] = 'Valóban visszaállítod ezt a verziót?';
+$lang['js']['media_diff'] = 'Különbségek megtekintése:';
+$lang['js']['media_diff_both'] = 'Egymás mellett';
+$lang['js']['media_diff_opacity'] = 'Áttetszően';
+$lang['js']['media_diff_portions'] = 'Húzással';
+$lang['js']['media_select'] = 'Fájlok kiválasztása...';
+$lang['js']['media_upload_btn'] = 'Feltöltés';
+$lang['js']['media_done_btn'] = 'Kész';
+$lang['js']['media_drop'] = 'Húzd ide a fájlokat a feltöltéshez';
+$lang['js']['media_cancel'] = 'eltávolítás';
+$lang['js']['media_overwrt'] = 'Meglévő fájlok felülírása';
+$lang['rssfailed'] = 'Hiba történt a hírfolyam betöltésekor: ';
+$lang['nothingfound'] = 'Üres mappa.';
$lang['mediaselect'] = 'Médiafájl kiválasztása';
$lang['fileupload'] = 'Médiafájl feltöltése';
-$lang['uploadsucc'] = 'A feltöltés sikerült';
+$lang['uploadsucc'] = 'Sikeres feltöltés';
$lang['uploadfail'] = 'A feltöltés nem sikerült. Talán rosszak a jogosultságok?';
-$lang['uploadwrong'] = 'A feltöltés megtagadva. Ez a fájl kiterjesztés tiltott.';
+$lang['uploadwrong'] = 'A feltöltés megtagadva. Ez a fájlkiterjesztés tiltott.';
$lang['uploadexist'] = 'A fájl már létezik, nem történt semmi.';
-$lang['uploadbadcontent'] = 'A feltöltött tartalom nem egyezik a %s fájl kiterjesztéssel.';
+$lang['uploadbadcontent'] = 'A feltöltött tartalom nem egyezik a %s fájlkiterjesztéssel.';
$lang['uploadspam'] = 'A feltöltést visszautasítottuk spam-gyanú miatt.';
$lang['uploadxss'] = 'A feltöltést visszautasítottuk, mert lehetséges, hogy kártékony kódot tartalmaz.';
$lang['uploadsize'] = 'A feltöltött fájl túl nagy. (max. %s)';
$lang['deletesucc'] = 'A "%s" fájlt töröltük.';
-$lang['deletefail'] = 'A "%s" fájl nem törölhető. - Ellenőrizd a jogosultságokat!';
-$lang['mediainuse'] = 'A "%s" fájl nem törlődött - még használat alatt van.';
-$lang['namespaces'] = 'Névtér';
+$lang['deletefail'] = 'A "%s" fájl nem törölhető - ellenőrizd a jogosultságokat!';
+$lang['mediainuse'] = 'A "%s" fájl nem törlődött - még használat alatt van!';
+$lang['namespaces'] = 'Névterek';
$lang['mediafiles'] = 'Elérhető fájlok itt:';
-$lang['accessdenied'] = 'Nincsen jogod az oldal megtekintésére.';
-$lang['mediausage'] = 'A következő formában hivatkozhatsz erre az állományra:';
-$lang['mediaview'] = 'Eredeti állomány megtekintése';
+$lang['accessdenied'] = 'Nincs jogod az oldal megtekintésére.';
+$lang['mediausage'] = 'A következő formában hivatkozhatsz erre a fájlra:';
+$lang['mediaview'] = 'Eredeti fájl megtekintése';
$lang['mediaroot'] = 'kiindulási hely';
-$lang['mediaupload'] = 'Itt tölthetsz fel állományt az aktuális névtérbe. Al-névtér létrehozásához a "Feltöltési név" mezőben kell kettősponttal elválasztva megadnod azt.';
+$lang['mediaupload'] = 'Itt tölthetsz fel állományt az aktuális névtérbe. Alnévtér létrehozásához a "Feltöltési név" mezőben kell kettősponttal elválasztva megadnod azt.';
$lang['mediaextchange'] = 'Az állomány kiterjesztése erről: .%s erre: .%s változott!';
$lang['reference'] = 'Hivatkozások';
$lang['ref_inuse'] = 'A fájl nem törölhető, mert a következő oldalakon használják:';
@@ -155,34 +171,44 @@ $lang['hits'] = 'Találatok';
$lang['quickhits'] = 'Illeszkedő oldalnevek';
$lang['toc'] = 'Tartalomjegyzék';
$lang['current'] = 'aktuális';
-$lang['yours'] = 'A te változatod';
-$lang['diff'] = 'a különbségeket mutatja az aktuális változathoz képest';
-$lang['diff2'] = 'a különbségeket mutatja a kiválasztott változatok között';
+$lang['yours'] = 'A Te változatod';
+$lang['diff'] = 'Különbségek az aktuális változathoz képest';
+$lang['diff2'] = 'Különbségek a kiválasztott változatok között';
$lang['difflink'] = 'Összehasonlító nézet linkje';
$lang['diff_type'] = 'Összehasonlítás módja:';
$lang['diff_inline'] = 'Sorok között';
-$lang['diff_side'] = 'Kétoldalas';
-$lang['line'] = 'sorszám';
+$lang['diff_side'] = 'Egymás mellett';
+$lang['line'] = 'Sor';
$lang['breadcrumb'] = 'Nyomvonal';
$lang['youarehere'] = 'Itt vagy';
$lang['lastmod'] = 'Utolsó módosítás';
$lang['by'] = 'szerkesztette:';
$lang['deleted'] = 'eltávolítva';
$lang['created'] = 'létrehozva';
-$lang['restored'] = 'az előző változat helyreállítva (%s)';
+$lang['restored'] = 'régebbi változat helyreállítva (%s)';
$lang['external_edit'] = 'külső szerkesztés';
$lang['summary'] = 'A változások összefoglalása';
$lang['noflash'] = 'Ennek a tartalomnak a megtekintéséhez <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> szükséges.';
$lang['download'] = 'Kódrészlet letöltése';
+$lang['tools'] = 'Eszközök';
+$lang['user_tools'] = 'Felhasználói eszközök';
+$lang['site_tools'] = 'Eszközök a webhelyen';
+$lang['page_tools'] = 'Eszközök az oldalon';
+$lang['skip_to_content'] = 'ugrás a tartalomhoz';
+$lang['sidebar'] = 'Oldalsáv';
$lang['mail_newpage'] = 'új oldal jött létre:';
$lang['mail_changed'] = 'oldal megváltozott:';
$lang['mail_subscribe_list'] = 'oldalak megváltoztak ebben a névtérben:';
-$lang['mail_new_user'] = 'Új felhasználó:';
-$lang['mail_upload'] = 'állományt töltöttek fel:';
+$lang['mail_new_user'] = 'új felhasználó:';
+$lang['mail_upload'] = 'új állományt töltöttek fel:';
+$lang['changes_type'] = 'A következő változásainak megtekintése:';
+$lang['pages_changes'] = 'Oldalak';
+$lang['media_changes'] = 'Médiafájlok';
+$lang['both_changes'] = 'Oldalak és médiafájlok';
$lang['qb_bold'] = 'Félkövér szöveg';
$lang['qb_italic'] = 'Dőlt szöveg';
$lang['qb_underl'] = 'Aláhúzott szöveg';
-$lang['qb_code'] = 'Forráskód szöveg';
+$lang['qb_code'] = 'Forráskód';
$lang['qb_strike'] = 'Áthúzott szöveg';
$lang['qb_h1'] = '1. szintű címsor';
$lang['qb_h2'] = '2. szintű címsor';
@@ -198,16 +224,16 @@ $lang['qb_link'] = 'Belső hivatkozás';
$lang['qb_extlink'] = 'Külső hivatkozás';
$lang['qb_hr'] = 'Vízszintes elválasztó vonal';
$lang['qb_ol'] = 'Sorszámozott lista elem';
-$lang['qb_ul'] = 'Felsorolás lista elem';
+$lang['qb_ul'] = 'Felsorolásos lista elem';
$lang['qb_media'] = 'Képek és más fájlok hozzáadása';
$lang['qb_sig'] = 'Aláírás beszúrása';
-$lang['qb_smileys'] = 'Szmájlik';
+$lang['qb_smileys'] = 'Smiley-k';
$lang['qb_chars'] = 'Speciális karakterek';
-$lang['upperns'] = 'Ugrás a szülő névtérhez';
+$lang['upperns'] = 'ugrás a tartalmazó névtérhez';
$lang['admin_register'] = 'Új felhasználó';
-$lang['metaedit'] = 'Meta-adatok szerkesztése';
-$lang['metasaveerr'] = 'A meta-adatok írása meghiúsult ';
-$lang['metasaveok'] = 'Meta-adatok elmentve';
+$lang['metaedit'] = 'Metaadatok szerkesztése';
+$lang['metasaveerr'] = 'A metaadatok írása nem sikerült';
+$lang['metasaveok'] = 'Metaadatok elmentve';
$lang['img_backto'] = 'Vissza';
$lang['img_title'] = 'Cím';
$lang['img_caption'] = 'Képaláírás';
@@ -215,17 +241,20 @@ $lang['img_date'] = 'Dátum';
$lang['img_fname'] = 'Fájlnév';
$lang['img_fsize'] = 'Méret';
$lang['img_artist'] = 'Készítette';
-$lang['img_copyr'] = 'Copyright';
+$lang['img_copyr'] = 'Szerzői jogok';
$lang['img_format'] = 'Formátum';
-$lang['img_camera'] = 'Fényképező típusa';
+$lang['img_camera'] = 'Fényképezőgép típusa';
$lang['img_keywords'] = 'Kulcsszavak';
+$lang['img_width'] = 'Szélesség';
+$lang['img_height'] = 'Magasság';
+$lang['img_manager'] = 'Megtekintés a médiakezelőben';
$lang['subscr_subscribe_success'] = '%s hozzáadva az értesítési listához: %s';
$lang['subscr_subscribe_error'] = 'Hiba történt %s hozzáadásakor az értesítési listához: %s';
-$lang['subscr_subscribe_noaddress'] = 'Nincsen e-mail cím megadva az adataidnál, így a rendszer nem tudott hozzáadni az értesítési listához';
+$lang['subscr_subscribe_noaddress'] = 'Nincs e-mail cím megadva az adataidnál, így a rendszer nem tudott hozzáadni az értesítési listához';
$lang['subscr_unsubscribe_success'] = '%s eltávolítva az értesítési listából: %s';
$lang['subscr_unsubscribe_error'] = 'Hiba történt %s eltávolításakor az értesítési listából: %s';
$lang['subscr_already_subscribed'] = '%s már feliratkozott erre: %s';
-$lang['subscr_not_subscribed'] = '%s nincsen feliratkozva erre: %s';
+$lang['subscr_not_subscribed'] = '%s nincs feliratkozva erre: %s';
$lang['subscr_m_not_subscribed'] = 'Jelenleg nem vagy feliratkozva erre az oldalra vagy névtérre';
$lang['subscr_m_new_header'] = 'Feliratkozás hozzáadása';
$lang['subscr_m_current_header'] = 'Feliratkozások';
@@ -235,13 +264,14 @@ $lang['subscr_m_receive'] = 'Küldj';
$lang['subscr_style_every'] = 'e-mailt minden változásról';
$lang['subscr_style_digest'] = 'összefoglaló e-mailt oldalanként (minden %.2f nap)';
$lang['subscr_style_list'] = 'egy listát a módosított oldalakról a legutóbbi e-mail óta (minden %.2f nap)';
-$lang['authmodfailed'] = 'Hibás felhasználó-aznosítási módszer van beállítva. Légy szíves értesítsd a Wiki-gazdát!';
-$lang['authtempfail'] = 'A felhasználó azonosítás átmenetileg nem működik. Ha sokáig így lenne, légy szíves értesítsd a Wiki-gazdát!';
+$lang['authmodfailed'] = 'Hibás felhasználó-azonosítási módszer van beállítva. Légy szíves értesítsd az Adminisztrátorokat!';
+$lang['authtempfail'] = 'A felhasználó azonosítás átmenetileg nem működik. Ha sokáig így lenne, légy szíves értesítsd az Adminisztrátorokat!';
+$lang['authpwdexpire'] = 'A jelszavad %d nap múlva lejár, hamarosan meg kell változtatnod.';
$lang['i_chooselang'] = 'Válassz nyelvet';
$lang['i_installer'] = 'DokuWiki Beállító Varázsló';
$lang['i_wikiname'] = 'A Wiki neve';
$lang['i_enableacl'] = 'Hozzáférési listák engedélyezése (ajánlott)';
-$lang['i_superuser'] = 'Wiki-gazda';
+$lang['i_superuser'] = 'Adminisztrátor';
$lang['i_problems'] = 'A Beállító Varázsló a következő problémák miatt megakadt. Nem tudjuk folytatni, amíg ezek nincsenek elhárítva!';
$lang['i_modified'] = 'Biztonsági okokból ez a Varázsló csak új és módosítatlan DokuWiki változaton működik.
Csomagold ki újra a fájlokat a letöltött csomagból, vagy nézd meg a teljes <a href="http://dokuwiki.org/install">Dokuwiki telepítési útmutatót</a>.';
@@ -254,12 +284,15 @@ $lang['i_badhash'] = 'A dokuwiki.php nem felismerhető vagy módosí
$lang['i_badval'] = '<code>%s</code> - nem helyes vagy üres érték';
$lang['i_success'] = 'A beállítás sikeresen befejeződött. Most már letörölhető az install.php fájl. Látogasd meg az <a href="doku.php?id=wiki:welcome">új DokuWikidet</a>!';
$lang['i_failure'] = 'Hiba lépett fel a konfigurációs állományok írásakor. Ki kell javítanod kézzel, mielőtt használni kezded az <a href="doku.php?id=wiki:welcome">új DokuWikidet</a>.';
-$lang['i_policy'] = 'Kezdeti hozzáférési politika';
-$lang['i_pol0'] = 'Nyitott Wiki (mindenki olvashatja, írhatja, és fájlokat tölthet fel)';
-$lang['i_pol1'] = 'Publikus Wiki (mindenki olvashatja, de csak regisztrált felhasználók írhatják, és tölthetnek fel fájlokat)';
-$lang['i_pol2'] = 'Zárt Wiki (csak regisztrált felhasználók olvashatják, írhatják és tölthetnek fel fájlokat)';
+$lang['i_policy'] = 'Kezdeti hozzáférési lista házirend';
+$lang['i_pol0'] = 'Nyitott wiki (mindenki olvashatja, írhatja és fájlokat tölthet fel)';
+$lang['i_pol1'] = 'Publikus wiki (mindenki olvashatja, de csak regisztrált felhasználók írhatják és tölthetnek fel fájlokat)';
+$lang['i_pol2'] = 'Zárt wiki (csak regisztrált felhasználók olvashatják, írhatják és tölthetnek fel fájlokat)';
$lang['i_retry'] = 'Újra';
-$lang['i_license'] = 'Kérlek válassz licenszt a feltöltött tartalomhoz:';
+$lang['i_license'] = 'Kérlek, válassz licencet a feltöltött tartalomhoz:';
+$lang['i_license_none'] = 'Ne jelenítsen meg licenc információt';
+$lang['i_pop_field'] = 'Kérjük, segíts a DokuWiki továbbfejlesztésében:';
+$lang['i_pop_label'] = 'Havonta egyszer névtelen üzenet küldése a DokuWiki fejlesztőinek';
$lang['recent_global'] = 'Jelenleg csak a <b>%s</b> névtér friss változásai látszanak. Megtekinthetők <a href="%s">a teljes wiki friss változásai</a> is.';
$lang['years'] = '%d évvel ezelőtt';
$lang['months'] = '%d hónappal ezelőtt';
@@ -268,4 +301,27 @@ $lang['days'] = '%d nappal ezelőtt';
$lang['hours'] = '%d órával ezelőtt';
$lang['minutes'] = '%d perccel ezelőtt';
$lang['seconds'] = '%d másodperccel ezelőtt';
-$lang['wordblock'] = 'A változásokat nem sikerült menteni, mert tiltott tartalom van benne (spam)';
+$lang['wordblock'] = 'A változásokat nem sikerült menteni, mert tiltott tartalom van benne (spam).';
+$lang['media_uploadtab'] = 'Feltöltés';
+$lang['media_searchtab'] = 'Keresés';
+$lang['media_file'] = 'Fájl';
+$lang['media_viewtab'] = 'Megtekintés';
+$lang['media_edittab'] = 'Szerkesztés';
+$lang['media_historytab'] = 'Korábbi változatok';
+$lang['media_list_thumbs'] = 'Bélyegképek';
+$lang['media_list_rows'] = 'Sorok';
+$lang['media_sort_name'] = 'Név';
+$lang['media_sort_date'] = 'Dátum';
+$lang['media_namespaces'] = 'Névtér kiválasztása';
+$lang['media_files'] = 'Fájlok itt: %s';
+$lang['media_upload'] = 'Feltöltés ide: %s';
+$lang['media_search'] = 'Keresés itt: %s';
+$lang['media_view'] = '%s';
+$lang['media_viewold'] = '%s itt: %s';
+$lang['media_edit'] = '%s szerkesztése';
+$lang['media_history'] = '%s korábbi változatai';
+$lang['media_meta_edited'] = 'metaadatot szerkesztve';
+$lang['media_perm_read'] = 'Sajnáljuk, nincs jogod a fájlok olvasásához.';
+$lang['media_perm_upload'] = 'Sajnáljuk, nincs jogod a feltöltéshez.';
+$lang['media_update'] = 'Új verzió feltöltése';
+$lang['media_restore'] = 'Ezen verzió visszaállítása';
diff --git a/inc/lang/hu/locked.txt b/inc/lang/hu/locked.txt
index 229141674..004c46191 100644
--- a/inc/lang/hu/locked.txt
+++ b/inc/lang/hu/locked.txt
@@ -1,4 +1,4 @@
====== Az oldal zárolva ======
-Ezt az oldalt épp szerkeszti egy másik felhasználó. Várnod kell, amíg a másik felhasználó befejezi, vagy amíg a zárolási időzítő le nem jár.
+Ezt az oldalt épp szerkeszti egy másik felhasználó. Várnod kell, amíg a másik felhasználó befejezi, vagy amíg a zárolási ideje le nem jár.
diff --git a/inc/lang/hu/mailwrap.html b/inc/lang/hu/mailwrap.html
new file mode 100644
index 000000000..50fc497fd
--- /dev/null
+++ b/inc/lang/hu/mailwrap.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>@TITLE@</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+
+@HTMLBODY@
+
+<br /><hr />
+<small>Ezt a levelet a @DOKUWIKIURL@ DokuWiki generálta.</small>
+</body>
+</html> \ No newline at end of file
diff --git a/inc/lang/hu/norev.txt b/inc/lang/hu/norev.txt
index 4dd408459..1f4e6725b 100644
--- a/inc/lang/hu/norev.txt
+++ b/inc/lang/hu/norev.txt
@@ -1,5 +1,5 @@
====== Nincs ilyen változat ======
-A megadott változat nem létezik. Használd az ''Előző változatok'' nyomógombot az előzmények listájának megtekintéséhez.
+A megadott változat nem létezik. Használd az ''Előző változatok'' gombot az előzmények listájának megtekintéséhez.
diff --git a/inc/lang/hu/preview.txt b/inc/lang/hu/preview.txt
index ad7f7d4b0..e04b2c838 100644
--- a/inc/lang/hu/preview.txt
+++ b/inc/lang/hu/preview.txt
@@ -1,4 +1,3 @@
====== Előnézet ======
-Ez a szöveged előnézete, így fog kinézni. Figyelj jól: ez **még nincs elmentve**!
-
+Ez a szöveged előnézete, így fog kinézni élesben. Viszont ez **még nincs elmentve**!
diff --git a/inc/lang/hu/pwconfirm.txt b/inc/lang/hu/pwconfirm.txt
index 617419ee8..da677d151 100644
--- a/inc/lang/hu/pwconfirm.txt
+++ b/inc/lang/hu/pwconfirm.txt
@@ -5,8 +5,8 @@ címen lévő @TITLE@ wiki felhasználódhoz.
Ha nem kértél ilyet, hagyd figyelmen kívül ezt a levelet.
-Ha Te voltál, az új jelszó kérelmed megerősítéséhez a
-következő linkre kattints, vagy másold a böngésződbe:
+Ha Te voltál, az új jelszó kérelmed megerősítéséhez kattints a
+következő linkre vagy másold a böngésződbe:
@CONFIRM@
diff --git a/inc/lang/hu/read.txt b/inc/lang/hu/read.txt
index 89ac96338..223a6fe1c 100644
--- a/inc/lang/hu/read.txt
+++ b/inc/lang/hu/read.txt
@@ -1,2 +1 @@
-Ez az oldal csak olvasható. Megtekintheted a forrását, de nem változtathatod meg. Ha úgy gondolod, hogy ez helytelen, kérdezd a Wiki-gazdát.
-
+Ez az oldal csak olvasható. Megtekintheted a forrását, de nem változtathatod meg. Ha úgy gondolod, hogy ez helytelen, kérdezd az Adminisztrátorokat!
diff --git a/inc/lang/hu/register.txt b/inc/lang/hu/register.txt
index 2745c4d77..523b720e7 100644
--- a/inc/lang/hu/register.txt
+++ b/inc/lang/hu/register.txt
@@ -1,4 +1,4 @@
====== Új felhasználó regisztrálása ======
-Töltsd ki az összes alábbi adatot az új Wiki felhasználói azonosítód létrehozásához. Győződj meg róla, hogy **érvényes e-mail címet** adtál meg -- az új jelszavad erre a címre küldjük el. Az azonosítód érvényes [[doku>pagename|oldalnév]] kell legyen.
+Töltsd ki az összes alábbi adatot az új Wiki felhasználói azonosítód létrehozásához. Győződj meg róla, hogy **érvényes e-mail címet** adtál meg, mivel az új jelszavad erre a címre küldjük el. Az azonosítód érvényes [[doku>pagename|oldalnév]] kell legyen.
diff --git a/inc/lang/hu/resendpwd.txt b/inc/lang/hu/resendpwd.txt
index 24931a7ed..b73fa42b2 100644
--- a/inc/lang/hu/resendpwd.txt
+++ b/inc/lang/hu/resendpwd.txt
@@ -1,3 +1,3 @@
===== Új jelszó kérése =====
-Kérlek add meg a felhasználó neved az új jelszó elküldéséhez. A jelszó cseréjéhez szükséges megerősítő linket a regisztrált e-mail címedre küldjük. \ No newline at end of file
+Kérlek, add meg a felhasználói azonosítód az új jelszó elküldéséhez. A jelszó cseréjéhez szükséges megerősítő linket elküldjük a regisztrált e-mail címedre. \ No newline at end of file
diff --git a/inc/lang/hu/resetpwd.txt b/inc/lang/hu/resetpwd.txt
new file mode 100644
index 000000000..53b28d75c
--- /dev/null
+++ b/inc/lang/hu/resetpwd.txt
@@ -0,0 +1,3 @@
+====== Új jelszó beállítása ======
+
+Kérlek, add meg az új jelszót a felhasználódhoz. \ No newline at end of file
diff --git a/inc/lang/hu/searchpage.txt b/inc/lang/hu/searchpage.txt
index b1defed84..ffde87b66 100644
--- a/inc/lang/hu/searchpage.txt
+++ b/inc/lang/hu/searchpage.txt
@@ -1,5 +1,5 @@
====== Keresés ======
-A keresés eredményét lentebb láthatod. Ha nem találtad meg amit kerestél, akkor létrehozhatsz egy új oldalt a keresésed alapján ''Az oldal szerkesztése'' gombbal.
+A keresés eredményét lentebb láthatod. Ha nem találtad meg amit kerestél, akkor létrehozhatsz egy új oldalt a keresésed alapján ''Az oldal szerkesztése'' gombbal.
===== Eredmény(ek) ===== \ No newline at end of file
diff --git a/inc/lang/hu/subscr_digest.txt b/inc/lang/hu/subscr_digest.txt
index 62e777faf..b00e0bba7 100644
--- a/inc/lang/hu/subscr_digest.txt
+++ b/inc/lang/hu/subscr_digest.txt
@@ -13,5 +13,4 @@ Régi verzió: @OLDPAGE@
Ha nem szeretnél értesítéseket kapni, jelentkezz be a wiki-be itt: @DOKUWIKIURL@, majd ezen az oldalon tudsz leiratkozni: @SUBSCRIBE@.
--
-Ezt a levelet a DokuWiki generálta
-@DOKUWIKIURL@ \ No newline at end of file
+Ezt a levelet a @DOKUWIKIURL@ DokuWiki generálta. \ No newline at end of file
diff --git a/inc/lang/hu/subscr_list.txt b/inc/lang/hu/subscr_list.txt
index f68e6fc0a..13295ff41 100644
--- a/inc/lang/hu/subscr_list.txt
+++ b/inc/lang/hu/subscr_list.txt
@@ -1,7 +1,7 @@
Szia,
A @PAGE@ névtérhez tartozó oldalak megváltoztak a @TITLE wikiben.
-Itt vannak a módosított oldalak:
+A módosított oldalak a következők:
--------------------------------------------------------
@DIFF@
@@ -10,5 +10,4 @@ Itt vannak a módosított oldalak:
Ha nem szeretnél értesítéseket kapni, jelentkezz be a wiki-be itt: @DOKUWIKIURL@, majd ezen az oldalon tudsz leiratkozni: @SUBSCRIBE@.
--
-Ezt a levelet a DokuWiki generálta
-@DOKUWIKIURL@ \ No newline at end of file
+Ezt a levelet a @DOKUWIKIURL@ DokuWiki generálta. \ No newline at end of file
diff --git a/inc/lang/hu/subscr_single.txt b/inc/lang/hu/subscr_single.txt
index a17a98cfd..e28226de5 100644
--- a/inc/lang/hu/subscr_single.txt
+++ b/inc/lang/hu/subscr_single.txt
@@ -1,7 +1,7 @@
Szia,
A @PAGE@ oldal a @TITLE wikiben megváltozott.
-Itt vannak az eltérések:
+Az eltérések a következők:
--------------------------------------------------------
@DIFF@
diff --git a/inc/lang/ko/edit.txt b/inc/lang/ko/edit.txt
index 97927b7fe..87d1a9a95 100644
--- a/inc/lang/ko/edit.txt
+++ b/inc/lang/ko/edit.txt
@@ -1 +1 @@
-문서를 편집하고 **저장**을 누르세요. 위키 구문은 [[wiki:syntax]] 또는 [[wiki:ko_syntax|(한국어) 구문]]을 참고하세요. 이 문서를 **더 좋게 만들 자신이 있을 때**에만 편집하세요. 연습을 하고 싶다면 먼저 [[playground:playground|연습장]]에 가서 연습하세요. \ No newline at end of file
+문서를 편집하고 **저장**을 누르세요. 위키 구문은 [[wiki:syntax]]를 참고하세요. 이 문서를 **더 좋게 만들 자신이 있을 때**에만 편집하세요. 연습을 하고 싶다면 먼저 [[playground:playground|연습장]]에 가서 연습하세요. \ No newline at end of file
diff --git a/inc/lang/ko/index.txt b/inc/lang/ko/index.txt
index 058f04254..a98bf877e 100644
--- a/inc/lang/ko/index.txt
+++ b/inc/lang/ko/index.txt
@@ -1,3 +1,3 @@
====== 사이트맵 ======
-[[doku>namespaces|이름공간]]에서 정렬한 모든 문서의 목록입니다. \ No newline at end of file
+[[doku>ko:namespaces|이름공간]]에서 정렬한 모든 문서의 목록입니다. \ No newline at end of file
diff --git a/inc/lang/ko/install.html b/inc/lang/ko/install.html
index a9961b47e..886ed2d30 100644
--- a/inc/lang/ko/install.html
+++ b/inc/lang/ko/install.html
@@ -1,6 +1,5 @@
<p>이 페이지는 <a href="http://dokuwiki.org">Dokuwiki</a> 설치와 환경 설정을 도와줍니다.
-설치 과정에 대한 더 자세한 정보는 <a href="http://dokuwiki.org/ko:install">(한국어) 설치 문서</a>와
-<a href="http://dokuwiki.org/install">(영어) 설치 문서</a>를 참고하시기 바랍니다.</p>
+설치 과정에 대한 더 자세한 정보는 <a href="http://dokuwiki.org/ko:installer">관련 문서</a>를 참고하시기 바랍니다.</p>
<p>DokuWiki는 위키 문서와 문서와 관련된 정보(예를 들어 그림, 검색 색인, 이전 판 문서)를 저장하기 위해 일반적인 텍스트 파일을 사용합니다. 정상적으로 DokuWiki를 사용하려면 이 파일을 담고 있는 디렉토리에 대한 쓰기 권한을 가지고 있어야 합니다.
현재 설치 과정 중에는 디렉토리 권한 설정이 불가능합니다. 보통 직접 셸 명령어를 사용하거나, 호스팅을 사용한다면 FTP나 호스팅 제어판(예를 들어 CPanel)을 사용해서 설정해야 합니다.</p>
@@ -8,8 +7,4 @@
<p>현재 설치 과정중에 관리자로 로그인 후 DokuWiki의 관리 메뉴(플러그인 설치, 사용자 관리, 위키 문서 접근 권한 관리, 옵션 설정)를 가능하게 <acronym title="접근 제어 목록">ACL</acronym>에 대한 환경 설정을 수행합니다.
DokuWiki가 동작하는데 필요한 사항은 아니지만, 어쨌든 더 쉽게 관리자가 관리할 수 있도록 해줍니다.</p>
-<p>숙련된 사용자나 특별한 설치 과정이 필요한 경우에 다음 링크를 참고하시기 바랍니다:
-<a href="http://dokuwiki.org/ko:install">설치 과정 (한국어)</a>
-과 <a href="http://dokuwiki.org/ko:config">환경 설정 (한국어),</a>
-<a href="http://dokuwiki.org/install">설치 과정 (영어)</a>
-과 <a href="http://dokuwiki.org/config">환경 설정 (영어)</a></p> \ No newline at end of file
+<p>숙련된 사용자나 특별한 설치 과정이 필요한 경우에는 <a href="http://dokuwiki.org/ko:install">설치 과정</a>과 <a href="http://dokuwiki.org/ko:config">환경 설정</a> 링크를 참고하시기 바랍니다.</p> \ No newline at end of file
diff --git a/inc/lang/ko/lang.php b/inc/lang/ko/lang.php
index 76684659c..71edc2a3e 100644
--- a/inc/lang/ko/lang.php
+++ b/inc/lang/ko/lang.php
@@ -71,8 +71,8 @@ $lang['regmissing'] = '모든 항목을 입력해야 합니다.';
$lang['reguexists'] = '같은 이름을 사용하는 사용자가 있습니다.';
$lang['regsuccess'] = '사용자를 만들었으며 비밀번호는 이메일로 보냈습니다.';
$lang['regsuccess2'] = '사용자를 만들었습니다.';
-$lang['regmailfail'] = '비밀번호를 이메일로 보낼 때 오류가 발생했습니다. 관리자에게 문의하시기 바랍니다!';
-$lang['regbadmail'] = '이메일 주소가 잘못됐습니다 - 오류라고 생각하면 관리자에게 문의하시기 바랍니다';
+$lang['regmailfail'] = '비밀번호를 이메일로 보낼 때 오류가 발생했습니다. 관리자에게 문의하세요!';
+$lang['regbadmail'] = '이메일 주소가 잘못됐습니다 - 오류라고 생각하면 관리자에게 문의하세요';
$lang['regbadpass'] = '새 비밀번호가 일치하지 않습니다. 다시 입력하세요.';
$lang['regpwmail'] = 'DokuWiki 비밀번호';
$lang['reghere'] = '계정이 없나요? 계정을 등록할 수 있습니다';
@@ -109,7 +109,7 @@ $lang['js']['mediaalign'] = '배치';
$lang['js']['mediasize'] = '그림 크기';
$lang['js']['mediatarget'] = '링크 목표';
$lang['js']['mediaclose'] = '닫기';
-$lang['js']['mediainsert'] = '삽입';
+$lang['js']['mediainsert'] = '넣기';
$lang['js']['mediadisplayimg'] = '그림을 보여줍니다.';
$lang['js']['mediadisplaylnk'] = '링크만 보여줍니다.';
$lang['js']['mediasmall'] = '작게';
@@ -272,7 +272,7 @@ $lang['i_enableacl'] = 'ACL 기능 사용 (권장)';
$lang['i_superuser'] = '슈퍼 유저';
$lang['i_problems'] = '설치하는 동안 아래와 같은 문제가 발생했습니다. 문제를 해결한 후 설치를 계속하세요.';
$lang['i_modified'] = '보안 상의 이유로 이 스크립트는 수정되지 않은 새 Dokuwiki 설치에서만 동작됩니다.
-다운로드한 압축 패키지를 다시 설치하거나 <a href="http://dokuwiki.org/install">DokuWiki 설치 과정</a>을 참고해서 설치하세요.';
+다운로드한 압축 패키지를 다시 설치하거나 <a href="http://dokuwiki.org/ko:install">DokuWiki 설치 과정</a>을 참고해서 설치하세요.';
$lang['i_funcna'] = '<code>%s</code> PHP 함수의 사용이 불가능합니다. 호스트 제공자가 어떤 이유에서인지 막아 놓았을지 모릅니다.';
$lang['i_phpver'] = 'PHP <code>%s</code> 버전은 필요한 <code>%s</code> 버전보다 오래되었습니다. PHP를 업그레이드할 필요가 있습니다.';
$lang['i_permfail'] = 'DokuWiki는 <code>%s</code>에 쓰기 가능 권한이 없습니다. 먼저 이 디렉토리에 쓰기 권한이 설정되어야 합니다!';
diff --git a/inc/lang/ko/read.txt b/inc/lang/ko/read.txt
index 8f080fcb1..079b8e130 100644
--- a/inc/lang/ko/read.txt
+++ b/inc/lang/ko/read.txt
@@ -1 +1 @@
-이 문서는 읽기 전용입니다. 내용을 볼 수는 있지만 바꿀 수는 없습니다. 문제가 있다고 생각하면 관리자에게 문의하세요. \ No newline at end of file
+이 문서는 읽기 전용입니다. 원본을 볼 수는 있지만 바꿀 수는 없습니다. 문제가 있다고 생각하면 관리자에게 문의하세요. \ No newline at end of file
diff --git a/inc/lang/ko/register.txt b/inc/lang/ko/register.txt
index 6509bed91..4df968896 100644
--- a/inc/lang/ko/register.txt
+++ b/inc/lang/ko/register.txt
@@ -1,3 +1,3 @@
====== 새 사용자 등록 ======
-이 위키에 새 계정을 만드려면 아래의 모든 내용을 입력하세요. **올바른 이메일 주소**를 사용하세요. 비밀번호를 입력하는 곳이 없다면 비밀번호는 이 이메일로 보내집니다. 사용자 이름은 올바른 [[doku>pagename|pagename]]이어야 합니다. \ No newline at end of file
+이 위키에 새 계정을 만드려면 아래의 모든 내용을 입력하세요. **올바른 이메일 주소**를 사용하세요. 비밀번호를 입력하는 곳이 없다면 비밀번호는 이 이메일로 보내집니다. 사용자 이름은 올바른 [[doku>ko:pagename|문서이름]]이어야 합니다. \ No newline at end of file
diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php
index 9608784c6..b00c61054 100644
--- a/inc/lang/sv/lang.php
+++ b/inc/lang/sv/lang.php
@@ -1,12 +1,11 @@
<?php
+
/**
- * Swedish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Joaquim Homrighausen <joho@webbplatsen.se>
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
* @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
@@ -18,6 +17,7 @@
* @author Peter Åström <eaustreum@gmail.com>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
+ * @author Henrik <henrik@idealis.se>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -61,6 +61,7 @@ $lang['btn_revert'] = 'Återställ';
$lang['btn_register'] = 'Registrera';
$lang['btn_apply'] = 'Verkställ';
$lang['btn_media'] = 'Media Hanteraren';
+$lang['btn_deleteuser'] = 'Ta bort Mitt Konto';
$lang['loggedinas'] = 'Inloggad som';
$lang['user'] = 'Användarnamn';
$lang['pass'] = 'Lösenord';
@@ -72,6 +73,7 @@ $lang['fullname'] = 'Namn';
$lang['email'] = 'E-post';
$lang['profile'] = 'Användarprofil';
$lang['badlogin'] = 'Felaktigt användarnamn eller lösenord.';
+$lang['badpassconfirm'] = 'Ledsen, lösenordet var felaktigt';
$lang['minoredit'] = 'Små ändringar';
$lang['draftdate'] = 'Utkast automatiskt sparat';
$lang['nosecedit'] = 'Sidan ändrades medan du skrev, sektionsinformationen var inte uppdaterad. Laddar hela sidan istället.';
@@ -88,6 +90,11 @@ $lang['profna'] = 'Denna wiki stödjer inte ändringar av profile
$lang['profnochange'] = 'Ingenting ändrades, inget att göra.';
$lang['profnoempty'] = 'Namn och e-postadress måste fyllas i.';
$lang['profchanged'] = 'Användarprofilen uppdaterad.';
+$lang['profnodelete'] = 'Den här wiki:n stödjer ej borttagning av användare';
+$lang['profdeleteuser'] = 'Radera kontot';
+$lang['profdeleted'] = 'Ditt användarkonto har raderats från den här wiki:n';
+$lang['profconfdelete'] = 'Jag vill ta bort mitt konto/inlogg på den här wiki:n <br/> Denna åtgärd går ej att ångra.';
+$lang['profconfdeletemissing'] = 'Bekräftelse-kryssrutan är ej markerad';
$lang['pwdforget'] = 'Glömt ditt lösenord? Ordna ett nytt';
$lang['resendna'] = 'Den här wikin stödjer inte utskick av lösenord.';
$lang['resendpwd'] = 'Sätt lösenord för';
@@ -310,6 +317,7 @@ $lang['media_searchtab'] = 'Sök';
$lang['media_file'] = 'Fil';
$lang['media_viewtab'] = 'Visa';
$lang['media_edittab'] = 'Redigera';
+$lang['media_historytab'] = 'Historik';
$lang['media_list_thumbs'] = 'Miniatyrbild';
$lang['media_list_rows'] = 'Rader';
$lang['media_sort_name'] = 'Namn';
@@ -321,6 +329,7 @@ $lang['media_search'] = 'Sök i %s';
$lang['media_view'] = '%s';
$lang['media_viewold'] = '%s vid %s';
$lang['media_edit'] = 'Redigera %s';
+$lang['media_history'] = '%s-historik';
$lang['media_meta_edited'] = 'metadata redigerat';
$lang['media_perm_read'] = 'Du har tyvärr inte tillräckliga behörigheter för att läsa filer.';
$lang['media_perm_upload'] = 'Du har tyvärr inte tillräckliga behörigheter för att ladda upp filer.';
diff --git a/inc/lessc.inc.php b/inc/lessc.inc.php
new file mode 100644
index 000000000..5c81ad2a9
--- /dev/null
+++ b/inc/lessc.inc.php
@@ -0,0 +1,3481 @@
+<?php
+
+/**
+ * lessphp v0.3.9
+ * http://leafo.net/lessphp
+ *
+ * LESS css compiler, adapted from http://lesscss.org
+ *
+ * Copyright 2012, Leaf Corcoran <leafot@gmail.com>
+ * Licensed under MIT or GPLv3, see LICENSE
+ */
+
+
+/**
+ * The less compiler and parser.
+ *
+ * Converting LESS to CSS is a three stage process. The incoming file is parsed
+ * by `lessc_parser` into a syntax tree, then it is compiled into another tree
+ * representing the CSS structure by `lessc`. The CSS tree is fed into a
+ * formatter, like `lessc_formatter` which then outputs CSS as a string.
+ *
+ * During the first compile, all values are *reduced*, which means that their
+ * types are brought to the lowest form before being dump as strings. This
+ * handles math equations, variable dereferences, and the like.
+ *
+ * The `parse` function of `lessc` is the entry point.
+ *
+ * In summary:
+ *
+ * The `lessc` class creates an intstance of the parser, feeds it LESS code,
+ * then transforms the resulting tree to a CSS tree. This class also holds the
+ * evaluation context, such as all available mixins and variables at any given
+ * time.
+ *
+ * The `lessc_parser` class is only concerned with parsing its input.
+ *
+ * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
+ * handling things like indentation.
+ */
+class lessc {
+ static public $VERSION = "v0.3.9";
+ static protected $TRUE = array("keyword", "true");
+ static protected $FALSE = array("keyword", "false");
+
+ protected $libFunctions = array();
+ protected $registeredVars = array();
+ protected $preserveComments = false;
+
+ public $vPrefix = '@'; // prefix of abstract properties
+ public $mPrefix = '$'; // prefix of abstract blocks
+ public $parentSelector = '&';
+
+ public $importDisabled = false;
+ public $importDir = '';
+
+ protected $numberPrecision = null;
+
+ // set to the parser that generated the current line when compiling
+ // so we know how to create error messages
+ protected $sourceParser = null;
+ protected $sourceLoc = null;
+
+ static public $defaultValue = array("keyword", "");
+
+ static protected $nextImportId = 0; // uniquely identify imports
+
+ // attempts to find the path of an import url, returns null for css files
+ protected function findImport($url) {
+ foreach ((array)$this->importDir as $dir) {
+ $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
+ if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
+ return $file;
+ }
+ }
+
+ return null;
+ }
+
+ protected function fileExists($name) {
+ return is_file($name);
+ }
+
+ static public function compressList($items, $delim) {
+ if (!isset($items[1]) && isset($items[0])) return $items[0];
+ else return array('list', $delim, $items);
+ }
+
+ static public function preg_quote($what) {
+ return preg_quote($what, '/');
+ }
+
+ protected function tryImport($importPath, $parentBlock, $out) {
+ if ($importPath[0] == "function" && $importPath[1] == "url") {
+ $importPath = $this->flattenList($importPath[2]);
+ }
+
+ $str = $this->coerceString($importPath);
+ if ($str === null) return false;
+
+ $url = $this->compileValue($this->lib_e($str));
+
+ // don't import if it ends in css
+ if (substr_compare($url, '.css', -4, 4) === 0) return false;
+
+ $realPath = $this->findImport($url);
+ if ($realPath === null) return false;
+
+ if ($this->importDisabled) {
+ return array(false, "/* import disabled */");
+ }
+
+ $this->addParsedFile($realPath);
+ $parser = $this->makeParser($realPath);
+ $root = $parser->parse(file_get_contents($realPath));
+
+ // set the parents of all the block props
+ foreach ($root->props as $prop) {
+ if ($prop[0] == "block") {
+ $prop[1]->parent = $parentBlock;
+ }
+ }
+
+ // copy mixins into scope, set their parents
+ // bring blocks from import into current block
+ // TODO: need to mark the source parser these came from this file
+ foreach ($root->children as $childName => $child) {
+ if (isset($parentBlock->children[$childName])) {
+ $parentBlock->children[$childName] = array_merge(
+ $parentBlock->children[$childName],
+ $child);
+ } else {
+ $parentBlock->children[$childName] = $child;
+ }
+ }
+
+ $pi = pathinfo($realPath);
+ $dir = $pi["dirname"];
+
+ list($top, $bottom) = $this->sortProps($root->props, true);
+ $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);
+
+ return array(true, $bottom, $parser, $dir);
+ }
+
+ protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
+ $oldSourceParser = $this->sourceParser;
+
+ $oldImport = $this->importDir;
+
+ // TODO: this is because the importDir api is stupid
+ $this->importDir = (array)$this->importDir;
+ array_unshift($this->importDir, $importDir);
+
+ foreach ($props as $prop) {
+ $this->compileProp($prop, $block, $out);
+ }
+
+ $this->importDir = $oldImport;
+ $this->sourceParser = $oldSourceParser;
+ }
+
+ /**
+ * Recursively compiles a block.
+ *
+ * A block is analogous to a CSS block in most cases. A single LESS document
+ * is encapsulated in a block when parsed, but it does not have parent tags
+ * so all of it's children appear on the root level when compiled.
+ *
+ * Blocks are made up of props and children.
+ *
+ * Props are property instructions, array tuples which describe an action
+ * to be taken, eg. write a property, set a variable, mixin a block.
+ *
+ * The children of a block are just all the blocks that are defined within.
+ * This is used to look up mixins when performing a mixin.
+ *
+ * Compiling the block involves pushing a fresh environment on the stack,
+ * and iterating through the props, compiling each one.
+ *
+ * See lessc::compileProp()
+ *
+ */
+ protected function compileBlock($block) {
+ switch ($block->type) {
+ case "root":
+ $this->compileRoot($block);
+ break;
+ case null:
+ $this->compileCSSBlock($block);
+ break;
+ case "media":
+ $this->compileMedia($block);
+ break;
+ case "directive":
+ $name = "@" . $block->name;
+ if (!empty($block->value)) {
+ $name .= " " . $this->compileValue($this->reduce($block->value));
+ }
+
+ $this->compileNestedBlock($block, array($name));
+ break;
+ default:
+ $this->throwError("unknown block type: $block->type\n");
+ }
+ }
+
+ protected function compileCSSBlock($block) {
+ $env = $this->pushEnv();
+
+ $selectors = $this->compileSelectors($block->tags);
+ $env->selectors = $this->multiplySelectors($selectors);
+ $out = $this->makeOutputBlock(null, $env->selectors);
+
+ $this->scope->children[] = $out;
+ $this->compileProps($block, $out);
+
+ $block->scope = $env; // mixins carry scope with them!
+ $this->popEnv();
+ }
+
+ protected function compileMedia($media) {
+ $env = $this->pushEnv($media);
+ $parentScope = $this->mediaParent($this->scope);
+
+ $query = $this->compileMediaQuery($this->multiplyMedia($env));
+
+ $this->scope = $this->makeOutputBlock($media->type, array($query));
+ $parentScope->children[] = $this->scope;
+
+ $this->compileProps($media, $this->scope);
+
+ if (count($this->scope->lines) > 0) {
+ $orphanSelelectors = $this->findClosestSelectors();
+ if (!is_null($orphanSelelectors)) {
+ $orphan = $this->makeOutputBlock(null, $orphanSelelectors);
+ $orphan->lines = $this->scope->lines;
+ array_unshift($this->scope->children, $orphan);
+ $this->scope->lines = array();
+ }
+ }
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function mediaParent($scope) {
+ while (!empty($scope->parent)) {
+ if (!empty($scope->type) && $scope->type != "media") {
+ break;
+ }
+ $scope = $scope->parent;
+ }
+
+ return $scope;
+ }
+
+ protected function compileNestedBlock($block, $selectors) {
+ $this->pushEnv($block);
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->parent->children[] = $this->scope;
+
+ $this->compileProps($block, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function compileRoot($root) {
+ $this->pushEnv();
+ $this->scope = $this->makeOutputBlock($root->type);
+ $this->compileProps($root, $this->scope);
+ $this->popEnv();
+ }
+
+ protected function compileProps($block, $out) {
+ foreach ($this->sortProps($block->props) as $prop) {
+ $this->compileProp($prop, $block, $out);
+ }
+ }
+
+ protected function sortProps($props, $split = false) {
+ $vars = array();
+ $imports = array();
+ $other = array();
+
+ foreach ($props as $prop) {
+ switch ($prop[0]) {
+ case "assign":
+ if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
+ $vars[] = $prop;
+ } else {
+ $other[] = $prop;
+ }
+ break;
+ case "import":
+ $id = self::$nextImportId++;
+ $prop[] = $id;
+ $imports[] = $prop;
+ $other[] = array("import_mixin", $id);
+ break;
+ default:
+ $other[] = $prop;
+ }
+ }
+
+ if ($split) {
+ return array(array_merge($vars, $imports), $other);
+ } else {
+ return array_merge($vars, $imports, $other);
+ }
+ }
+
+ protected function compileMediaQuery($queries) {
+ $compiledQueries = array();
+ foreach ($queries as $query) {
+ $parts = array();
+ foreach ($query as $q) {
+ switch ($q[0]) {
+ case "mediaType":
+ $parts[] = implode(" ", array_slice($q, 1));
+ break;
+ case "mediaExp":
+ if (isset($q[2])) {
+ $parts[] = "($q[1]: " .
+ $this->compileValue($this->reduce($q[2])) . ")";
+ } else {
+ $parts[] = "($q[1])";
+ }
+ break;
+ case "variable":
+ $parts[] = $this->compileValue($this->reduce($q));
+ break;
+ }
+ }
+
+ if (count($parts) > 0) {
+ $compiledQueries[] = implode(" and ", $parts);
+ }
+ }
+
+ $out = "@media";
+ if (!empty($parts)) {
+ $out .= " " .
+ implode($this->formatter->selectorSeparator, $compiledQueries);
+ }
+ return $out;
+ }
+
+ protected function multiplyMedia($env, $childQueries = null) {
+ if (is_null($env) ||
+ !empty($env->block->type) && $env->block->type != "media")
+ {
+ return $childQueries;
+ }
+
+ // plain old block, skip
+ if (empty($env->block->type)) {
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ $out = array();
+ $queries = $env->block->queries;
+ if (is_null($childQueries)) {
+ $out = $queries;
+ } else {
+ foreach ($queries as $parent) {
+ foreach ($childQueries as $child) {
+ $out[] = array_merge($parent, $child);
+ }
+ }
+ }
+
+ return $this->multiplyMedia($env->parent, $out);
+ }
+
+ protected function expandParentSelectors(&$tag, $replace) {
+ $parts = explode("$&$", $tag);
+ $count = 0;
+ foreach ($parts as &$part) {
+ $part = str_replace($this->parentSelector, $replace, $part, $c);
+ $count += $c;
+ }
+ $tag = implode($this->parentSelector, $parts);
+ return $count;
+ }
+
+ protected function findClosestSelectors() {
+ $env = $this->env;
+ $selectors = null;
+ while ($env !== null) {
+ if (isset($env->selectors)) {
+ $selectors = $env->selectors;
+ break;
+ }
+ $env = $env->parent;
+ }
+
+ return $selectors;
+ }
+
+
+ // multiply $selectors against the nearest selectors in env
+ protected function multiplySelectors($selectors) {
+ // find parent selectors
+
+ $parentSelectors = $this->findClosestSelectors();
+ if (is_null($parentSelectors)) {
+ // kill parent reference in top level selector
+ foreach ($selectors as &$s) {
+ $this->expandParentSelectors($s, "");
+ }
+
+ return $selectors;
+ }
+
+ $out = array();
+ foreach ($parentSelectors as $parent) {
+ foreach ($selectors as $child) {
+ $count = $this->expandParentSelectors($child, $parent);
+
+ // don't prepend the parent tag if & was used
+ if ($count > 0) {
+ $out[] = trim($child);
+ } else {
+ $out[] = trim($parent . ' ' . $child);
+ }
+ }
+ }
+
+ return $out;
+ }
+
+ // reduces selector expressions
+ protected function compileSelectors($selectors) {
+ $out = array();
+
+ foreach ($selectors as $s) {
+ if (is_array($s)) {
+ list(, $value) = $s;
+ $out[] = trim($this->compileValue($this->reduce($value)));
+ } else {
+ $out[] = $s;
+ }
+ }
+
+ return $out;
+ }
+
+ protected function eq($left, $right) {
+ return $left == $right;
+ }
+
+ protected function patternMatch($block, $callingArgs) {
+ // match the guards if it has them
+ // any one of the groups must have all its guards pass for a match
+ if (!empty($block->guards)) {
+ $groupPassed = false;
+ foreach ($block->guards as $guardGroup) {
+ foreach ($guardGroup as $guard) {
+ $this->pushEnv();
+ $this->zipSetArgs($block->args, $callingArgs);
+
+ $negate = false;
+ if ($guard[0] == "negate") {
+ $guard = $guard[1];
+ $negate = true;
+ }
+
+ $passed = $this->reduce($guard) == self::$TRUE;
+ if ($negate) $passed = !$passed;
+
+ $this->popEnv();
+
+ if ($passed) {
+ $groupPassed = true;
+ } else {
+ $groupPassed = false;
+ break;
+ }
+ }
+
+ if ($groupPassed) break;
+ }
+
+ if (!$groupPassed) {
+ return false;
+ }
+ }
+
+ $numCalling = count($callingArgs);
+
+ if (empty($block->args)) {
+ return $block->isVararg || $numCalling == 0;
+ }
+
+ $i = -1; // no args
+ // try to match by arity or by argument literal
+ foreach ($block->args as $i => $arg) {
+ switch ($arg[0]) {
+ case "lit":
+ if (empty($callingArgs[$i]) || !$this->eq($arg[1], $callingArgs[$i])) {
+ return false;
+ }
+ break;
+ case "arg":
+ // no arg and no default value
+ if (!isset($callingArgs[$i]) && !isset($arg[2])) {
+ return false;
+ }
+ break;
+ case "rest":
+ $i--; // rest can be empty
+ break 2;
+ }
+ }
+
+ if ($block->isVararg) {
+ return true; // not having enough is handled above
+ } else {
+ $numMatched = $i + 1;
+ // greater than becuase default values always match
+ return $numMatched >= $numCalling;
+ }
+ }
+
+ protected function patternMatchAll($blocks, $callingArgs) {
+ $matches = null;
+ foreach ($blocks as $block) {
+ if ($this->patternMatch($block, $callingArgs)) {
+ $matches[] = $block;
+ }
+ }
+
+ return $matches;
+ }
+
+ // attempt to find blocks matched by path and args
+ protected function findBlocks($searchIn, $path, $args, $seen=array()) {
+ if ($searchIn == null) return null;
+ if (isset($seen[$searchIn->id])) return null;
+ $seen[$searchIn->id] = true;
+
+ $name = $path[0];
+
+ if (isset($searchIn->children[$name])) {
+ $blocks = $searchIn->children[$name];
+ if (count($path) == 1) {
+ $matches = $this->patternMatchAll($blocks, $args);
+ if (!empty($matches)) {
+ // This will return all blocks that match in the closest
+ // scope that has any matching block, like lessjs
+ return $matches;
+ }
+ } else {
+ $matches = array();
+ foreach ($blocks as $subBlock) {
+ $subMatches = $this->findBlocks($subBlock,
+ array_slice($path, 1), $args, $seen);
+
+ if (!is_null($subMatches)) {
+ foreach ($subMatches as $sm) {
+ $matches[] = $sm;
+ }
+ }
+ }
+
+ return count($matches) > 0 ? $matches : null;
+ }
+ }
+
+ if ($searchIn->parent === $searchIn) return null;
+ return $this->findBlocks($searchIn->parent, $path, $args, $seen);
+ }
+
+ // sets all argument names in $args to either the default value
+ // or the one passed in through $values
+ protected function zipSetArgs($args, $values) {
+ $i = 0;
+ $assignedValues = array();
+ foreach ($args as $a) {
+ if ($a[0] == "arg") {
+ if ($i < count($values) && !is_null($values[$i])) {
+ $value = $values[$i];
+ } elseif (isset($a[2])) {
+ $value = $a[2];
+ } else $value = null;
+
+ $value = $this->reduce($value);
+ $this->set($a[1], $value);
+ $assignedValues[] = $value;
+ }
+ $i++;
+ }
+
+ // check for a rest
+ $last = end($args);
+ if ($last[0] == "rest") {
+ $rest = array_slice($values, count($args) - 1);
+ $this->set($last[1], $this->reduce(array("list", " ", $rest)));
+ }
+
+ $this->env->arguments = $assignedValues;
+ }
+
+ // compile a prop and update $lines or $blocks appropriately
+ protected function compileProp($prop, $block, $out) {
+ // set error position context
+ $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;
+
+ switch ($prop[0]) {
+ case 'assign':
+ list(, $name, $value) = $prop;
+ if ($name[0] == $this->vPrefix) {
+ $this->set($name, $value);
+ } else {
+ $out->lines[] = $this->formatter->property($name,
+ $this->compileValue($this->reduce($value)));
+ }
+ break;
+ case 'block':
+ list(, $child) = $prop;
+ $this->compileBlock($child);
+ break;
+ case 'mixin':
+ list(, $path, $args, $suffix) = $prop;
+
+ $args = array_map(array($this, "reduce"), (array)$args);
+ $mixins = $this->findBlocks($block, $path, $args);
+
+ if ($mixins === null) {
+ // fwrite(STDERR,"failed to find block: ".implode(" > ", $path)."\n");
+ break; // throw error here??
+ }
+
+ foreach ($mixins as $mixin) {
+ if ($mixin === $block && !$args) {
+ continue;
+ }
+
+ $haveScope = false;
+ if (isset($mixin->parent->scope)) {
+ $haveScope = true;
+ $mixinParentEnv = $this->pushEnv();
+ $mixinParentEnv->storeParent = $mixin->parent->scope;
+ }
+
+ $haveArgs = false;
+ if (isset($mixin->args)) {
+ $haveArgs = true;
+ $this->pushEnv();
+ $this->zipSetArgs($mixin->args, $args);
+ }
+
+ $oldParent = $mixin->parent;
+ if ($mixin != $block) $mixin->parent = $block;
+
+ foreach ($this->sortProps($mixin->props) as $subProp) {
+ if ($suffix !== null &&
+ $subProp[0] == "assign" &&
+ is_string($subProp[1]) &&
+ $subProp[1]{0} != $this->vPrefix)
+ {
+ $subProp[2] = array(
+ 'list', ' ',
+ array($subProp[2], array('keyword', $suffix))
+ );
+ }
+
+ $this->compileProp($subProp, $mixin, $out);
+ }
+
+ $mixin->parent = $oldParent;
+
+ if ($haveArgs) $this->popEnv();
+ if ($haveScope) $this->popEnv();
+ }
+
+ break;
+ case 'raw':
+ $out->lines[] = $prop[1];
+ break;
+ case "directive":
+ list(, $name, $value) = $prop;
+ $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
+ break;
+ case "comment":
+ $out->lines[] = $prop[1];
+ break;
+ case "import";
+ list(, $importPath, $importId) = $prop;
+ $importPath = $this->reduce($importPath);
+
+ if (!isset($this->env->imports)) {
+ $this->env->imports = array();
+ }
+
+ $result = $this->tryImport($importPath, $block, $out);
+
+ $this->env->imports[$importId] = $result === false ?
+ array(false, "@import " . $this->compileValue($importPath).";") :
+ $result;
+
+ break;
+ case "import_mixin":
+ list(,$importId) = $prop;
+ $import = $this->env->imports[$importId];
+ if ($import[0] === false) {
+ $out->lines[] = $import[1];
+ } else {
+ list(, $bottom, $parser, $importDir) = $import;
+ $this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
+ }
+
+ break;
+ default:
+ $this->throwError("unknown op: {$prop[0]}\n");
+ }
+ }
+
+
+ /**
+ * Compiles a primitive value into a CSS property value.
+ *
+ * Values in lessphp are typed by being wrapped in arrays, their format is
+ * typically:
+ *
+ * array(type, contents [, additional_contents]*)
+ *
+ * The input is expected to be reduced. This function will not work on
+ * things like expressions and variables.
+ */
+ protected function compileValue($value) {
+ switch ($value[0]) {
+ case 'list':
+ // [1] - delimiter
+ // [2] - array of values
+ return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
+ case 'raw_color':
+ if (!empty($this->formatter->compressColors)) {
+ return $this->compileValue($this->coerceColor($value));
+ }
+ return $value[1];
+ case 'keyword':
+ // [1] - the keyword
+ return $value[1];
+ case 'number':
+ list(, $num, $unit) = $value;
+ // [1] - the number
+ // [2] - the unit
+ if ($this->numberPrecision !== null) {
+ $num = round($num, $this->numberPrecision);
+ }
+ return $num . $unit;
+ case 'string':
+ // [1] - contents of string (includes quotes)
+ list(, $delim, $content) = $value;
+ foreach ($content as &$part) {
+ if (is_array($part)) {
+ $part = $this->compileValue($part);
+ }
+ }
+ return $delim . implode($content) . $delim;
+ case 'color':
+ // [1] - red component (either number or a %)
+ // [2] - green component
+ // [3] - blue component
+ // [4] - optional alpha component
+ list(, $r, $g, $b) = $value;
+ $r = round($r);
+ $g = round($g);
+ $b = round($b);
+
+ if (count($value) == 5 && $value[4] != 1) { // rgba
+ return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
+ }
+
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
+
+ if (!empty($this->formatter->compressColors)) {
+ // Converting hex color to short notation (e.g. #003399 to #039)
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
+ $h = '#' . $h[1] . $h[3] . $h[5];
+ }
+ }
+
+ return $h;
+
+ case 'function':
+ list(, $name, $args) = $value;
+ return $name.'('.$this->compileValue($args).')';
+ default: // assumed to be unit
+ $this->throwError("unknown value type: $value[0]");
+ }
+ }
+
+ protected function lib_isnumber($value) {
+ return $this->toBool($value[0] == "number");
+ }
+
+ protected function lib_isstring($value) {
+ return $this->toBool($value[0] == "string");
+ }
+
+ protected function lib_iscolor($value) {
+ return $this->toBool($this->coerceColor($value));
+ }
+
+ protected function lib_iskeyword($value) {
+ return $this->toBool($value[0] == "keyword");
+ }
+
+ protected function lib_ispixel($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "px");
+ }
+
+ protected function lib_ispercentage($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "%");
+ }
+
+ protected function lib_isem($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "em");
+ }
+
+ protected function lib_isrem($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "rem");
+ }
+
+ protected function lib_rgbahex($color) {
+ $color = $this->coerceColor($color);
+ if (is_null($color))
+ $this->throwError("color expected for rgbahex");
+
+ return sprintf("#%02x%02x%02x%02x",
+ isset($color[4]) ? $color[4]*255 : 255,
+ $color[1],$color[2], $color[3]);
+ }
+
+ protected function lib_argb($color){
+ return $this->lib_rgbahex($color);
+ }
+
+ // utility func to unquote a string
+ protected function lib_e($arg) {
+ switch ($arg[0]) {
+ case "list":
+ $items = $arg[2];
+ if (isset($items[0])) {
+ return $this->lib_e($items[0]);
+ }
+ return self::$defaultValue;
+ case "string":
+ $arg[1] = "";
+ return $arg;
+ case "keyword":
+ return $arg;
+ default:
+ return array("keyword", $this->compileValue($arg));
+ }
+ }
+
+ protected function lib__sprintf($args) {
+ if ($args[0] != "list") return $args;
+ $values = $args[2];
+ $string = array_shift($values);
+ $template = $this->compileValue($this->lib_e($string));
+
+ $i = 0;
+ if (preg_match_all('/%[dsa]/', $template, $m)) {
+ foreach ($m[0] as $match) {
+ $val = isset($values[$i]) ?
+ $this->reduce($values[$i]) : array('keyword', '');
+
+ // lessjs compat, renders fully expanded color, not raw color
+ if ($color = $this->coerceColor($val)) {
+ $val = $color;
+ }
+
+ $i++;
+ $rep = $this->compileValue($this->lib_e($val));
+ $template = preg_replace('/'.self::preg_quote($match).'/',
+ $rep, $template, 1);
+ }
+ }
+
+ $d = $string[0] == "string" ? $string[1] : '"';
+ return array("string", $d, array($template));
+ }
+
+ protected function lib_floor($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", floor($value), $arg[2]);
+ }
+
+ protected function lib_ceil($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", ceil($value), $arg[2]);
+ }
+
+ protected function lib_round($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", round($value), $arg[2]);
+ }
+
+ protected function lib_unit($arg) {
+ if ($arg[0] == "list") {
+ list($number, $newUnit) = $arg[2];
+ return array("number", $this->assertNumber($number),
+ $this->compileValue($this->lib_e($newUnit)));
+ } else {
+ return array("number", $this->assertNumber($arg), "");
+ }
+ }
+
+ /**
+ * Helper function to get arguments for color manipulation functions.
+ * takes a list that contains a color like thing and a percentage
+ */
+ protected function colorArgs($args) {
+ if ($args[0] != 'list' || count($args[2]) < 2) {
+ return array(array('color', 0, 0, 0), 0);
+ }
+ list($color, $delta) = $args[2];
+ $color = $this->assertColor($color);
+ $delta = floatval($delta[1]);
+
+ return array($color, $delta);
+ }
+
+ protected function lib_darken($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[3] = $this->clamp($hsl[3] - $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_lighten($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[3] = $this->clamp($hsl[3] + $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_saturate($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[2] = $this->clamp($hsl[2] + $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_desaturate($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[2] = $this->clamp($hsl[2] - $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_spin($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+
+ $hsl[1] = $hsl[1] + $delta % 360;
+ if ($hsl[1] < 0) $hsl[1] += 360;
+
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_fadeout($args) {
+ list($color, $delta) = $this->colorArgs($args);
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
+ return $color;
+ }
+
+ protected function lib_fadein($args) {
+ list($color, $delta) = $this->colorArgs($args);
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
+ return $color;
+ }
+
+ protected function lib_hue($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[1]);
+ }
+
+ protected function lib_saturation($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[2]);
+ }
+
+ protected function lib_lightness($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[3]);
+ }
+
+ // get the alpha of a color
+ // defaults to 1 for non-colors or colors without an alpha
+ protected function lib_alpha($value) {
+ if (!is_null($color = $this->coerceColor($value))) {
+ return isset($color[4]) ? $color[4] : 1;
+ }
+ }
+
+ // set the alpha of the color
+ protected function lib_fade($args) {
+ list($color, $alpha) = $this->colorArgs($args);
+ $color[4] = $this->clamp($alpha / 100.0);
+ return $color;
+ }
+
+ protected function lib_percentage($arg) {
+ $num = $this->assertNumber($arg);
+ return array("number", $num*100, "%");
+ }
+
+ // mixes two colors by weight
+ // mix(@color1, @color2, [@weight: 50%]);
+ // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
+ protected function lib_mix($args) {
+ if ($args[0] != "list" || count($args[2]) < 2)
+ $this->throwError("mix expects (color1, color2, weight)");
+
+ list($first, $second) = $args[2];
+ $first = $this->assertColor($first);
+ $second = $this->assertColor($second);
+
+ $first_a = $this->lib_alpha($first);
+ $second_a = $this->lib_alpha($second);
+
+ if (isset($args[2][2])) {
+ $weight = $args[2][2][1] / 100.0;
+ } else {
+ $weight = 0.5;
+ }
+
+ $w = $weight * 2 - 1;
+ $a = $first_a - $second_a;
+
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
+ $w2 = 1.0 - $w1;
+
+ $new = array('color',
+ $w1 * $first[1] + $w2 * $second[1],
+ $w1 * $first[2] + $w2 * $second[2],
+ $w1 * $first[3] + $w2 * $second[3],
+ );
+
+ if ($first_a != 1.0 || $second_a != 1.0) {
+ $new[] = $first_a * $weight + $second_a * ($weight - 1);
+ }
+
+ return $this->fixColor($new);
+ }
+
+ protected function lib_contrast($args) {
+ if ($args[0] != 'list' || count($args[2]) < 3) {
+ return array(array('color', 0, 0, 0), 0);
+ }
+
+ list($inputColor, $darkColor, $lightColor) = $args[2];
+
+ $inputColor = $this->assertColor($inputColor);
+ $darkColor = $this->assertColor($darkColor);
+ $lightColor = $this->assertColor($lightColor);
+ $hsl = $this->toHSL($inputColor);
+
+ if ($hsl[3] > 50) {
+ return $darkColor;
+ }
+
+ return $lightColor;
+ }
+
+ protected function assertColor($value, $error = "expected color value") {
+ $color = $this->coerceColor($value);
+ if (is_null($color)) $this->throwError($error);
+ return $color;
+ }
+
+ protected function assertNumber($value, $error = "expecting number") {
+ if ($value[0] == "number") return $value[1];
+ $this->throwError($error);
+ }
+
+ protected function toHSL($color) {
+ if ($color[0] == 'hsl') return $color;
+
+ $r = $color[1] / 255;
+ $g = $color[2] / 255;
+ $b = $color[3] / 255;
+
+ $min = min($r, $g, $b);
+ $max = max($r, $g, $b);
+
+ $L = ($min + $max) / 2;
+ if ($min == $max) {
+ $S = $H = 0;
+ } else {
+ if ($L < 0.5)
+ $S = ($max - $min)/($max + $min);
+ else
+ $S = ($max - $min)/(2.0 - $max - $min);
+
+ if ($r == $max) $H = ($g - $b)/($max - $min);
+ elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min);
+ elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min);
+
+ }
+
+ $out = array('hsl',
+ ($H < 0 ? $H + 6 : $H)*60,
+ $S*100,
+ $L*100,
+ );
+
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
+ return $out;
+ }
+
+ protected function toRGB_helper($comp, $temp1, $temp2) {
+ if ($comp < 0) $comp += 1.0;
+ elseif ($comp > 1) $comp -= 1.0;
+
+ if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
+ if (2 * $comp < 1) return $temp2;
+ if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
+
+ return $temp1;
+ }
+
+ /**
+ * Converts a hsl array into a color value in rgb.
+ * Expects H to be in range of 0 to 360, S and L in 0 to 100
+ */
+ protected function toRGB($color) {
+ if ($color[0] == 'color') return $color;
+
+ $H = $color[1] / 360;
+ $S = $color[2] / 100;
+ $L = $color[3] / 100;
+
+ if ($S == 0) {
+ $r = $g = $b = $L;
+ } else {
+ $temp2 = $L < 0.5 ?
+ $L*(1.0 + $S) :
+ $L + $S - $L * $S;
+
+ $temp1 = 2.0 * $L - $temp2;
+
+ $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
+ $g = $this->toRGB_helper($H, $temp1, $temp2);
+ $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
+ }
+
+ // $out = array('color', round($r*255), round($g*255), round($b*255));
+ $out = array('color', $r*255, $g*255, $b*255);
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
+ return $out;
+ }
+
+ protected function clamp($v, $max = 1, $min = 0) {
+ return min($max, max($min, $v));
+ }
+
+ /**
+ * Convert the rgb, rgba, hsl color literals of function type
+ * as returned by the parser into values of color type.
+ */
+ protected function funcToColor($func) {
+ $fname = $func[1];
+ if ($func[2][0] != 'list') return false; // need a list of arguments
+ $rawComponents = $func[2][2];
+
+ if ($fname == 'hsl' || $fname == 'hsla') {
+ $hsl = array('hsl');
+ $i = 0;
+ foreach ($rawComponents as $c) {
+ $val = $this->reduce($c);
+ $val = isset($val[1]) ? floatval($val[1]) : 0;
+
+ if ($i == 0) $clamp = 360;
+ elseif ($i < 3) $clamp = 100;
+ else $clamp = 1;
+
+ $hsl[] = $this->clamp($val, $clamp);
+ $i++;
+ }
+
+ while (count($hsl) < 4) $hsl[] = 0;
+ return $this->toRGB($hsl);
+
+ } elseif ($fname == 'rgb' || $fname == 'rgba') {
+ $components = array();
+ $i = 1;
+ foreach ($rawComponents as $c) {
+ $c = $this->reduce($c);
+ if ($i < 4) {
+ if ($c[0] == "number" && $c[2] == "%") {
+ $components[] = 255 * ($c[1] / 100);
+ } else {
+ $components[] = floatval($c[1]);
+ }
+ } elseif ($i == 4) {
+ if ($c[0] == "number" && $c[2] == "%") {
+ $components[] = 1.0 * ($c[1] / 100);
+ } else {
+ $components[] = floatval($c[1]);
+ }
+ } else break;
+
+ $i++;
+ }
+ while (count($components) < 3) $components[] = 0;
+ array_unshift($components, 'color');
+ return $this->fixColor($components);
+ }
+
+ return false;
+ }
+
+ protected function reduce($value, $forExpression = false) {
+ switch ($value[0]) {
+ case "interpolate":
+ $reduced = $this->reduce($value[1]);
+ $var = $this->compileValue($reduced);
+ $res = $this->reduce(array("variable", $this->vPrefix . $var));
+
+ if (empty($value[2])) $res = $this->lib_e($res);
+
+ return $res;
+ case "variable":
+ $key = $value[1];
+ if (is_array($key)) {
+ $key = $this->reduce($key);
+ $key = $this->vPrefix . $this->compileValue($this->lib_e($key));
+ }
+
+ $seen =& $this->env->seenNames;
+
+ if (!empty($seen[$key])) {
+ $this->throwError("infinite loop detected: $key");
+ }
+
+ $seen[$key] = true;
+ $out = $this->reduce($this->get($key, self::$defaultValue));
+ $seen[$key] = false;
+ return $out;
+ case "list":
+ foreach ($value[2] as &$item) {
+ $item = $this->reduce($item, $forExpression);
+ }
+ return $value;
+ case "expression":
+ return $this->evaluate($value);
+ case "string":
+ foreach ($value[2] as &$part) {
+ if (is_array($part)) {
+ $strip = $part[0] == "variable";
+ $part = $this->reduce($part);
+ if ($strip) $part = $this->lib_e($part);
+ }
+ }
+ return $value;
+ case "escape":
+ list(,$inner) = $value;
+ return $this->lib_e($this->reduce($inner));
+ case "function":
+ $color = $this->funcToColor($value);
+ if ($color) return $color;
+
+ list(, $name, $args) = $value;
+ if ($name == "%") $name = "_sprintf";
+ $f = isset($this->libFunctions[$name]) ?
+ $this->libFunctions[$name] : array($this, 'lib_'.$name);
+
+ if (is_callable($f)) {
+ if ($args[0] == 'list')
+ $args = self::compressList($args[2], $args[1]);
+
+ $ret = call_user_func($f, $this->reduce($args, true), $this);
+
+ if (is_null($ret)) {
+ return array("string", "", array(
+ $name, "(", $args, ")"
+ ));
+ }
+
+ // convert to a typed value if the result is a php primitive
+ if (is_numeric($ret)) $ret = array('number', $ret, "");
+ elseif (!is_array($ret)) $ret = array('keyword', $ret);
+
+ return $ret;
+ }
+
+ // plain function, reduce args
+ $value[2] = $this->reduce($value[2]);
+ return $value;
+ case "unary":
+ list(, $op, $exp) = $value;
+ $exp = $this->reduce($exp);
+
+ if ($exp[0] == "number") {
+ switch ($op) {
+ case "+":
+ return $exp;
+ case "-":
+ $exp[1] *= -1;
+ return $exp;
+ }
+ }
+ return array("string", "", array($op, $exp));
+ }
+
+ if ($forExpression) {
+ switch ($value[0]) {
+ case "keyword":
+ if ($color = $this->coerceColor($value)) {
+ return $color;
+ }
+ break;
+ case "raw_color":
+ return $this->coerceColor($value);
+ }
+ }
+
+ return $value;
+ }
+
+
+ // coerce a value for use in color operation
+ protected function coerceColor($value) {
+ switch($value[0]) {
+ case 'color': return $value;
+ case 'raw_color':
+ $c = array("color", 0, 0, 0);
+ $colorStr = substr($value[1], 1);
+ $num = hexdec($colorStr);
+ $width = strlen($colorStr) == 3 ? 16 : 256;
+
+ for ($i = 3; $i > 0; $i--) { // 3 2 1
+ $t = $num % $width;
+ $num /= $width;
+
+ $c[$i] = $t * (256/$width) + $t * floor(16/$width);
+ }
+
+ return $c;
+ case 'keyword':
+ $name = $value[1];
+ if (isset(self::$cssColors[$name])) {
+ $rgba = explode(',', self::$cssColors[$name]);
+
+ if(isset($rgba[3]))
+ return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
+
+ return array('color', $rgba[0], $rgba[1], $rgba[2]);
+ }
+ return null;
+ }
+ }
+
+ // make something string like into a string
+ protected function coerceString($value) {
+ switch ($value[0]) {
+ case "string":
+ return $value;
+ case "keyword":
+ return array("string", "", array($value[1]));
+ }
+ return null;
+ }
+
+ // turn list of length 1 into value type
+ protected function flattenList($value) {
+ if ($value[0] == "list" && count($value[2]) == 1) {
+ return $this->flattenList($value[2][0]);
+ }
+ return $value;
+ }
+
+ protected function toBool($a) {
+ if ($a) return self::$TRUE;
+ else return self::$FALSE;
+ }
+
+ // evaluate an expression
+ protected function evaluate($exp) {
+ list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;
+
+ $left = $this->reduce($left, true);
+ $right = $this->reduce($right, true);
+
+ if ($leftColor = $this->coerceColor($left)) {
+ $left = $leftColor;
+ }
+
+ if ($rightColor = $this->coerceColor($right)) {
+ $right = $rightColor;
+ }
+
+ $ltype = $left[0];
+ $rtype = $right[0];
+
+ // operators that work on all types
+ if ($op == "and") {
+ return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
+ }
+
+ if ($op == "=") {
+ return $this->toBool($this->eq($left, $right) );
+ }
+
+ if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) {
+ return $str;
+ }
+
+ // type based operators
+ $fname = "op_${ltype}_${rtype}";
+ if (is_callable(array($this, $fname))) {
+ $out = $this->$fname($op, $left, $right);
+ if (!is_null($out)) return $out;
+ }
+
+ // make the expression look it did before being parsed
+ $paddedOp = $op;
+ if ($whiteBefore) $paddedOp = " " . $paddedOp;
+ if ($whiteAfter) $paddedOp .= " ";
+
+ return array("string", "", array($left, $paddedOp, $right));
+ }
+
+ protected function stringConcatenate($left, $right) {
+ if ($strLeft = $this->coerceString($left)) {
+ if ($right[0] == "string") {
+ $right[1] = "";
+ }
+ $strLeft[2][] = $right;
+ return $strLeft;
+ }
+
+ if ($strRight = $this->coerceString($right)) {
+ array_unshift($strRight[2], $left);
+ return $strRight;
+ }
+ }
+
+
+ // make sure a color's components don't go out of bounds
+ protected function fixColor($c) {
+ foreach (range(1, 3) as $i) {
+ if ($c[$i] < 0) $c[$i] = 0;
+ if ($c[$i] > 255) $c[$i] = 255;
+ }
+
+ return $c;
+ }
+
+ protected function op_number_color($op, $lft, $rgt) {
+ if ($op == '+' || $op == '*') {
+ return $this->op_color_number($op, $rgt, $lft);
+ }
+ }
+
+ protected function op_color_number($op, $lft, $rgt) {
+ if ($rgt[0] == '%') $rgt[1] /= 100;
+
+ return $this->op_color_color($op, $lft,
+ array_fill(1, count($lft) - 1, $rgt[1]));
+ }
+
+ protected function op_color_color($op, $left, $right) {
+ $out = array('color');
+ $max = count($left) > count($right) ? count($left) : count($right);
+ foreach (range(1, $max - 1) as $i) {
+ $lval = isset($left[$i]) ? $left[$i] : 0;
+ $rval = isset($right[$i]) ? $right[$i] : 0;
+ switch ($op) {
+ case '+':
+ $out[] = $lval + $rval;
+ break;
+ case '-':
+ $out[] = $lval - $rval;
+ break;
+ case '*':
+ $out[] = $lval * $rval;
+ break;
+ case '%':
+ $out[] = $lval % $rval;
+ break;
+ case '/':
+ if ($rval == 0) $this->throwError("evaluate error: can't divide by zero");
+ $out[] = $lval / $rval;
+ break;
+ default:
+ $this->throwError('evaluate error: color op number failed on op '.$op);
+ }
+ }
+ return $this->fixColor($out);
+ }
+
+ function lib_red($color){
+ $color = $this->coerceColor($color);
+ if (is_null($color)) {
+ $this->throwError('color expected for red()');
+ }
+
+ return $color[1];
+ }
+
+ function lib_green($color){
+ $color = $this->coerceColor($color);
+ if (is_null($color)) {
+ $this->throwError('color expected for green()');
+ }
+
+ return $color[2];
+ }
+
+ function lib_blue($color){
+ $color = $this->coerceColor($color);
+ if (is_null($color)) {
+ $this->throwError('color expected for blue()');
+ }
+
+ return $color[3];
+ }
+
+
+ // operator on two numbers
+ protected function op_number_number($op, $left, $right) {
+ $unit = empty($left[2]) ? $right[2] : $left[2];
+
+ $value = 0;
+ switch ($op) {
+ case '+':
+ $value = $left[1] + $right[1];
+ break;
+ case '*':
+ $value = $left[1] * $right[1];
+ break;
+ case '-':
+ $value = $left[1] - $right[1];
+ break;
+ case '%':
+ $value = $left[1] % $right[1];
+ break;
+ case '/':
+ if ($right[1] == 0) $this->throwError('parse error: divide by zero');
+ $value = $left[1] / $right[1];
+ break;
+ case '<':
+ return $this->toBool($left[1] < $right[1]);
+ case '>':
+ return $this->toBool($left[1] > $right[1]);
+ case '>=':
+ return $this->toBool($left[1] >= $right[1]);
+ case '=<':
+ return $this->toBool($left[1] <= $right[1]);
+ default:
+ $this->throwError('parse error: unknown number operator: '.$op);
+ }
+
+ return array("number", $value, $unit);
+ }
+
+
+ /* environment functions */
+
+ protected function makeOutputBlock($type, $selectors = null) {
+ $b = new stdclass;
+ $b->lines = array();
+ $b->children = array();
+ $b->selectors = $selectors;
+ $b->type = $type;
+ $b->parent = $this->scope;
+ return $b;
+ }
+
+ // the state of execution
+ protected function pushEnv($block = null) {
+ $e = new stdclass;
+ $e->parent = $this->env;
+ $e->store = array();
+ $e->block = $block;
+
+ $this->env = $e;
+ return $e;
+ }
+
+ // pop something off the stack
+ protected function popEnv() {
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ return $old;
+ }
+
+ // set something in the current env
+ protected function set($name, $value) {
+ $this->env->store[$name] = $value;
+ }
+
+
+ // get the highest occurrence entry for a name
+ protected function get($name, $default=null) {
+ $current = $this->env;
+
+ $isArguments = $name == $this->vPrefix . 'arguments';
+ while ($current) {
+ if ($isArguments && isset($current->arguments)) {
+ return array('list', ' ', $current->arguments);
+ }
+
+ if (isset($current->store[$name]))
+ return $current->store[$name];
+ else {
+ $current = isset($current->storeParent) ?
+ $current->storeParent : $current->parent;
+ }
+ }
+
+ return $default;
+ }
+
+ // inject array of unparsed strings into environment as variables
+ protected function injectVariables($args) {
+ $this->pushEnv();
+ $parser = new lessc_parser($this, __METHOD__);
+ foreach ($args as $name => $strValue) {
+ if ($name{0} != '@') $name = '@'.$name;
+ $parser->count = 0;
+ $parser->buffer = (string)$strValue;
+ if (!$parser->propertyValue($value)) {
+ throw new Exception("failed to parse passed in variable $name: $strValue");
+ }
+
+ $this->set($name, $value);
+ }
+ }
+
+ /**
+ * Initialize any static state, can initialize parser for a file
+ * $opts isn't used yet
+ */
+ public function __construct($fname = null) {
+ if ($fname !== null) {
+ // used for deprecated parse method
+ $this->_parseFile = $fname;
+ }
+ }
+
+ public function compile($string, $name = null) {
+ $locale = setlocale(LC_NUMERIC, 0);
+ setlocale(LC_NUMERIC, "C");
+
+ $this->parser = $this->makeParser($name);
+ $root = $this->parser->parse($string);
+
+ $this->env = null;
+ $this->scope = null;
+
+ $this->formatter = $this->newFormatter();
+
+ if (!empty($this->registeredVars)) {
+ $this->injectVariables($this->registeredVars);
+ }
+
+ $this->sourceParser = $this->parser; // used for error messages
+ $this->compileBlock($root);
+
+ ob_start();
+ $this->formatter->block($this->scope);
+ $out = ob_get_clean();
+ setlocale(LC_NUMERIC, $locale);
+ return $out;
+ }
+
+ public function compileFile($fname, $outFname = null) {
+ if (!is_readable($fname)) {
+ throw new Exception('load error: failed to find '.$fname);
+ }
+
+ $pi = pathinfo($fname);
+
+ $oldImport = $this->importDir;
+
+ $this->importDir = (array)$this->importDir;
+ $this->importDir[] = $pi['dirname'].'/';
+
+ $this->allParsedFiles = array();
+ $this->addParsedFile($fname);
+
+ $out = $this->compile(file_get_contents($fname), $fname);
+
+ $this->importDir = $oldImport;
+
+ if ($outFname !== null) {
+ return file_put_contents($outFname, $out);
+ }
+
+ return $out;
+ }
+
+ // compile only if changed input has changed or output doesn't exist
+ public function checkedCompile($in, $out) {
+ if (!is_file($out) || filemtime($in) > filemtime($out)) {
+ $this->compileFile($in, $out);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Execute lessphp on a .less file or a lessphp cache structure
+ *
+ * The lessphp cache structure contains information about a specific
+ * less file having been parsed. It can be used as a hint for future
+ * calls to determine whether or not a rebuild is required.
+ *
+ * The cache structure contains two important keys that may be used
+ * externally:
+ *
+ * compiled: The final compiled CSS
+ * updated: The time (in seconds) the CSS was last compiled
+ *
+ * The cache structure is a plain-ol' PHP associative array and can
+ * be serialized and unserialized without a hitch.
+ *
+ * @param mixed $in Input
+ * @param bool $force Force rebuild?
+ * @return array lessphp cache structure
+ */
+ public function cachedCompile($in, $force = false) {
+ // assume no root
+ $root = null;
+
+ if (is_string($in)) {
+ $root = $in;
+ } elseif (is_array($in) and isset($in['root'])) {
+ if ($force or ! isset($in['files'])) {
+ // If we are forcing a recompile or if for some reason the
+ // structure does not contain any file information we should
+ // specify the root to trigger a rebuild.
+ $root = $in['root'];
+ } elseif (isset($in['files']) and is_array($in['files'])) {
+ foreach ($in['files'] as $fname => $ftime ) {
+ if (!file_exists($fname) or filemtime($fname) > $ftime) {
+ // One of the files we knew about previously has changed
+ // so we should look at our incoming root again.
+ $root = $in['root'];
+ break;
+ }
+ }
+ }
+ } else {
+ // TODO: Throw an exception? We got neither a string nor something
+ // that looks like a compatible lessphp cache structure.
+ return null;
+ }
+
+ if ($root !== null) {
+ // If we have a root value which means we should rebuild.
+ $out = array();
+ $out['root'] = $root;
+ $out['compiled'] = $this->compileFile($root);
+ $out['files'] = $this->allParsedFiles();
+ $out['updated'] = time();
+ return $out;
+ } else {
+ // No changes, pass back the structure
+ // we were given initially.
+ return $in;
+ }
+
+ }
+
+ // parse and compile buffer
+ // This is deprecated
+ public function parse($str = null, $initialVariables = null) {
+ if (is_array($str)) {
+ $initialVariables = $str;
+ $str = null;
+ }
+
+ $oldVars = $this->registeredVars;
+ if ($initialVariables !== null) {
+ $this->setVariables($initialVariables);
+ }
+
+ if ($str == null) {
+ if (empty($this->_parseFile)) {
+ throw new exception("nothing to parse");
+ }
+
+ $out = $this->compileFile($this->_parseFile);
+ } else {
+ $out = $this->compile($str);
+ }
+
+ $this->registeredVars = $oldVars;
+ return $out;
+ }
+
+ protected function makeParser($name) {
+ $parser = new lessc_parser($this, $name);
+ $parser->writeComments = $this->preserveComments;
+
+ return $parser;
+ }
+
+ public function setFormatter($name) {
+ $this->formatterName = $name;
+ }
+
+ protected function newFormatter() {
+ $className = "lessc_formatter_lessjs";
+ if (!empty($this->formatterName)) {
+ if (!is_string($this->formatterName))
+ return $this->formatterName;
+ $className = "lessc_formatter_$this->formatterName";
+ }
+
+ return new $className;
+ }
+
+ public function setPreserveComments($preserve) {
+ $this->preserveComments = $preserve;
+ }
+
+ public function registerFunction($name, $func) {
+ $this->libFunctions[$name] = $func;
+ }
+
+ public function unregisterFunction($name) {
+ unset($this->libFunctions[$name]);
+ }
+
+ public function setVariables($variables) {
+ $this->registeredVars = array_merge($this->registeredVars, $variables);
+ }
+
+ public function unsetVariable($name) {
+ unset($this->registeredVars[$name]);
+ }
+
+ public function setImportDir($dirs) {
+ $this->importDir = (array)$dirs;
+ }
+
+ public function addImportDir($dir) {
+ $this->importDir = (array)$this->importDir;
+ $this->importDir[] = $dir;
+ }
+
+ public function allParsedFiles() {
+ return $this->allParsedFiles;
+ }
+
+ protected function addParsedFile($file) {
+ $this->allParsedFiles[realpath($file)] = filemtime($file);
+ }
+
+ /**
+ * Uses the current value of $this->count to show line and line number
+ */
+ protected function throwError($msg = null) {
+ if ($this->sourceLoc >= 0) {
+ $this->sourceParser->throwError($msg, $this->sourceLoc);
+ }
+ throw new exception($msg);
+ }
+
+ // compile file $in to file $out if $in is newer than $out
+ // returns true when it compiles, false otherwise
+ public static function ccompile($in, $out, $less = null) {
+ if ($less === null) {
+ $less = new self;
+ }
+ return $less->checkedCompile($in, $out);
+ }
+
+ public static function cexecute($in, $force = false, $less = null) {
+ if ($less === null) {
+ $less = new self;
+ }
+ return $less->cachedCompile($in, $force);
+ }
+
+ static protected $cssColors = array(
+ 'aliceblue' => '240,248,255',
+ 'antiquewhite' => '250,235,215',
+ 'aqua' => '0,255,255',
+ 'aquamarine' => '127,255,212',
+ 'azure' => '240,255,255',
+ 'beige' => '245,245,220',
+ 'bisque' => '255,228,196',
+ 'black' => '0,0,0',
+ 'blanchedalmond' => '255,235,205',
+ 'blue' => '0,0,255',
+ 'blueviolet' => '138,43,226',
+ 'brown' => '165,42,42',
+ 'burlywood' => '222,184,135',
+ 'cadetblue' => '95,158,160',
+ 'chartreuse' => '127,255,0',
+ 'chocolate' => '210,105,30',
+ 'coral' => '255,127,80',
+ 'cornflowerblue' => '100,149,237',
+ 'cornsilk' => '255,248,220',
+ 'crimson' => '220,20,60',
+ 'cyan' => '0,255,255',
+ 'darkblue' => '0,0,139',
+ 'darkcyan' => '0,139,139',
+ 'darkgoldenrod' => '184,134,11',
+ 'darkgray' => '169,169,169',
+ 'darkgreen' => '0,100,0',
+ 'darkgrey' => '169,169,169',
+ 'darkkhaki' => '189,183,107',
+ 'darkmagenta' => '139,0,139',
+ 'darkolivegreen' => '85,107,47',
+ 'darkorange' => '255,140,0',
+ 'darkorchid' => '153,50,204',
+ 'darkred' => '139,0,0',
+ 'darksalmon' => '233,150,122',
+ 'darkseagreen' => '143,188,143',
+ 'darkslateblue' => '72,61,139',
+ 'darkslategray' => '47,79,79',
+ 'darkslategrey' => '47,79,79',
+ 'darkturquoise' => '0,206,209',
+ 'darkviolet' => '148,0,211',
+ 'deeppink' => '255,20,147',
+ 'deepskyblue' => '0,191,255',
+ 'dimgray' => '105,105,105',
+ 'dimgrey' => '105,105,105',
+ 'dodgerblue' => '30,144,255',
+ 'firebrick' => '178,34,34',
+ 'floralwhite' => '255,250,240',
+ 'forestgreen' => '34,139,34',
+ 'fuchsia' => '255,0,255',
+ 'gainsboro' => '220,220,220',
+ 'ghostwhite' => '248,248,255',
+ 'gold' => '255,215,0',
+ 'goldenrod' => '218,165,32',
+ 'gray' => '128,128,128',
+ 'green' => '0,128,0',
+ 'greenyellow' => '173,255,47',
+ 'grey' => '128,128,128',
+ 'honeydew' => '240,255,240',
+ 'hotpink' => '255,105,180',
+ 'indianred' => '205,92,92',
+ 'indigo' => '75,0,130',
+ 'ivory' => '255,255,240',
+ 'khaki' => '240,230,140',
+ 'lavender' => '230,230,250',
+ 'lavenderblush' => '255,240,245',
+ 'lawngreen' => '124,252,0',
+ 'lemonchiffon' => '255,250,205',
+ 'lightblue' => '173,216,230',
+ 'lightcoral' => '240,128,128',
+ 'lightcyan' => '224,255,255',
+ 'lightgoldenrodyellow' => '250,250,210',
+ 'lightgray' => '211,211,211',
+ 'lightgreen' => '144,238,144',
+ 'lightgrey' => '211,211,211',
+ 'lightpink' => '255,182,193',
+ 'lightsalmon' => '255,160,122',
+ 'lightseagreen' => '32,178,170',
+ 'lightskyblue' => '135,206,250',
+ 'lightslategray' => '119,136,153',
+ 'lightslategrey' => '119,136,153',
+ 'lightsteelblue' => '176,196,222',
+ 'lightyellow' => '255,255,224',
+ 'lime' => '0,255,0',
+ 'limegreen' => '50,205,50',
+ 'linen' => '250,240,230',
+ 'magenta' => '255,0,255',
+ 'maroon' => '128,0,0',
+ 'mediumaquamarine' => '102,205,170',
+ 'mediumblue' => '0,0,205',
+ 'mediumorchid' => '186,85,211',
+ 'mediumpurple' => '147,112,219',
+ 'mediumseagreen' => '60,179,113',
+ 'mediumslateblue' => '123,104,238',
+ 'mediumspringgreen' => '0,250,154',
+ 'mediumturquoise' => '72,209,204',
+ 'mediumvioletred' => '199,21,133',
+ 'midnightblue' => '25,25,112',
+ 'mintcream' => '245,255,250',
+ 'mistyrose' => '255,228,225',
+ 'moccasin' => '255,228,181',
+ 'navajowhite' => '255,222,173',
+ 'navy' => '0,0,128',
+ 'oldlace' => '253,245,230',
+ 'olive' => '128,128,0',
+ 'olivedrab' => '107,142,35',
+ 'orange' => '255,165,0',
+ 'orangered' => '255,69,0',
+ 'orchid' => '218,112,214',
+ 'palegoldenrod' => '238,232,170',
+ 'palegreen' => '152,251,152',
+ 'paleturquoise' => '175,238,238',
+ 'palevioletred' => '219,112,147',
+ 'papayawhip' => '255,239,213',
+ 'peachpuff' => '255,218,185',
+ 'peru' => '205,133,63',
+ 'pink' => '255,192,203',
+ 'plum' => '221,160,221',
+ 'powderblue' => '176,224,230',
+ 'purple' => '128,0,128',
+ 'red' => '255,0,0',
+ 'rosybrown' => '188,143,143',
+ 'royalblue' => '65,105,225',
+ 'saddlebrown' => '139,69,19',
+ 'salmon' => '250,128,114',
+ 'sandybrown' => '244,164,96',
+ 'seagreen' => '46,139,87',
+ 'seashell' => '255,245,238',
+ 'sienna' => '160,82,45',
+ 'silver' => '192,192,192',
+ 'skyblue' => '135,206,235',
+ 'slateblue' => '106,90,205',
+ 'slategray' => '112,128,144',
+ 'slategrey' => '112,128,144',
+ 'snow' => '255,250,250',
+ 'springgreen' => '0,255,127',
+ 'steelblue' => '70,130,180',
+ 'tan' => '210,180,140',
+ 'teal' => '0,128,128',
+ 'thistle' => '216,191,216',
+ 'tomato' => '255,99,71',
+ 'transparent' => '0,0,0,0',
+ 'turquoise' => '64,224,208',
+ 'violet' => '238,130,238',
+ 'wheat' => '245,222,179',
+ 'white' => '255,255,255',
+ 'whitesmoke' => '245,245,245',
+ 'yellow' => '255,255,0',
+ 'yellowgreen' => '154,205,50'
+ );
+}
+
+// responsible for taking a string of LESS code and converting it into a
+// syntax tree
+class lessc_parser {
+ static protected $nextBlockId = 0; // used to uniquely identify blocks
+
+ static protected $precedence = array(
+ '=<' => 0,
+ '>=' => 0,
+ '=' => 0,
+ '<' => 0,
+ '>' => 0,
+
+ '+' => 1,
+ '-' => 1,
+ '*' => 2,
+ '/' => 2,
+ '%' => 2,
+ );
+
+ static protected $whitePattern;
+ static protected $commentMulti;
+
+ static protected $commentSingle = "//";
+ static protected $commentMultiLeft = "/*";
+ static protected $commentMultiRight = "*/";
+
+ // regex string to match any of the operators
+ static protected $operatorString;
+
+ // these properties will supress division unless it's inside parenthases
+ static protected $supressDivisionProps =
+ array('/border-radius$/i', '/^font$/i');
+
+ protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
+ protected $lineDirectives = array("charset");
+
+ /**
+ * if we are in parens we can be more liberal with whitespace around
+ * operators because it must evaluate to a single value and thus is less
+ * ambiguous.
+ *
+ * Consider:
+ * property1: 10 -5; // is two numbers, 10 and -5
+ * property2: (10 -5); // should evaluate to 5
+ */
+ protected $inParens = false;
+
+ // caches preg escaped literals
+ static protected $literalCache = array();
+
+ public function __construct($lessc, $sourceName = null) {
+ $this->eatWhiteDefault = true;
+ // reference to less needed for vPrefix, mPrefix, and parentSelector
+ $this->lessc = $lessc;
+
+ $this->sourceName = $sourceName; // name used for error messages
+
+ $this->writeComments = false;
+
+ if (!self::$operatorString) {
+ self::$operatorString =
+ '('.implode('|', array_map(array('lessc', 'preg_quote'),
+ array_keys(self::$precedence))).')';
+
+ $commentSingle = lessc::preg_quote(self::$commentSingle);
+ $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
+ $commentMultiRight = lessc::preg_quote(self::$commentMultiRight);
+
+ self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
+ self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
+ }
+ }
+
+ public function parse($buffer) {
+ $this->count = 0;
+ $this->line = 1;
+
+ $this->env = null; // block stack
+ $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
+ $this->pushSpecialBlock("root");
+ $this->eatWhiteDefault = true;
+ $this->seenComments = array();
+
+ // trim whitespace on head
+ // if (preg_match('/^\s+/', $this->buffer, $m)) {
+ // $this->line += substr_count($m[0], "\n");
+ // $this->buffer = ltrim($this->buffer);
+ // }
+ $this->whitespace();
+
+ // parse the entire file
+ $lastCount = $this->count;
+ while (false !== $this->parseChunk());
+
+ if ($this->count != strlen($this->buffer))
+ $this->throwError();
+
+ // TODO report where the block was opened
+ if (!is_null($this->env->parent))
+ throw new exception('parse error: unclosed block');
+
+ return $this->env;
+ }
+
+ /**
+ * Parse a single chunk off the head of the buffer and append it to the
+ * current parse environment.
+ * Returns false when the buffer is empty, or when there is an error.
+ *
+ * This function is called repeatedly until the entire document is
+ * parsed.
+ *
+ * This parser is most similar to a recursive descent parser. Single
+ * functions represent discrete grammatical rules for the language, and
+ * they are able to capture the text that represents those rules.
+ *
+ * Consider the function lessc::keyword(). (all parse functions are
+ * structured the same)
+ *
+ * The function takes a single reference argument. When calling the
+ * function it will attempt to match a keyword on the head of the buffer.
+ * If it is successful, it will place the keyword in the referenced
+ * argument, advance the position in the buffer, and return true. If it
+ * fails then it won't advance the buffer and it will return false.
+ *
+ * All of these parse functions are powered by lessc::match(), which behaves
+ * the same way, but takes a literal regular expression. Sometimes it is
+ * more convenient to use match instead of creating a new function.
+ *
+ * Because of the format of the functions, to parse an entire string of
+ * grammatical rules, you can chain them together using &&.
+ *
+ * But, if some of the rules in the chain succeed before one fails, then
+ * the buffer position will be left at an invalid state. In order to
+ * avoid this, lessc::seek() is used to remember and set buffer positions.
+ *
+ * Before parsing a chain, use $s = $this->seek() to remember the current
+ * position into $s. Then if a chain fails, use $this->seek($s) to
+ * go back where we started.
+ */
+ protected function parseChunk() {
+ if (empty($this->buffer)) return false;
+ $s = $this->seek();
+
+ // setting a property
+ if ($this->keyword($key) && $this->assign() &&
+ $this->propertyValue($value, $key) && $this->end())
+ {
+ $this->append(array('assign', $key, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+
+ // look for special css blocks
+ if ($this->literal('@', false)) {
+ $this->count--;
+
+ // media
+ if ($this->literal('@media')) {
+ if (($this->mediaQueryList($mediaQueries) || true)
+ && $this->literal('{'))
+ {
+ $media = $this->pushSpecialBlock("media");
+ $media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
+ return true;
+ } else {
+ $this->seek($s);
+ return false;
+ }
+ }
+
+ if ($this->literal("@", false) && $this->keyword($dirName)) {
+ if ($this->isDirective($dirName, $this->blockDirectives)) {
+ if (($this->openString("{", $dirValue, null, array(";")) || true) &&
+ $this->literal("{"))
+ {
+ $dir = $this->pushSpecialBlock("directive");
+ $dir->name = $dirName;
+ if (isset($dirValue)) $dir->value = $dirValue;
+ return true;
+ }
+ } elseif ($this->isDirective($dirName, $this->lineDirectives)) {
+ if ($this->propertyValue($dirValue) && $this->end()) {
+ $this->append(array("directive", $dirName, $dirValue));
+ return true;
+ }
+ }
+ }
+
+ $this->seek($s);
+ }
+
+ // setting a variable
+ if ($this->variable($var) && $this->assign() &&
+ $this->propertyValue($value) && $this->end())
+ {
+ $this->append(array('assign', $var, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->import($importValue)) {
+ $this->append($importValue, $s);
+ return true;
+ }
+
+ // opening parametric mixin
+ if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
+ ($this->guards($guards) || true) &&
+ $this->literal('{'))
+ {
+ $block = $this->pushBlock($this->fixTags(array($tag)));
+ $block->args = $args;
+ $block->isVararg = $isVararg;
+ if (!empty($guards)) $block->guards = $guards;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // opening a simple block
+ if ($this->tags($tags) && $this->literal('{')) {
+ $tags = $this->fixTags($tags);
+ $this->pushBlock($tags);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // closing a block
+ if ($this->literal('}', false)) {
+ try {
+ $block = $this->pop();
+ } catch (exception $e) {
+ $this->seek($s);
+ $this->throwError($e->getMessage());
+ }
+
+ $hidden = false;
+ if (is_null($block->type)) {
+ $hidden = true;
+ if (!isset($block->args)) {
+ foreach ($block->tags as $tag) {
+ if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) {
+ $hidden = false;
+ break;
+ }
+ }
+ }
+
+ foreach ($block->tags as $tag) {
+ if (is_string($tag)) {
+ $this->env->children[$tag][] = $block;
+ }
+ }
+ }
+
+ if (!$hidden) {
+ $this->append(array('block', $block), $s);
+ }
+
+ // this is done here so comments aren't bundled into he block that
+ // was just closed
+ $this->whitespace();
+ return true;
+ }
+
+ // mixin
+ if ($this->mixinTags($tags) &&
+ ($this->argumentValues($argv) || true) &&
+ ($this->keyword($suffix) || true) && $this->end())
+ {
+ $tags = $this->fixTags($tags);
+ $this->append(array('mixin', $tags, $argv, $suffix), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // spare ;
+ if ($this->literal(';')) return true;
+
+ return false; // got nothing, throw error
+ }
+
+ protected function isDirective($dirname, $directives) {
+ // TODO: cache pattern in parser
+ $pattern = implode("|",
+ array_map(array("lessc", "preg_quote"), $directives));
+ $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
+
+ return preg_match($pattern, $dirname);
+ }
+
+ protected function fixTags($tags) {
+ // move @ tags out of variable namespace
+ foreach ($tags as &$tag) {
+ if ($tag{0} == $this->lessc->vPrefix)
+ $tag[0] = $this->lessc->mPrefix;
+ }
+ return $tags;
+ }
+
+ // a list of expressions
+ protected function expressionList(&$exps) {
+ $values = array();
+
+ while ($this->expression($exp)) {
+ $values[] = $exp;
+ }
+
+ if (count($values) == 0) return false;
+
+ $exps = lessc::compressList($values, ' ');
+ return true;
+ }
+
+ /**
+ * Attempt to consume an expression.
+ * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
+ */
+ protected function expression(&$out) {
+ if ($this->value($lhs)) {
+ $out = $this->expHelper($lhs, 0);
+
+ // look for / shorthand
+ if (!empty($this->env->supressedDivision)) {
+ unset($this->env->supressedDivision);
+ $s = $this->seek();
+ if ($this->literal("/") && $this->value($rhs)) {
+ $out = array("list", "",
+ array($out, array("keyword", "/"), $rhs));
+ } else {
+ $this->seek($s);
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * recursively parse infix equation with $lhs at precedence $minP
+ */
+ protected function expHelper($lhs, $minP) {
+ $this->inExp = true;
+ $ss = $this->seek();
+
+ while (true) {
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ // If there is whitespace before the operator, then we require
+ // whitespace after the operator for it to be an expression
+ $needWhite = $whiteBefore && !$this->inParens;
+
+ if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
+ if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
+ foreach (self::$supressDivisionProps as $pattern) {
+ if (preg_match($pattern, $this->env->currentProperty)) {
+ $this->env->supressedDivision = true;
+ break 2;
+ }
+ }
+ }
+
+
+ $whiteAfter = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ if (!$this->value($rhs)) break;
+
+ // peek for next operator to see what to do with rhs
+ if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
+ $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
+ }
+
+ $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
+ $ss = $this->seek();
+
+ continue;
+ }
+
+ break;
+ }
+
+ $this->seek($ss);
+
+ return $lhs;
+ }
+
+ // consume a list of values for a property
+ public function propertyValue(&$value, $keyName = null) {
+ $values = array();
+
+ if ($keyName !== null) $this->env->currentProperty = $keyName;
+
+ $s = null;
+ while ($this->expressionList($v)) {
+ $values[] = $v;
+ $s = $this->seek();
+ if (!$this->literal(',')) break;
+ }
+
+ if ($s) $this->seek($s);
+
+ if ($keyName !== null) unset($this->env->currentProperty);
+
+ if (count($values) == 0) return false;
+
+ $value = lessc::compressList($values, ', ');
+ return true;
+ }
+
+ protected function parenValue(&$out) {
+ $s = $this->seek();
+
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
+ return false;
+ }
+
+ $inParens = $this->inParens;
+ if ($this->literal("(") &&
+ ($this->inParens = true) && $this->expression($exp) &&
+ $this->literal(")"))
+ {
+ $out = $exp;
+ $this->inParens = $inParens;
+ return true;
+ } else {
+ $this->inParens = $inParens;
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ // a single value
+ protected function value(&$value) {
+ $s = $this->seek();
+
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
+ // negation
+ if ($this->literal("-", false) &&
+ (($this->variable($inner) && $inner = array("variable", $inner)) ||
+ $this->unit($inner) ||
+ $this->parenValue($inner)))
+ {
+ $value = array("unary", "-", $inner);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+ }
+
+ if ($this->parenValue($value)) return true;
+ if ($this->unit($value)) return true;
+ if ($this->color($value)) return true;
+ if ($this->func($value)) return true;
+ if ($this->string($value)) return true;
+
+ if ($this->keyword($word)) {
+ $value = array('keyword', $word);
+ return true;
+ }
+
+ // try a variable
+ if ($this->variable($var)) {
+ $value = array('variable', $var);
+ return true;
+ }
+
+ // unquote string (should this work on any type?
+ if ($this->literal("~") && $this->string($str)) {
+ $value = array("escape", $str);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // css hack: \0
+ if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
+ $value = array('keyword', '\\'.$m[1]);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ // an import statement
+ protected function import(&$out) {
+ $s = $this->seek();
+ if (!$this->literal('@import')) return false;
+
+ // @import "something.css" media;
+ // @import url("something.css") media;
+ // @import url(something.css) media;
+
+ if ($this->propertyValue($value)) {
+ $out = array("import", $value);
+ return true;
+ }
+ }
+
+ protected function mediaQueryList(&$out) {
+ if ($this->genericList($list, "mediaQuery", ",", false)) {
+ $out = $list[2];
+ return true;
+ }
+ return false;
+ }
+
+ protected function mediaQuery(&$out) {
+ $s = $this->seek();
+
+ $expressions = null;
+ $parts = array();
+
+ if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
+ $prop = array("mediaType");
+ if (isset($only)) $prop[] = "only";
+ if (isset($not)) $prop[] = "not";
+ $prop[] = $mediaType;
+ $parts[] = $prop;
+ } else {
+ $this->seek($s);
+ }
+
+
+ if (!empty($mediaType) && !$this->literal("and")) {
+ // ~
+ } else {
+ $this->genericList($expressions, "mediaExpression", "and", false);
+ if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
+ }
+
+ if (count($parts) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function mediaExpression(&$out) {
+ $s = $this->seek();
+ $value = null;
+ if ($this->literal("(") &&
+ $this->keyword($feature) &&
+ ($this->literal(":") && $this->expression($value) || true) &&
+ $this->literal(")"))
+ {
+ $out = array("mediaExp", $feature);
+ if ($value) $out[] = $value;
+ return true;
+ } elseif ($this->variable($variable)) {
+ $out = array('variable', $variable);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // an unbounded string stopped by $end
+ protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $stop = array("'", '"', "@{", $end);
+ $stop = array_map(array("lessc", "preg_quote"), $stop);
+ // $stop[] = self::$commentMulti;
+
+ if (!is_null($rejectStrs)) {
+ $stop = array_merge($stop, $rejectStrs);
+ }
+
+ $patt = '(.*?)('.implode("|", $stop).')';
+
+ $nestingLevel = 0;
+
+ $content = array();
+ while ($this->match($patt, $m, false)) {
+ if (!empty($m[1])) {
+ $content[] = $m[1];
+ if ($nestingOpen) {
+ $nestingLevel += substr_count($m[1], $nestingOpen);
+ }
+ }
+
+ $tok = $m[2];
+
+ $this->count-= strlen($tok);
+ if ($tok == $end) {
+ if ($nestingLevel == 0) {
+ break;
+ } else {
+ $nestingLevel--;
+ }
+ }
+
+ if (($tok == "'" || $tok == '"') && $this->string($str)) {
+ $content[] = $str;
+ continue;
+ }
+
+ if ($tok == "@{" && $this->interpolation($inter)) {
+ $content[] = $inter;
+ continue;
+ }
+
+ if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
+ break;
+ }
+
+ $content[] = $tok;
+ $this->count+= strlen($tok);
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($content) == 0) return false;
+
+ // trim the end
+ if (is_string(end($content))) {
+ $content[count($content) - 1] = rtrim(end($content));
+ }
+
+ $out = array("string", "", $content);
+ return true;
+ }
+
+ protected function string(&$out) {
+ $s = $this->seek();
+ if ($this->literal('"', false)) {
+ $delim = '"';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
+ } else {
+ return false;
+ }
+
+ $content = array();
+
+ // look for either ending delim , escape, or string interpolation
+ $patt = '([^\n]*?)(@\{|\\\\|' .
+ lessc::preg_quote($delim).')';
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while ($this->match($patt, $m, false)) {
+ $content[] = $m[1];
+ if ($m[2] == "@{") {
+ $this->count -= strlen($m[2]);
+ if ($this->interpolation($inter, false)) {
+ $content[] = $inter;
+ } else {
+ $this->count += strlen($m[2]);
+ $content[] = "@{"; // ignore it
+ }
+ } elseif ($m[2] == '\\') {
+ $content[] = $m[2];
+ if ($this->literal($delim, false)) {
+ $content[] = $delim;
+ }
+ } else {
+ $this->count -= strlen($delim);
+ break; // delim
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if ($this->literal($delim)) {
+ $out = array("string", $delim, $content);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function interpolation(&$out) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = true;
+
+ $s = $this->seek();
+ if ($this->literal("@{") &&
+ $this->openString("}", $interp, null, array("'", '"', ";")) &&
+ $this->literal("}", false))
+ {
+ $out = array("interpolate", $interp);
+ $this->eatWhiteDefault = $oldWhite;
+ if ($this->eatWhiteDefault) $this->whitespace();
+ return true;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ $this->seek($s);
+ return false;
+ }
+
+ protected function unit(&$unit) {
+ // speed shortcut
+ if (isset($this->buffer[$this->count])) {
+ $char = $this->buffer[$this->count];
+ if (!ctype_digit($char) && $char != ".") return false;
+ }
+
+ if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
+ $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
+ return true;
+ }
+ return false;
+ }
+
+ // a # color
+ protected function color(&$out) {
+ if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
+ if (strlen($m[1]) > 7) {
+ $out = array("string", "", array($m[1]));
+ } else {
+ $out = array("raw_color", $m[1]);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ // consume a list of property values delimited by ; and wrapped in ()
+ protected function argumentValues(&$args, $delim = ',') {
+ $s = $this->seek();
+ if (!$this->literal('(')) return false;
+
+ $values = array();
+ while (true) {
+ if ($this->expressionList($value)) $values[] = $value;
+ if (!$this->literal($delim)) break;
+ else {
+ if ($value == null) $values[] = null;
+ $value = null;
+ }
+ }
+
+ if (!$this->literal(')')) {
+ $this->seek($s);
+ return false;
+ }
+
+ $args = $values;
+ return true;
+ }
+
+ // consume an argument definition list surrounded by ()
+ // each argument is a variable name with optional value
+ // or at the end a ... or a variable named followed by ...
+ protected function argumentDef(&$args, &$isVararg, $delim = ',') {
+ $s = $this->seek();
+ if (!$this->literal('(')) return false;
+
+ $values = array();
+
+ $isVararg = false;
+ while (true) {
+ if ($this->literal("...")) {
+ $isVararg = true;
+ break;
+ }
+
+ if ($this->variable($vname)) {
+ $arg = array("arg", $vname);
+ $ss = $this->seek();
+ if ($this->assign() && $this->expressionList($value)) {
+ $arg[] = $value;
+ } else {
+ $this->seek($ss);
+ if ($this->literal("...")) {
+ $arg[0] = "rest";
+ $isVararg = true;
+ }
+ }
+ $values[] = $arg;
+ if ($isVararg) break;
+ continue;
+ }
+
+ if ($this->value($literal)) {
+ $values[] = array("lit", $literal);
+ }
+
+ if (!$this->literal($delim)) break;
+ }
+
+ if (!$this->literal(')')) {
+ $this->seek($s);
+ return false;
+ }
+
+ $args = $values;
+
+ return true;
+ }
+
+ // consume a list of tags
+ // this accepts a hanging delimiter
+ protected function tags(&$tags, $simple = false, $delim = ',') {
+ $tags = array();
+ while ($this->tag($tt, $simple)) {
+ $tags[] = $tt;
+ if (!$this->literal($delim)) break;
+ }
+ if (count($tags) == 0) return false;
+
+ return true;
+ }
+
+ // list of tags of specifying mixin path
+ // optionally separated by > (lazy, accepts extra >)
+ protected function mixinTags(&$tags) {
+ $s = $this->seek();
+ $tags = array();
+ while ($this->tag($tt, true)) {
+ $tags[] = $tt;
+ $this->literal(">");
+ }
+
+ if (count($tags) == 0) return false;
+
+ return true;
+ }
+
+ // a bracketed value (contained within in a tag definition)
+ protected function tagBracket(&$value) {
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
+ return false;
+ }
+
+ $s = $this->seek();
+ if ($this->literal('[') && $this->to(']', $c, true) && $this->literal(']', false)) {
+ $value = '['.$c.']';
+ // whitespace?
+ if ($this->whitespace()) $value .= " ";
+
+ // escape parent selector, (yuck)
+ $value = str_replace($this->lessc->parentSelector, "$&$", $value);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function tagExpression(&$value) {
+ $s = $this->seek();
+ if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
+ $value = array('exp', $exp);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // a space separated list of selectors
+ protected function tag(&$tag, $simple = false) {
+ if ($simple)
+ $chars = '^@,:;{}\][>\(\) "\'';
+ else
+ $chars = '^@,;{}["\'';
+
+ $s = $this->seek();
+
+ if (!$simple && $this->tagExpression($tag)) {
+ return true;
+ }
+
+ $hasExpression = false;
+ $parts = array();
+ while ($this->tagBracket($first)) $parts[] = $first;
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
+ $parts[] = $m[1];
+ if ($simple) break;
+
+ while ($this->tagBracket($brack)) {
+ $parts[] = $brack;
+ }
+ continue;
+ }
+
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
+ if ($this->interpolation($interp)) {
+ $hasExpression = true;
+ $interp[2] = true; // don't unescape
+ $parts[] = $interp;
+ continue;
+ }
+
+ if ($this->literal("@")) {
+ $parts[] = "@";
+ continue;
+ }
+ }
+
+ if ($this->unit($unit)) { // for keyframes
+ $parts[] = $unit[1];
+ $parts[] = $unit[2];
+ continue;
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ if (!$parts) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($hasExpression) {
+ $tag = array("exp", array("string", "", $parts));
+ } else {
+ $tag = trim(implode($parts));
+ }
+
+ $this->whitespace();
+ return true;
+ }
+
+ // a css function
+ protected function func(&$func) {
+ $s = $this->seek();
+
+ if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
+ $fname = $m[1];
+
+ $sPreArgs = $this->seek();
+
+ $args = array();
+ while (true) {
+ $ss = $this->seek();
+ // this ugly nonsense is for ie filter properties
+ if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
+ $args[] = array("string", "", array($name, "=", $value));
+ } else {
+ $this->seek($ss);
+ if ($this->expressionList($value)) {
+ $args[] = $value;
+ }
+ }
+
+ if (!$this->literal(',')) break;
+ }
+ $args = array('list', ',', $args);
+
+ if ($this->literal(')')) {
+ $func = array('function', $fname, $args);
+ return true;
+ } elseif ($fname == 'url') {
+ // couldn't parse and in url? treat as string
+ $this->seek($sPreArgs);
+ if ($this->openString(")", $string) && $this->literal(")")) {
+ $func = array('function', $fname, $string);
+ return true;
+ }
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // consume a less variable
+ protected function variable(&$name) {
+ $s = $this->seek();
+ if ($this->literal($this->lessc->vPrefix, false) &&
+ ($this->variable($sub) || $this->keyword($name)))
+ {
+ if (!empty($sub)) {
+ $name = array('variable', $sub);
+ } else {
+ $name = $this->lessc->vPrefix.$name;
+ }
+ return true;
+ }
+
+ $name = null;
+ $this->seek($s);
+ return false;
+ }
+
+ /**
+ * Consume an assignment operator
+ * Can optionally take a name that will be set to the current property name
+ */
+ protected function assign($name = null) {
+ if ($name) $this->currentProperty = $name;
+ return $this->literal(':') || $this->literal('=');
+ }
+
+ // consume a keyword
+ protected function keyword(&$word) {
+ if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
+ $word = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ // consume an end of statement delimiter
+ protected function end() {
+ if ($this->literal(';')) {
+ return true;
+ } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
+ // if there is end of file or a closing block next then we don't need a ;
+ return true;
+ }
+ return false;
+ }
+
+ protected function guards(&$guards) {
+ $s = $this->seek();
+
+ if (!$this->literal("when")) {
+ $this->seek($s);
+ return false;
+ }
+
+ $guards = array();
+
+ while ($this->guardGroup($g)) {
+ $guards[] = $g;
+ if (!$this->literal(",")) break;
+ }
+
+ if (count($guards) == 0) {
+ $guards = null;
+ $this->seek($s);
+ return false;
+ }
+
+ return true;
+ }
+
+ // a bunch of guards that are and'd together
+ // TODO rename to guardGroup
+ protected function guardGroup(&$guardGroup) {
+ $s = $this->seek();
+ $guardGroup = array();
+ while ($this->guard($guard)) {
+ $guardGroup[] = $guard;
+ if (!$this->literal("and")) break;
+ }
+
+ if (count($guardGroup) == 0) {
+ $guardGroup = null;
+ $this->seek($s);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function guard(&$guard) {
+ $s = $this->seek();
+ $negate = $this->literal("not");
+
+ if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
+ $guard = $exp;
+ if ($negate) $guard = array("negate", $guard);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ /* raw parsing functions */
+
+ protected function literal($what, $eatWhitespace = null) {
+ if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
+
+ // shortcut on single letter
+ if (!isset($what[1]) && isset($this->buffer[$this->count])) {
+ if ($this->buffer[$this->count] == $what) {
+ if (!$eatWhitespace) {
+ $this->count++;
+ return true;
+ }
+ // goes below...
+ } else {
+ return false;
+ }
+ }
+
+ if (!isset(self::$literalCache[$what])) {
+ self::$literalCache[$what] = lessc::preg_quote($what);
+ }
+
+ return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
+ }
+
+ protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
+ $s = $this->seek();
+ $items = array();
+ while ($this->$parseItem($value)) {
+ $items[] = $value;
+ if ($delim) {
+ if (!$this->literal($delim)) break;
+ }
+ }
+
+ if (count($items) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($flatten && count($items) == 1) {
+ $out = $items[0];
+ } else {
+ $out = array("list", $delim, $items);
+ }
+
+ return true;
+ }
+
+
+ // advance counter to next occurrence of $what
+ // $until - don't include $what in advance
+ // $allowNewline, if string, will be used as valid char set
+ protected function to($what, &$out, $until = false, $allowNewline = false) {
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? "." : "[^\n]";
+ }
+ if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
+ if ($until) $this->count -= strlen($what); // give back $what
+ $out = $m[1];
+ return true;
+ }
+
+ // try to match something on head of buffer
+ protected function match($regex, &$out, $eatWhitespace = null) {
+ if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
+
+ $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+ if ($eatWhitespace && $this->writeComments) $this->whitespace();
+ return true;
+ }
+ return false;
+ }
+
+ // match some whitespace
+ protected function whitespace() {
+ if ($this->writeComments) {
+ $gotWhite = false;
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->append(array("comment", $m[1]));
+ $this->commentsSeen[$this->count] = true;
+ }
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
+ }
+ return $gotWhite;
+ } else {
+ $this->match("", $m);
+ return strlen($m[0]) > 0;
+ }
+ }
+
+ // match something without consuming it
+ protected function peek($regex, &$out = null, $from=null) {
+ if (is_null($from)) $from = $this->count;
+ $r = '/'.$regex.'/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ // seek to a spot in the buffer or return where we are on no argument
+ protected function seek($where = null) {
+ if ($where === null) return $this->count;
+ else $this->count = $where;
+ return true;
+ }
+
+ /* misc functions */
+
+ public function throwError($msg = "parse error", $count = null) {
+ $count = is_null($count) ? $this->count : $count;
+
+ $line = $this->line +
+ substr_count(substr($this->buffer, 0, $count), "\n");
+
+ if (!empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ // TODO this depends on $this->count
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new exception("$msg: failed at `$m[1]` $loc");
+ } else {
+ throw new exception("$msg: $loc");
+ }
+ }
+
+ protected function pushBlock($selectors=null, $type=null) {
+ $b = new stdclass;
+ $b->parent = $this->env;
+
+ $b->type = $type;
+ $b->id = self::$nextBlockId++;
+
+ $b->isVararg = false; // TODO: kill me from here
+ $b->tags = $selectors;
+
+ $b->props = array();
+ $b->children = array();
+
+ $this->env = $b;
+ return $b;
+ }
+
+ // push a block that doesn't multiply tags
+ protected function pushSpecialBlock($type) {
+ return $this->pushBlock(null, $type);
+ }
+
+ // append a property to the current block
+ protected function append($prop, $pos = null) {
+ if ($pos !== null) $prop[-1] = $pos;
+ $this->env->props[] = $prop;
+ }
+
+ // pop something off the stack
+ protected function pop() {
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ return $old;
+ }
+
+ // remove comments from $text
+ // todo: make it work for all functions, not just url
+ protected function removeComments($text) {
+ $look = array(
+ 'url(', '//', '/*', '"', "'"
+ );
+
+ $out = '';
+ $min = null;
+ while (true) {
+ // find the next item
+ foreach ($look as $token) {
+ $pos = strpos($text, $token);
+ if ($pos !== false) {
+ if (!isset($min) || $pos < $min[1]) $min = array($token, $pos);
+ }
+ }
+
+ if (is_null($min)) break;
+
+ $count = $min[1];
+ $skip = 0;
+ $newlines = 0;
+ switch ($min[0]) {
+ case 'url(':
+ if (preg_match('/url\(.*?\)/', $text, $m, 0, $count))
+ $count += strlen($m[0]) - strlen($min[0]);
+ break;
+ case '"':
+ case "'":
+ if (preg_match('/'.$min[0].'.*?'.$min[0].'/', $text, $m, 0, $count))
+ $count += strlen($m[0]) - 1;
+ break;
+ case '//':
+ $skip = strpos($text, "\n", $count);
+ if ($skip === false) $skip = strlen($text) - $count;
+ else $skip -= $count;
+ break;
+ case '/*':
+ if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
+ $skip = strlen($m[0]);
+ $newlines = substr_count($m[0], "\n");
+ }
+ break;
+ }
+
+ if ($skip == 0) $count += strlen($min[0]);
+
+ $out .= substr($text, 0, $count).str_repeat("\n", $newlines);
+ $text = substr($text, $count + $skip);
+
+ $min = null;
+ }
+
+ return $out.$text;
+ }
+
+}
+
+class lessc_formatter_classic {
+ public $indentChar = " ";
+
+ public $break = "\n";
+ public $open = " {";
+ public $close = "}";
+ public $selectorSeparator = ", ";
+ public $assignSeparator = ":";
+
+ public $openSingle = " { ";
+ public $closeSingle = " }";
+
+ public $disableSingle = false;
+ public $breakSelectors = false;
+
+ public $compressColors = false;
+
+ public function __construct() {
+ $this->indentLevel = 0;
+ }
+
+ public function indentStr($n = 0) {
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
+ public function property($name, $value) {
+ return $name . $this->assignSeparator . $value . ";";
+ }
+
+ protected function isEmpty($block) {
+ if (empty($block->lines)) {
+ foreach ($block->children as $child) {
+ if (!$this->isEmpty($child)) return false;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ public function block($block) {
+ if ($this->isEmpty($block)) return;
+
+ $inner = $pre = $this->indentStr();
+
+ $isSingle = !$this->disableSingle &&
+ is_null($block->type) && count($block->lines) == 1;
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel++;
+
+ if ($this->breakSelectors) {
+ $selectorSeparator = $this->selectorSeparator . $this->break . $pre;
+ } else {
+ $selectorSeparator = $this->selectorSeparator;
+ }
+
+ echo $pre .
+ implode($selectorSeparator, $block->selectors);
+ if ($isSingle) {
+ echo $this->openSingle;
+ $inner = "";
+ } else {
+ echo $this->open . $this->break;
+ $inner = $this->indentStr();
+ }
+
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!$isSingle && !empty($block->children)) {
+ echo $this->break;
+ }
+ }
+
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+
+ if (!empty($block->selectors)) {
+ if (!$isSingle && empty($block->children)) echo $this->break;
+
+ if ($isSingle) {
+ echo $this->closeSingle . $this->break;
+ } else {
+ echo $pre . $this->close . $this->break;
+ }
+
+ $this->indentLevel--;
+ }
+ }
+}
+
+class lessc_formatter_compressed extends lessc_formatter_classic {
+ public $disableSingle = true;
+ public $open = "{";
+ public $selectorSeparator = ",";
+ public $assignSeparator = ":";
+ public $break = "";
+ public $compressColors = true;
+
+ public function indentStr($n = 0) {
+ return "";
+ }
+}
+
+class lessc_formatter_lessjs extends lessc_formatter_classic {
+ public $disableSingle = true;
+ public $breakSelectors = true;
+ public $assignSeparator = ": ";
+ public $selectorSeparator = ",";
+}
+
+
diff --git a/inc/load.php b/inc/load.php
index 5ca9b4cd8..923671296 100644
--- a/inc/load.php
+++ b/inc/load.php
@@ -82,12 +82,17 @@ function load_autoload($name){
'RemoteAPI' => DOKU_INC.'inc/remote.php',
'RemoteAPICore' => DOKU_INC.'inc/RemoteAPICore.php',
'Subscription' => DOKU_INC.'inc/subscription.php',
+ 'Crypt_Base' => DOKU_INC.'inc/phpseclib/Crypt_Base.php',
+ 'Crypt_Rijndael' => DOKU_INC.'inc/phpseclib/Crypt_Rijndael.php',
+ 'Crypt_AES' => DOKU_INC.'inc/phpseclib/Crypt_AES.php',
+ 'Crypt_Hash' => DOKU_INC.'inc/phpseclib/Crypt_Hash.php',
+ 'lessc' => DOKU_INC.'inc/lessc.inc.php',
'DokuWiki_Action_Plugin' => DOKU_PLUGIN.'action.php',
'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php',
'DokuWiki_Syntax_Plugin' => DOKU_PLUGIN.'syntax.php',
'DokuWiki_Remote_Plugin' => DOKU_PLUGIN.'remote.php',
- 'DokuWiki_Auth_Plugin' => DOKU_PLUGIN.'auth.php',
+ 'DokuWiki_Auth_Plugin' => DOKU_PLUGIN.'auth.php',
);
diff --git a/inc/media.php b/inc/media.php
index fbe1363ec..c4378fe9e 100644
--- a/inc/media.php
+++ b/inc/media.php
@@ -178,7 +178,7 @@ function media_inuse($id) {
global $conf;
$mediareferences = array();
if($conf['refcheck']){
- $mediareferences = ft_mediause($id,$conf['refshow']);
+ $mediareferences = ft_mediause($id,true);
if(!count($mediareferences)) {
return false;
} else {
@@ -1900,7 +1900,7 @@ function media_crop_image($file, $ext, $w, $h=0){
*/
function media_get_token($id,$w,$h){
// token is only required for modified images
- if ($w || $h) {
+ if ($w || $h || media_isexternal($id)) {
$token = $id;
if ($w) $token .= '.'.$w;
if ($h) $token .= '.'.$h;
diff --git a/inc/parser/metadata.php b/inc/parser/metadata.php
index e17b82f8b..d64fe4d77 100644
--- a/inc/parser/metadata.php
+++ b/inc/parser/metadata.php
@@ -282,8 +282,10 @@ class Doku_Renderer_metadata extends Doku_Renderer {
function internallink($id, $name = NULL){
global $ID;
- if(is_array($name))
+ if(is_array($name)) {
$this->_firstimage($name['src']);
+ if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']);
+ }
$default = $this->_simpleTitle($id);
@@ -304,8 +306,10 @@ class Doku_Renderer_metadata extends Doku_Renderer {
}
function externallink($url, $name = NULL){
- if(is_array($name))
+ if(is_array($name)) {
$this->_firstimage($name['src']);
+ if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']);
+ }
if ($this->capture){
$this->doc .= $this->_getLinkTitle($name, '<' . $url . '>');
@@ -313,8 +317,10 @@ class Doku_Renderer_metadata extends Doku_Renderer {
}
function interwikilink($match, $name = NULL, $wikiName, $wikiUri){
- if(is_array($name))
+ if(is_array($name)) {
$this->_firstimage($name['src']);
+ if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']);
+ }
if ($this->capture){
list($wikiUri, $hash) = explode('#', $wikiUri, 2);
@@ -324,8 +330,10 @@ class Doku_Renderer_metadata extends Doku_Renderer {
}
function windowssharelink($url, $name = NULL){
- if(is_array($name))
+ if(is_array($name)) {
$this->_firstimage($name['src']);
+ if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']);
+ }
if ($this->capture){
if ($name) $this->doc .= $name;
@@ -334,8 +342,10 @@ class Doku_Renderer_metadata extends Doku_Renderer {
}
function emaillink($address, $name = NULL){
- if(is_array($name))
+ if(is_array($name)) {
$this->_firstimage($name['src']);
+ if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']);
+ }
if ($this->capture){
if ($name) $this->doc .= $name;
@@ -347,6 +357,7 @@ class Doku_Renderer_metadata extends Doku_Renderer {
$height=NULL, $cache=NULL, $linking=NULL){
if ($this->capture && $title) $this->doc .= '['.$title.']';
$this->_firstimage($src);
+ $this->_recordMediaUsage($src);
}
function externalmedia($src, $title=NULL, $align=NULL, $width=NULL,
@@ -439,6 +450,15 @@ class Doku_Renderer_metadata extends Doku_Renderer {
$this->firstimage = $src;
}
}
+
+ function _recordMediaUsage($src) {
+ global $ID;
+
+ list ($src, $hash) = explode('#', $src, 2);
+ if (media_isexternal($src)) return;
+ resolve_mediaid(getNS($ID), $src, $exists);
+ $this->meta['relation']['media'][$src] = $exists;
+ }
}
//Setup VIM: ex: et ts=4 :
diff --git a/inc/parser/parser.php b/inc/parser/parser.php
index 915899f53..4af1cd333 100644
--- a/inc/parser/parser.php
+++ b/inc/parser/parser.php
@@ -454,8 +454,8 @@ class Doku_Parser_Mode_table extends Doku_Parser_Mode {
}
function connectTo($mode) {
- $this->Lexer->addEntryPattern('\n\^',$mode,'table');
- $this->Lexer->addEntryPattern('\n\|',$mode,'table');
+ $this->Lexer->addEntryPattern('\s*\n\^',$mode,'table');
+ $this->Lexer->addEntryPattern('\s*\n\|',$mode,'table');
}
function postConnect() {
@@ -555,7 +555,7 @@ class Doku_Parser_Mode_preformatted extends Doku_Parser_Mode {
class Doku_Parser_Mode_code extends Doku_Parser_Mode {
function connectTo($mode) {
- $this->Lexer->addEntryPattern('<code(?=.*</code>)',$mode,'code');
+ $this->Lexer->addEntryPattern('<code\b(?=.*</code>)',$mode,'code');
}
function postConnect() {
@@ -571,7 +571,7 @@ class Doku_Parser_Mode_code extends Doku_Parser_Mode {
class Doku_Parser_Mode_file extends Doku_Parser_Mode {
function connectTo($mode) {
- $this->Lexer->addEntryPattern('<file(?=.*</file>)',$mode,'file');
+ $this->Lexer->addEntryPattern('<file\b(?=.*</file>)',$mode,'file');
}
function postConnect() {
diff --git a/inc/phpseclib/Crypt_AES.php b/inc/phpseclib/Crypt_AES.php
new file mode 100644
index 000000000..81fa2feab
--- /dev/null
+++ b/inc/phpseclib/Crypt_AES.php
@@ -0,0 +1,188 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Pure-PHP implementation of AES.
+ *
+ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
+ *
+ * PHP versions 4 and 5
+ *
+ * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
+ * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
+ * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
+ * is called, again, at which point, it'll be recalculated.
+ *
+ * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
+ * make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
+ * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include('Crypt/AES.php');
+ *
+ * $aes = new Crypt_AES();
+ *
+ * $aes->setKey('abcdefghijklmnop');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $aes->decrypt($aes->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @category Crypt
+ * @package Crypt_AES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright MMVIII Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+/**
+ * Include Crypt_Rijndael
+ */
+if (!class_exists('Crypt_Rijndael')) {
+ require_once('Rijndael.php');
+}
+
+/**#@+
+ * @access public
+ * @see Crypt_AES::encrypt()
+ * @see Crypt_AES::decrypt()
+ */
+/**
+ * Encrypt / decrypt using the Counter mode.
+ *
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
+ */
+define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
+/**
+ * Encrypt / decrypt using the Electronic Code Book mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
+ */
+define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
+/**
+ * Encrypt / decrypt using the Code Book Chaining mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
+ */
+define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
+/**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
+ */
+define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
+/**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
+ */
+define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
+/**#@-*/
+
+/**#@+
+ * @access private
+ * @see Crypt_AES::Crypt_AES()
+ */
+/**
+ * Toggles the internal implementation
+ */
+define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
+/**
+ * Toggles the mcrypt implementation
+ */
+define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
+/**#@-*/
+
+/**
+ * Pure-PHP implementation of AES.
+ *
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @version 0.1.0
+ * @access public
+ * @package Crypt_AES
+ */
+class Crypt_AES extends Crypt_Rijndael {
+ /**
+ * The namespace used by the cipher for its constants.
+ *
+ * @see Crypt_Base::const_namespace
+ * @var String
+ * @access private
+ */
+ var $const_namespace = 'AES';
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * $mode could be:
+ *
+ * - CRYPT_AES_MODE_ECB
+ *
+ * - CRYPT_AES_MODE_CBC
+ *
+ * - CRYPT_AES_MODE_CTR
+ *
+ * - CRYPT_AES_MODE_CFB
+ *
+ * - CRYPT_AES_MODE_OFB
+ *
+ * If not explictly set, CRYPT_AES_MODE_CBC will be used.
+ *
+ * @see Crypt_Rijndael::Crypt_Rijndael()
+ * @see Crypt_Base::Crypt_Base()
+ * @param optional Integer $mode
+ * @access public
+ */
+ function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
+ {
+ parent::Crypt_Rijndael($mode);
+ }
+
+ /**
+ * Dummy function
+ *
+ * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
+ *
+ * @see Crypt_Rijndael::setBlockLength()
+ * @access public
+ * @param Integer $length
+ */
+ function setBlockLength($length)
+ {
+ return;
+ }
+}
+
+// vim: ts=4:sw=4:et:
+// vim6: fdl=1:
diff --git a/inc/phpseclib/Crypt_Base.php b/inc/phpseclib/Crypt_Base.php
new file mode 100644
index 000000000..7c650ca72
--- /dev/null
+++ b/inc/phpseclib/Crypt_Base.php
@@ -0,0 +1,1989 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Base Class for all Crypt_* cipher classes
+ *
+ * PHP versions 4 and 5
+ *
+ * Internally for phpseclib developers:
+ * If you plan to add a new cipher class, please note following rules:
+ *
+ * - The new Crypt_* cipher class should extend Crypt_Base
+ *
+ * - Following methods are then required to be overridden/overloaded:
+ *
+ * - _encryptBlock()
+ *
+ * - _decryptBlock()
+ *
+ * - _setupKey()
+ *
+ * - All other methods are optional to be overridden/overloaded
+ *
+ * - Look at the source code of the current ciphers how they extend Crypt_Base
+ * and take one of them as a start up for the new cipher class.
+ *
+ * - Please read all the other comments/notes/hints here also for each class var/method
+ *
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @category Crypt
+ * @package Crypt_Base
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @copyright MMVII Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version 1.0.1
+ * @link http://phpseclib.sourceforge.net
+ */
+
+/**#@+
+ * @access public
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ */
+/**
+ * Encrypt / decrypt using the Counter mode.
+ *
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
+ */
+define('CRYPT_MODE_CTR', -1);
+/**
+ * Encrypt / decrypt using the Electronic Code Book mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
+ */
+define('CRYPT_MODE_ECB', 1);
+/**
+ * Encrypt / decrypt using the Code Book Chaining mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
+ */
+define('CRYPT_MODE_CBC', 2);
+/**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
+ */
+define('CRYPT_MODE_CFB', 3);
+/**
+ * Encrypt / decrypt using the Output Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
+ */
+define('CRYPT_MODE_OFB', 4);
+/**
+ * Encrypt / decrypt using streaming mode.
+ *
+ */
+define('CRYPT_MODE_STREAM', 5);
+/**#@-*/
+
+/**#@+
+ * @access private
+ * @see Crypt_Base::Crypt_Base()
+ */
+/**
+ * Base value for the internal implementation $engine switch
+ */
+define('CRYPT_MODE_INTERNAL', 1);
+/**
+ * Base value for the mcrypt implementation $engine switch
+ */
+define('CRYPT_MODE_MCRYPT', 2);
+/**#@-*/
+
+/**
+ * Base Class for all Crypt_* cipher classes
+ *
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @version 1.0.0
+ * @access public
+ * @package Crypt_Base
+ */
+class Crypt_Base {
+ /**
+ * The Encryption Mode
+ *
+ * @see Crypt_Base::Crypt_Base()
+ * @var Integer
+ * @access private
+ */
+ var $mode;
+
+ /**
+ * The Block Length of the block cipher
+ *
+ * @var Integer
+ * @access private
+ */
+ var $block_size = 16;
+
+ /**
+ * The Key
+ *
+ * @see Crypt_Base::setKey()
+ * @var String
+ * @access private
+ */
+ var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+ /**
+ * The Initialization Vector
+ *
+ * @see Crypt_Base::setIV()
+ * @var String
+ * @access private
+ */
+ var $iv;
+
+ /**
+ * A "sliding" Initialization Vector
+ *
+ * @see Crypt_Base::enableContinuousBuffer()
+ * @see Crypt_Base::_clearBuffers()
+ * @var String
+ * @access private
+ */
+ var $encryptIV;
+
+ /**
+ * A "sliding" Initialization Vector
+ *
+ * @see Crypt_Base::enableContinuousBuffer()
+ * @see Crypt_Base::_clearBuffers()
+ * @var String
+ * @access private
+ */
+ var $decryptIV;
+
+ /**
+ * Continuous Buffer status
+ *
+ * @see Crypt_Base::enableContinuousBuffer()
+ * @var Boolean
+ * @access private
+ */
+ var $continuousBuffer = false;
+
+ /**
+ * Encryption buffer for CTR, OFB and CFB modes
+ *
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::_clearBuffers()
+ * @var Array
+ * @access private
+ */
+ var $enbuffer;
+
+ /**
+ * Decryption buffer for CTR, OFB and CFB modes
+ *
+ * @see Crypt_Base::decrypt()
+ * @see Crypt_Base::_clearBuffers()
+ * @var Array
+ * @access private
+ */
+ var $debuffer;
+
+ /**
+ * mcrypt resource for encryption
+ *
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
+ *
+ * @see Crypt_Base::encrypt()
+ * @var Resource
+ * @access private
+ */
+ var $enmcrypt;
+
+ /**
+ * mcrypt resource for decryption
+ *
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
+ *
+ * @see Crypt_Base::decrypt()
+ * @var Resource
+ * @access private
+ */
+ var $demcrypt;
+
+ /**
+ * Does the enmcrypt resource need to be (re)initialized?
+ *
+ * @see Crypt_Twofish::setKey()
+ * @see Crypt_Twofish::setIV()
+ * @var Boolean
+ * @access private
+ */
+ var $enchanged = true;
+
+ /**
+ * Does the demcrypt resource need to be (re)initialized?
+ *
+ * @see Crypt_Twofish::setKey()
+ * @see Crypt_Twofish::setIV()
+ * @var Boolean
+ * @access private
+ */
+ var $dechanged = true;
+
+ /**
+ * mcrypt resource for CFB mode
+ *
+ * mcrypt's CFB mode, in (and only in) buffered context,
+ * is broken, so phpseclib implements the CFB mode by it self,
+ * even when the mcrypt php extension is available.
+ *
+ * In order to do the CFB-mode work (fast) phpseclib
+ * use a separate ECB-mode mcrypt resource.
+ *
+ * @link http://phpseclib.sourceforge.net/cfb-demo.phps
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ * @see Crypt_Base::_setupMcrypt()
+ * @var Resource
+ * @access private
+ */
+ var $ecb;
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * Only relevant if $continuousBuffer enabled
+ * and $engine == CRYPT_MODE_MCRYPT
+ *
+ * It's faster to re-init $enmcrypt if
+ * $buffer bytes > $cfb_init_len than
+ * using the $ecb resource furthermore.
+ *
+ * This value depends of the choosen cipher
+ * and the time it would be needed for it's
+ * initialization [by mcrypt_generic_init()]
+ * which, typically, depends on the complexity
+ * on its internaly Key-expanding algorithm.
+ *
+ * @see Crypt_Base::encrypt()
+ * @var Integer
+ * @access private
+ */
+ var $cfb_init_len = 600;
+
+ /**
+ * Does internal cipher state need to be (re)initialized?
+ *
+ * @see setKey()
+ * @see setIV()
+ * @see disableContinuousBuffer()
+ * @var Boolean
+ * @access private
+ */
+ var $changed = true;
+
+ /**
+ * Padding status
+ *
+ * @see Crypt_Base::enablePadding()
+ * @var Boolean
+ * @access private
+ */
+ var $padding = true;
+
+ /**
+ * Is the mode one that is paddable?
+ *
+ * @see Crypt_Base::Crypt_Base()
+ * @var Boolean
+ * @access private
+ */
+ var $paddable = false;
+
+ /**
+ * Holds which crypt engine internaly should be use,
+ * which will be determined automatically on __construct()
+ *
+ * Currently available $engines are:
+ * - CRYPT_MODE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
+ * - CRYPT_MODE_INTERNAL (slower, pure php-engine, no php-extension required)
+ *
+ * In the pipeline... maybe. But currently not available:
+ * - CRYPT_MODE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
+ *
+ * If possible, CRYPT_MODE_MCRYPT will be used for each cipher.
+ * Otherwise CRYPT_MODE_INTERNAL
+ *
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ * @var Integer
+ * @access private
+ */
+ var $engine;
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * Only used if $engine == CRYPT_MODE_MCRYPT
+ *
+ * @link http://www.php.net/mcrypt_module_open
+ * @link http://www.php.net/mcrypt_list_algorithms
+ * @see Crypt_Base::_setupMcrypt()
+ * @var String
+ * @access private
+ */
+ var $cipher_name_mcrypt;
+
+ /**
+ * The default password key_size used by setPassword()
+ *
+ * @see Crypt_Base::setPassword()
+ * @var Integer
+ * @access private
+ */
+ var $password_key_size = 32;
+
+ /**
+ * The default salt used by setPassword()
+ *
+ * @see Crypt_Base::setPassword()
+ * @var String
+ * @access private
+ */
+ var $password_default_salt = 'phpseclib/salt';
+
+ /**
+ * The namespace used by the cipher for its constants.
+ *
+ * ie: AES.php is using CRYPT_AES_MODE_* for its constants
+ * so $const_namespace is AES
+ *
+ * DES.php is using CRYPT_DES_MODE_* for its constants
+ * so $const_namespace is DES... and so on
+ *
+ * All CRYPT_<$const_namespace>_MODE_* are aliases of
+ * the generic CRYPT_MODE_* constants, so both could be used
+ * for each cipher.
+ *
+ * Example:
+ * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
+ * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
+ *
+ * @see Crypt_Base::Crypt_Base()
+ * @var String
+ * @access private
+ */
+ var $const_namespace;
+
+ /**
+ * The name of the performance-optimized callback function
+ *
+ * Used by encrypt() / decrypt()
+ * only if $engine == CRYPT_MODE_INTERNAL
+ *
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ * @see Crypt_Base::_setupInlineCrypt()
+ * @see Crypt_Base::$use_inline_crypt
+ * @var Callback
+ * @access private
+ */
+ var $inline_crypt;
+
+ /**
+ * Holds whether performance-optimized $inline_crypt() can/should be used.
+ *
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ * @see Crypt_Base::inline_crypt
+ * @var mixed
+ * @access private
+ */
+ var $use_inline_crypt;
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * $mode could be:
+ *
+ * - CRYPT_MODE_ECB
+ *
+ * - CRYPT_MODE_CBC
+ *
+ * - CRYPT_MODE_CTR
+ *
+ * - CRYPT_MODE_CFB
+ *
+ * - CRYPT_MODE_OFB
+ *
+ * (or the alias constants of the choosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
+ *
+ * If not explictly set, CRYPT_MODE_CBC will be used.
+ *
+ * @param optional Integer $mode
+ * @access public
+ */
+ function Crypt_Base($mode = CRYPT_MODE_CBC)
+ {
+ $const_crypt_mode = 'CRYPT_' . $this->const_namespace . '_MODE';
+
+ // Determining the availibility of mcrypt support for the cipher
+ if (!defined($const_crypt_mode)) {
+ switch (true) {
+ case extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()):
+ define($const_crypt_mode, CRYPT_MODE_MCRYPT);
+ break;
+ default:
+ define($const_crypt_mode, CRYPT_MODE_INTERNAL);
+ }
+ }
+
+ // Determining which internal $engine should be used.
+ // The fastes possible first.
+ switch (true) {
+ case empty($this->cipher_name_mcrypt): // The cipher module has no mcrypt-engine support at all so we force CRYPT_MODE_INTERNAL
+ $this->engine = CRYPT_MODE_INTERNAL;
+ break;
+ case constant($const_crypt_mode) == CRYPT_MODE_MCRYPT:
+ $this->engine = CRYPT_MODE_MCRYPT;
+ break;
+ default:
+ $this->engine = CRYPT_MODE_INTERNAL;
+ }
+
+ // $mode dependent settings
+ switch ($mode) {
+ case CRYPT_MODE_ECB:
+ $this->paddable = true;
+ $this->mode = $mode;
+ break;
+ case CRYPT_MODE_CTR:
+ case CRYPT_MODE_CFB:
+ case CRYPT_MODE_OFB:
+ case CRYPT_MODE_STREAM:
+ $this->mode = $mode;
+ break;
+ case CRYPT_MODE_CBC:
+ default:
+ $this->paddable = true;
+ $this->mode = CRYPT_MODE_CBC;
+ }
+
+ // Determining whether inline crypting can be used by the cipher
+ if ($this->use_inline_crypt !== false && function_exists('create_function')) {
+ $this->use_inline_crypt = true;
+ }
+ }
+
+ /**
+ * Sets the initialization vector. (optional)
+ *
+ * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explictly set, it'll be assumed
+ * to be all zero's.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @access public
+ * @param String $iv
+ */
+ function setIV($iv)
+ {
+ if ($this->mode == CRYPT_MODE_ECB) {
+ return;
+ }
+
+ $this->iv = $iv;
+ $this->changed = true;
+ }
+
+ /**
+ * Sets the key.
+ *
+ * The min/max length(s) of the key depends on the cipher which is used.
+ * If the key not fits the length(s) of the cipher it will paded with null bytes
+ * up to the closest valid key length. If the key is more than max length,
+ * we trim the excess bits.
+ *
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @access public
+ * @param String $key
+ */
+ function setKey($key)
+ {
+ $this->key = $key;
+ $this->changed = true;
+ }
+
+ /**
+ * Sets the password.
+ *
+ * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
+ * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
+ * $hash, $salt, $count, $dkLen
+ *
+ * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see Crypt/Hash.php
+ * @param String $password
+ * @param optional String $method
+ * @access public
+ */
+ function setPassword($password, $method = 'pbkdf2')
+ {
+ $key = '';
+
+ switch ($method) {
+ default: // 'pbkdf2'
+ $func_args = func_get_args();
+
+ // Hash function
+ $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
+
+ // WPA and WPA2 use the SSID as the salt
+ $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
+
+ // RFC2898#section-4.2 uses 1,000 iterations by default
+ // WPA and WPA2 use 4,096.
+ $count = isset($func_args[4]) ? $func_args[4] : 1000;
+
+ // Keylength
+ $dkLen = isset($func_args[5]) ? $func_args[5] : $this->password_key_size;
+
+ // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
+ switch (true) {
+ case !function_exists('hash_pbkdf2'):
+ case !function_exists('hash_algos'):
+ case !in_array($hash, hash_algos()):
+ if (!class_exists('Crypt_Hash')) {
+ require_once('Crypt/Hash.php');
+ }
+ $i = 1;
+ while (strlen($key) < $dkLen) {
+ $hmac = new Crypt_Hash();
+ $hmac->setHash($hash);
+ $hmac->setKey($password);
+ $f = $u = $hmac->hash($salt . pack('N', $i++));
+ for ($j = 2; $j <= $count; ++$j) {
+ $u = $hmac->hash($u);
+ $f^= $u;
+ }
+ $key.= $f;
+ }
+ $key = substr($key, 0, $dkLen);
+ break;
+ default:
+ $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
+ }
+ }
+
+ $this->setKey($key);
+ }
+
+ /**
+ * Encrypts a message.
+ *
+ * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
+ * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
+ * necessary are discussed in the following
+ * URL:
+ *
+ * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
+ *
+ * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
+ * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
+ * length.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see Crypt_Base::decrypt()
+ * @access public
+ * @param String $plaintext
+ * @return String $cipertext
+ */
+ function encrypt($plaintext)
+ {
+ if ($this->engine == CRYPT_MODE_MCRYPT) {
+ if ($this->changed) {
+ $this->_setupMcrypt();
+ $this->changed = false;
+ }
+ if ($this->enchanged) {
+ mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
+ $this->enchanged = false;
+ }
+
+ // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
+ // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
+ // rewritten CFB implementation the above outputs the same thing twice.
+ if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
+ $block_size = $this->block_size;
+ $iv = &$this->encryptIV;
+ $pos = &$this->enbuffer['pos'];
+ $len = strlen($plaintext);
+ $ciphertext = '';
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
+ $this->enbuffer['enmcrypt_init'] = true;
+ }
+ if ($len >= $block_size) {
+ if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
+ if ($this->enbuffer['enmcrypt_init'] === true) {
+ mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
+ $this->enbuffer['enmcrypt_init'] = false;
+ }
+ $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
+ $iv = substr($ciphertext, -$block_size);
+ $len%= $block_size;
+ } else {
+ while ($len >= $block_size) {
+ $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
+ $ciphertext.= $iv;
+ $len-= $block_size;
+ $i+= $block_size;
+ }
+ }
+ }
+
+ if ($len) {
+ $iv = mcrypt_generic($this->ecb, $iv);
+ $block = $iv ^ substr($plaintext, -$len);
+ $iv = substr_replace($iv, $block, 0, $len);
+ $ciphertext.= $block;
+ $pos = $len;
+ }
+
+ return $ciphertext;
+ }
+
+ if ($this->paddable) {
+ $plaintext = $this->_pad($plaintext);
+ }
+
+ $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
+
+ if (!$this->continuousBuffer) {
+ mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
+ }
+
+ return $ciphertext;
+ }
+
+ if ($this->changed) {
+ $this->_setup();
+ $this->changed = false;
+ }
+ if ($this->use_inline_crypt) {
+ $inline = $this->inline_crypt;
+ return $inline('encrypt', $this, $plaintext);
+ }
+ if ($this->paddable) {
+ $plaintext = $this->_pad($plaintext);
+ }
+
+ $buffer = &$this->enbuffer;
+ $block_size = $this->block_size;
+ $ciphertext = '';
+ switch ($this->mode) {
+ case CRYPT_MODE_ECB:
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
+ }
+ break;
+ case CRYPT_MODE_CBC:
+ $xor = $this->encryptIV;
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ $block = $this->_encryptBlock($block ^ $xor);
+ $xor = $block;
+ $ciphertext.= $block;
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = $xor;
+ }
+ break;
+ case CRYPT_MODE_CTR:
+ $xor = $this->encryptIV;
+ if (strlen($buffer['encrypted'])) {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['encrypted'])) {
+ $buffer['encrypted'].= $this->_encryptBlock($this->_generateXor($xor, $block_size));
+ }
+ $key = $this->_stringShift($buffer['encrypted'], $block_size);
+ $ciphertext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ $key = $this->_encryptBlock($this->_generateXor($xor, $block_size));
+ $ciphertext.= $block ^ $key;
+ }
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = $xor;
+ if ($start = strlen($plaintext) % $block_size) {
+ $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
+ }
+ }
+ break;
+ case CRYPT_MODE_CFB:
+ // cfb loosely routines inspired by openssl's:
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
+ if ($this->continuousBuffer) {
+ $iv = &$this->encryptIV;
+ $pos = &$buffer['pos'];
+ } else {
+ $iv = $this->encryptIV;
+ $pos = 0;
+ }
+ $len = strlen($plaintext);
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
+ }
+ while ($len >= $block_size) {
+ $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
+ $ciphertext.= $iv;
+ $len-= $block_size;
+ $i+= $block_size;
+ }
+ if ($len) {
+ $iv = $this->_encryptBlock($iv);
+ $block = $iv ^ substr($plaintext, $i);
+ $iv = substr_replace($iv, $block, 0, $len);
+ $ciphertext.= $block;
+ $pos = $len;
+ }
+ break;
+ case CRYPT_MODE_OFB:
+ $xor = $this->encryptIV;
+ if (strlen($buffer['xor'])) {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['xor'])) {
+ $xor = $this->_encryptBlock($xor);
+ $buffer['xor'].= $xor;
+ }
+ $key = $this->_stringShift($buffer['xor'], $block_size);
+ $ciphertext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $xor = $this->_encryptBlock($xor);
+ $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
+ }
+ $key = $xor;
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = $xor;
+ if ($start = strlen($plaintext) % $block_size) {
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
+ }
+ }
+ break;
+ case CRYPT_MODE_STREAM:
+ $ciphertext = $this->_encryptBlock($plaintext);
+ break;
+ }
+
+ return $ciphertext;
+ }
+
+ /**
+ * Decrypts a message.
+ *
+ * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
+ * it is.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see Crypt_Base::encrypt()
+ * @access public
+ * @param String $ciphertext
+ * @return String $plaintext
+ */
+ function decrypt($ciphertext)
+ {
+ if ($this->engine == CRYPT_MODE_MCRYPT) {
+ $block_size = $this->block_size;
+ if ($this->changed) {
+ $this->_setupMcrypt();
+ $this->changed = false;
+ }
+ if ($this->dechanged) {
+ mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
+ $this->dechanged = false;
+ }
+
+ if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
+ $iv = &$this->decryptIV;
+ $pos = &$this->debuffer['pos'];
+ $len = strlen($ciphertext);
+ $plaintext = '';
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
+ }
+ if ($len >= $block_size) {
+ $cb = substr($ciphertext, $i, $len - $len % $block_size);
+ $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
+ $iv = substr($cb, -$block_size);
+ $len%= $block_size;
+ }
+ if ($len) {
+ $iv = mcrypt_generic($this->ecb, $iv);
+ $plaintext.= $iv ^ substr($ciphertext, -$len);
+ $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
+ $pos = $len;
+ }
+
+ return $plaintext;
+ }
+
+ if ($this->paddable) {
+ // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
+ // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
+ $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0));
+ }
+
+ $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
+
+ if (!$this->continuousBuffer) {
+ mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
+ }
+
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
+ }
+
+ if ($this->changed) {
+ $this->_setup();
+ $this->changed = false;
+ }
+ if ($this->use_inline_crypt) {
+ $inline = $this->inline_crypt;
+ return $inline('decrypt', $this, $ciphertext);
+ }
+
+ $block_size = $this->block_size;
+ if ($this->paddable) {
+ // we pad with chr(0) since that's what mcrypt_generic does [...]
+ $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0));
+ }
+
+ $buffer = &$this->debuffer;
+ $plaintext = '';
+ switch ($this->mode) {
+ case CRYPT_MODE_ECB:
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
+ }
+ break;
+ case CRYPT_MODE_CBC:
+ $xor = $this->decryptIV;
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ $plaintext.= $this->_decryptBlock($block) ^ $xor;
+ $xor = $block;
+ }
+ if ($this->continuousBuffer) {
+ $this->decryptIV = $xor;
+ }
+ break;
+ case CRYPT_MODE_CTR:
+ $xor = $this->decryptIV;
+ if (strlen($buffer['ciphertext'])) {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
+ $buffer['ciphertext'].= $this->_encryptBlock($this->_generateXor($xor, $block_size));
+ }
+ $key = $this->_stringShift($buffer['ciphertext'], $block_size);
+ $plaintext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ $key = $this->_encryptBlock($this->_generateXor($xor, $block_size));
+ $plaintext.= $block ^ $key;
+ }
+ }
+ if ($this->continuousBuffer) {
+ $this->decryptIV = $xor;
+ if ($start = strlen($ciphertext) % $block_size) {
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
+ }
+ }
+ break;
+ case CRYPT_MODE_CFB:
+ if ($this->continuousBuffer) {
+ $iv = &$this->decryptIV;
+ $pos = &$buffer['pos'];
+ } else {
+ $iv = $this->decryptIV;
+ $pos = 0;
+ }
+ $len = strlen($ciphertext);
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
+ }
+ while ($len >= $block_size) {
+ $iv = $this->_encryptBlock($iv);
+ $cb = substr($ciphertext, $i, $block_size);
+ $plaintext.= $iv ^ $cb;
+ $iv = $cb;
+ $len-= $block_size;
+ $i+= $block_size;
+ }
+ if ($len) {
+ $iv = $this->_encryptBlock($iv);
+ $plaintext.= $iv ^ substr($ciphertext, $i);
+ $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
+ $pos = $len;
+ }
+ break;
+ case CRYPT_MODE_OFB:
+ $xor = $this->decryptIV;
+ if (strlen($buffer['xor'])) {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['xor'])) {
+ $xor = $this->_encryptBlock($xor);
+ $buffer['xor'].= $xor;
+ }
+ $key = $this->_stringShift($buffer['xor'], $block_size);
+ $plaintext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $xor = $this->_encryptBlock($xor);
+ $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
+ }
+ $key = $xor;
+ }
+ if ($this->continuousBuffer) {
+ $this->decryptIV = $xor;
+ if ($start = strlen($ciphertext) % $block_size) {
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
+ }
+ }
+ break;
+ case CRYPT_MODE_STREAM:
+ $plaintext = $this->_decryptBlock($ciphertext);
+ break;
+ }
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
+ }
+
+ /**
+ * Pad "packets".
+ *
+ * Block ciphers working by encrypting between their specified [$this->]block_size at a time
+ * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
+ * pad the input so that it is of the proper length.
+ *
+ * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
+ * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
+ * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
+ * transmitted separately)
+ *
+ * @see Crypt_Base::disablePadding()
+ * @access public
+ */
+ function enablePadding()
+ {
+ $this->padding = true;
+ }
+
+ /**
+ * Do not pad packets.
+ *
+ * @see Crypt_Base::enablePadding()
+ * @access public
+ */
+ function disablePadding()
+ {
+ $this->padding = false;
+ }
+
+ /**
+ * Treat consecutive "packets" as if they are a continuous buffer.
+ *
+ * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
+ * will yield different outputs:
+ *
+ * <code>
+ * echo $rijndael->encrypt(substr($plaintext, 0, 16));
+ * echo $rijndael->encrypt(substr($plaintext, 16, 16));
+ * </code>
+ * <code>
+ * echo $rijndael->encrypt($plaintext);
+ * </code>
+ *
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
+ * another, as demonstrated with the following:
+ *
+ * <code>
+ * $rijndael->encrypt(substr($plaintext, 0, 16));
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
+ * </code>
+ * <code>
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
+ * </code>
+ *
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
+ *
+ * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
+ * however, they are also less intuitive and more likely to cause you problems.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see Crypt_Base::disableContinuousBuffer()
+ * @access public
+ */
+ function enableContinuousBuffer()
+ {
+ if ($this->mode == CRYPT_MODE_ECB) {
+ return;
+ }
+
+ $this->continuousBuffer = true;
+ }
+
+ /**
+ * Treat consecutive packets as if they are a discontinuous buffer.
+ *
+ * The default behavior.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see Crypt_Base::enableContinuousBuffer()
+ * @access public
+ */
+ function disableContinuousBuffer()
+ {
+ if ($this->mode == CRYPT_MODE_ECB) {
+ return;
+ }
+ if (!$this->continuousBuffer) {
+ return;
+ }
+
+ $this->continuousBuffer = false;
+ $this->changed = true;
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * Note: Must extend by the child Crypt_* class
+ *
+ * @access private
+ * @param String $in
+ * @return String
+ */
+ function _encryptBlock($in)
+ {
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * Note: Must extend by the child Crypt_* class
+ *
+ * @access private
+ * @param String $in
+ * @return String
+ */
+ function _decryptBlock($in)
+ {
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
+ }
+
+ /**
+ * Setup the key (expansion)
+ *
+ * Only used if $engine == CRYPT_MODE_INTERNAL
+ *
+ * Note: Must extend by the child Crypt_* class
+ *
+ * @see Crypt_Base::_setup()
+ * @access private
+ */
+ function _setupKey()
+ {
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
+ }
+
+ /**
+ * Setup the CRYPT_MODE_INTERNAL $engine
+ *
+ * (re)init, if necessary, the internal cipher $engine and flush all $buffers
+ * Used (only) if $engine == CRYPT_MODE_INTERNAL
+ *
+ * _setup() will be called each time if $changed === true
+ * typically this happens when using one or more of following public methods:
+ *
+ * - setKey()
+ *
+ * - setIV()
+ *
+ * - disableContinuousBuffer()
+ *
+ * - First run of encrypt() / decrypt() with no init-settings
+ *
+ * Internally: _setup() is called always before(!) en/decryption.
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see setKey()
+ * @see setIV()
+ * @see disableContinuousBuffer()
+ * @access private
+ */
+ function _setup()
+ {
+ $this->_clearBuffers();
+ $this->_setupKey();
+
+ if ($this->use_inline_crypt) {
+ $this->_setupInlineCrypt();
+ }
+ }
+
+ /**
+ * Setup the CRYPT_MODE_MCRYPT $engine
+ *
+ * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
+ * Used (only) if $engine = CRYPT_MODE_MCRYPT
+ *
+ * _setupMcrypt() will be called each time if $changed === true
+ * typically this happens when using one or more of following public methods:
+ *
+ * - setKey()
+ *
+ * - setIV()
+ *
+ * - disableContinuousBuffer()
+ *
+ * - First run of encrypt() / decrypt()
+ *
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @see setKey()
+ * @see setIV()
+ * @see disableContinuousBuffer()
+ * @access private
+ */
+ function _setupMcrypt()
+ {
+ $this->_clearBuffers();
+ $this->enchanged = $this->dechanged = true;
+
+ if (!isset($this->enmcrypt)) {
+ static $mcrypt_modes = array(
+ CRYPT_MODE_CTR => 'ctr',
+ CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
+ CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
+ CRYPT_MODE_CFB => 'ncfb',
+ CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
+ CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
+ );
+
+ $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
+ $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
+
+ // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
+ // to workaround mcrypt's broken ncfb implementation in buffered mode
+ // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
+ if ($this->mode == CRYPT_MODE_CFB) {
+ $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
+ }
+
+ } // else should mcrypt_generic_deinit be called?
+
+ if ($this->mode == CRYPT_MODE_CFB) {
+ mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
+ }
+ }
+
+ /**
+ * Pads a string
+ *
+ * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
+ * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
+ * chr($this->block_size - (strlen($text) % $this->block_size)
+ *
+ * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
+ * and padding will, hence forth, be enabled.
+ *
+ * @see Crypt_Base::_unpad()
+ * @param String $text
+ * @access private
+ * @return String
+ */
+ function _pad($text)
+ {
+ $length = strlen($text);
+
+ if (!$this->padding) {
+ if ($length % $this->block_size == 0) {
+ return $text;
+ } else {
+ user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
+ $this->padding = true;
+ }
+ }
+
+ $pad = $this->block_size - ($length % $this->block_size);
+
+ return str_pad($text, $length + $pad, chr($pad));
+ }
+
+ /**
+ * Unpads a string.
+ *
+ * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
+ * and false will be returned.
+ *
+ * @see Crypt_Base::_pad()
+ * @param String $text
+ * @access private
+ * @return String
+ */
+ function _unpad($text)
+ {
+ if (!$this->padding) {
+ return $text;
+ }
+
+ $length = ord($text[strlen($text) - 1]);
+
+ if (!$length || $length > $this->block_size) {
+ return false;
+ }
+
+ return substr($text, 0, -$length);
+ }
+
+ /**
+ * Clears internal buffers
+ *
+ * Clearing/resetting the internal buffers is done everytime
+ * after disableContinuousBuffer() or on cipher $engine (re)init
+ * ie after setKey() or setIV()
+ *
+ * Note: Could, but not must, extend by the child Crypt_* class
+ *
+ * @access public
+ */
+ function _clearBuffers()
+ {
+ $this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
+ $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
+
+ // mcrypt's handling of invalid's $iv:
+ // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
+ $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param String $string
+ * @param optional Integer $index
+ * @access private
+ * @return String
+ */
+ function _stringShift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+
+ /**
+ * Generate CTR XOR encryption key
+ *
+ * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
+ * plaintext / ciphertext in CTR mode.
+ *
+ * @see Crypt_Base::decrypt()
+ * @see Crypt_Base::encrypt()
+ * @param String $iv
+ * @param Integer $length
+ * @access private
+ * @return String $xor
+ */
+ function _generateXor(&$iv, $length)
+ {
+ $xor = '';
+ $block_size = $this->block_size;
+ $num_blocks = floor(($length + ($block_size - 1)) / $block_size);
+ for ($i = 0; $i < $num_blocks; $i++) {
+ $xor.= $iv;
+ for ($j = 4; $j <= $block_size; $j+= 4) {
+ $temp = substr($iv, -$j, 4);
+ switch ($temp) {
+ case "\xFF\xFF\xFF\xFF":
+ $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
+ break;
+ case "\x7F\xFF\xFF\xFF":
+ $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
+ break 2;
+ default:
+ extract(unpack('Ncount', $temp));
+ $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
+ break 2;
+ }
+ }
+ }
+
+ return $xor;
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * Stores the created (or existing) callback function-name
+ * in $this->inline_crypt
+ *
+ * Internally for phpseclib developers:
+ *
+ * _setupInlineCrypt() would be called only if:
+ *
+ * - $engine == CRYPT_MODE_INTERNAL and
+ *
+ * - $use_inline_crypt === true
+ *
+ * - each time on _setup(), after(!) _setupKey()
+ *
+ *
+ * This ensures that _setupInlineCrypt() has allways a
+ * full ready2go initializated internal cipher $engine state
+ * where, for example, the keys allready expanded,
+ * keys/block_size calculated and such.
+ *
+ * It is, each time if called, the responsibility of _setupInlineCrypt():
+ *
+ * - to set $this->inline_crypt to a valid and fully working callback function
+ * as a (faster) replacement for encrypt() / decrypt()
+ *
+ * - NOT to create unlimited callback functions (for memory reasons!)
+ * no matter how often _setupInlineCrypt() would be called. At some
+ * point of amount they must be generic re-useable.
+ *
+ * - the code of _setupInlineCrypt() it self,
+ * and the generated callback code,
+ * must be, in following order:
+ * - 100% safe
+ * - 100% compatible to encrypt()/decrypt()
+ * - using only php5+ features/lang-constructs/php-extensions if
+ * compatibility (down to php4) or fallback is provided
+ * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
+ * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
+ * the reason for the existence of _setupInlineCrypt() :-)]
+ * - memory-nice
+ * - short (as good as possible)
+ *
+ * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
+ * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
+ * - The following variable names are reserved:
+ * - $_* (all variable names prefixed with an underscore)
+ * - $self (object reference to it self. Do not use $this, but $self instead)
+ * - $in (the content of $in has to en/decrypt by the generated code)
+ * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
+ *
+ *
+ * @see Crypt_Base::_setup()
+ * @see Crypt_Base::_createInlineCryptFunction()
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ // If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
+
+ // If, for any reason, an extending Crypt_Base() Crypt_* class
+ // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
+ // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
+ // in the constructor at object instance-time
+ // or, if it's runtime-specific, at runtime
+
+ $this->use_inline_crypt = false;
+ }
+
+ /**
+ * Creates the performance-optimized function for en/decrypt()
+ *
+ * Internally for phpseclib developers:
+ *
+ * _createInlineCryptFunction():
+ *
+ * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
+ * with the current [$this->]mode of operation code
+ *
+ * - create the $inline function, which called by encrypt() / decrypt()
+ * as its replacement to speed up the en/decryption operations.
+ *
+ * - return the name of the created $inline callback function
+ *
+ * - used to speed up en/decryption
+ *
+ *
+ *
+ * The main reason why can speed up things [up to 50%] this way are:
+ *
+ * - using variables more effective then regular.
+ * (ie no use of expensive arrays but integers $k_0, $k_1 ...
+ * or even, for example, the pure $key[] values hardcoded)
+ *
+ * - avoiding 1000's of function calls of ie _encryptBlock()
+ * but inlining the crypt operations.
+ * in the mode of operation for() loop.
+ *
+ * - full loop unroll the (sometimes key-dependent) rounds
+ * avoiding this way ++$i counters and runtime-if's etc...
+ *
+ * The basic code architectur of the generated $inline en/decrypt()
+ * lambda function, in pseudo php, is:
+ *
+ * <code>
+ * +----------------------------------------------------------------------------------------------+
+ * | callback $inline = create_function: |
+ * | lambda_function_0001_crypt_ECB($action, $text) |
+ * | { |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['init_crypt']; // general init code. |
+ * | // ie: $sbox'es declarations used for |
+ * | // encrypt and decrypt'ing. |
+ * | |
+ * | switch ($action) { |
+ * | case 'encrypt': |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
+ * | ie: specified $key or $box |
+ * | declarations for encrypt'ing. |
+ * | |
+ * | foreach ($ciphertext) { |
+ * | $in = $block_size of $ciphertext; |
+ * | |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
+ * | // strlen($in) == $this->block_size |
+ * | // here comes the cipher algorithm in action |
+ * | // for encryption. |
+ * | // $cipher_code['encrypt_block'] has to |
+ * | // encrypt the content of the $in variable |
+ * | |
+ * | $plaintext .= $in; |
+ * | } |
+ * | return $plaintext; |
+ * | |
+ * | case 'decrypt': |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
+ * | ie: specified $key or $box |
+ * | declarations for decrypt'ing. |
+ * | foreach ($plaintext) { |
+ * | $in = $block_size of $plaintext; |
+ * | |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
+ * | // strlen($in) == $this->block_size |
+ * | // here comes the cipher algorithm in action |
+ * | // for decryption. |
+ * | // $cipher_code['decrypt_block'] has to |
+ * | // decrypt the content of the $in variable |
+ * | $ciphertext .= $in; |
+ * | } |
+ * | return $ciphertext; |
+ * | } |
+ * | } |
+ * +----------------------------------------------------------------------------------------------+
+ * </code>
+ *
+ * See also the Crypt_*::_setupInlineCrypt()'s for
+ * productive inline $cipher_code's how they works.
+ *
+ * Structure of:
+ * <code>
+ * $cipher_code = array(
+ * 'init_crypt' => (string) '', // optional
+ * 'init_encrypt' => (string) '', // optional
+ * 'init_decrypt' => (string) '', // optional
+ * 'encrypt_block' => (string) '', // required
+ * 'decrypt_block' => (string) '' // required
+ * );
+ * </code>
+ *
+ * @see Crypt_Base::_setupInlineCrypt()
+ * @see Crypt_Base::encrypt()
+ * @see Crypt_Base::decrypt()
+ * @param Array $cipher_code
+ * @access private
+ * @return String (the name of the created callback function)
+ */
+ function _createInlineCryptFunction($cipher_code)
+ {
+ $block_size = $this->block_size;
+
+ // optional
+ $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
+ $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
+ $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
+ // required
+ $encrypt_block = $cipher_code['encrypt_block'];
+ $decrypt_block = $cipher_code['decrypt_block'];
+
+ // Generating mode of operation inline code,
+ // merged with the $cipher_code algorithm
+ // for encrypt- and decryption.
+ switch ($this->mode) {
+ case CRYPT_MODE_ECB:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_text = $self->_pad($_text);
+ $_plaintext_len = strlen($_text);
+
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $in = substr($_text, $_i, '.$block_size.');
+ '.$encrypt_block.'
+ $_ciphertext.= $in;
+ }
+
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_decrypt . '
+ $_plaintext = "";
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
+ $_ciphertext_len = strlen($_text);
+
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $in = substr($_text, $_i, '.$block_size.');
+ '.$decrypt_block.'
+ $_plaintext.= $in;
+ }
+
+ return $self->_unpad($_plaintext);
+ ';
+ break;
+ case CRYPT_MODE_CTR:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_plaintext_len = strlen($_text);
+ $_xor = $self->encryptIV;
+ $_buffer = &$self->enbuffer;
+
+ if (strlen($_buffer["encrypted"])) {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["encrypted"])) {
+ $in = $self->_generateXor($_xor, '.$block_size.');
+ '.$encrypt_block.'
+ $_buffer["encrypted"].= $in;
+ }
+ $_key = $self->_stringShift($_buffer["encrypted"], '.$block_size.');
+ $_ciphertext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ $in = $self->_generateXor($_xor, '.$block_size.');
+ '.$encrypt_block.'
+ $_key = $in;
+ $_ciphertext.= $_block ^ $_key;
+ }
+ }
+ if ($self->continuousBuffer) {
+ $self->encryptIV = $_xor;
+ if ($_start = $_plaintext_len % '.$block_size.') {
+ $_buffer["encrypted"] = substr($_key, $_start) . $_buffer["encrypted"];
+ }
+ }
+
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_ciphertext_len = strlen($_text);
+ $_xor = $self->decryptIV;
+ $_buffer = &$self->debuffer;
+
+ if (strlen($_buffer["ciphertext"])) {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
+ $in = $self->_generateXor($_xor, '.$block_size.');
+ '.$encrypt_block.'
+ $_buffer["ciphertext"].= $in;
+ }
+ $_key = $self->_stringShift($_buffer["ciphertext"], '.$block_size.');
+ $_plaintext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ $in = $self->_generateXor($_xor, '.$block_size.');
+ '.$encrypt_block.'
+ $_key = $in;
+ $_plaintext.= $_block ^ $_key;
+ }
+ }
+ if ($self->continuousBuffer) {
+ $self->decryptIV = $_xor;
+ if ($_start = $_ciphertext_len % '.$block_size.') {
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
+ }
+ }
+
+ return $_plaintext;
+ ';
+ break;
+ case CRYPT_MODE_CFB:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_buffer = &$self->enbuffer;
+
+ if ($self->continuousBuffer) {
+ $_iv = &$self->encryptIV;
+ $_pos = &$_buffer["pos"];
+ } else {
+ $_iv = $self->encryptIV;
+ $_pos = 0;
+ }
+ $_len = strlen($_text);
+ $_i = 0;
+ if ($_pos) {
+ $_orig_pos = $_pos;
+ $_max = '.$block_size.' - $_pos;
+ if ($_len >= $_max) {
+ $_i = $_max;
+ $_len-= $_max;
+ $_pos = 0;
+ } else {
+ $_i = $_len;
+ $_pos+= $_len;
+ $_len = 0;
+ }
+ $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
+ $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
+ }
+ while ($_len >= '.$block_size.') {
+ $in = $_iv;
+ '.$encrypt_block.';
+ $_iv = $in ^ substr($_text, $_i, '.$block_size.');
+ $_ciphertext.= $_iv;
+ $_len-= '.$block_size.';
+ $_i+= '.$block_size.';
+ }
+ if ($_len) {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_iv = $in;
+ $_block = $_iv ^ substr($_text, $_i);
+ $_iv = substr_replace($_iv, $_block, 0, $_len);
+ $_ciphertext.= $_block;
+ $_pos = $_len;
+ }
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_buffer = &$self->debuffer;
+
+ if ($self->continuousBuffer) {
+ $_iv = &$self->decryptIV;
+ $_pos = &$_buffer["pos"];
+ } else {
+ $_iv = $self->decryptIV;
+ $_pos = 0;
+ }
+ $_len = strlen($_text);
+ $_i = 0;
+ if ($_pos) {
+ $_orig_pos = $_pos;
+ $_max = '.$block_size.' - $_pos;
+ if ($_len >= $_max) {
+ $_i = $_max;
+ $_len-= $_max;
+ $_pos = 0;
+ } else {
+ $_i = $_len;
+ $_pos+= $_len;
+ $_len = 0;
+ }
+ $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
+ $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
+ }
+ while ($_len >= '.$block_size.') {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_iv = $in;
+ $cb = substr($_text, $_i, '.$block_size.');
+ $_plaintext.= $_iv ^ $cb;
+ $_iv = $cb;
+ $_len-= '.$block_size.';
+ $_i+= '.$block_size.';
+ }
+ if ($_len) {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_iv = $in;
+ $_plaintext.= $_iv ^ substr($_text, $_i);
+ $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
+ $_pos = $_len;
+ }
+
+ return $_plaintext;
+ ';
+ break;
+ case CRYPT_MODE_OFB:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_plaintext_len = strlen($_text);
+ $_xor = $self->encryptIV;
+ $_buffer = &$self->enbuffer;
+
+ if (strlen($_buffer["xor"])) {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["xor"])) {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_buffer["xor"].= $_xor;
+ }
+ $_key = $self->_stringShift($_buffer["xor"], '.$block_size.');
+ $_ciphertext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
+ }
+ $_key = $_xor;
+ }
+ if ($self->continuousBuffer) {
+ $self->encryptIV = $_xor;
+ if ($_start = $_plaintext_len % '.$block_size.') {
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
+ }
+ }
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_ciphertext_len = strlen($_text);
+ $_xor = $self->decryptIV;
+ $_buffer = &$self->debuffer;
+
+ if (strlen($_buffer["xor"])) {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["xor"])) {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_buffer["xor"].= $_xor;
+ }
+ $_key = $self->_stringShift($_buffer["xor"], '.$block_size.');
+ $_plaintext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
+ }
+ $_key = $_xor;
+ }
+ if ($self->continuousBuffer) {
+ $self->decryptIV = $_xor;
+ if ($_start = $_ciphertext_len % '.$block_size.') {
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
+ }
+ }
+ return $_plaintext;
+ ';
+ break;
+ case CRYPT_MODE_STREAM:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ '.$encrypt_block.'
+ return $_ciphertext;
+ ';
+ $decrypt = $init_decrypt . '
+ $_plaintext = "";
+ '.$decrypt_block.'
+ return $_plaintext;
+ ';
+ break;
+ // case CRYPT_MODE_CBC:
+ default:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_text = $self->_pad($_text);
+ $_plaintext_len = strlen($_text);
+
+ $in = $self->encryptIV;
+
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $in = substr($_text, $_i, '.$block_size.') ^ $in;
+ '.$encrypt_block.'
+ $_ciphertext.= $in;
+ }
+
+ if ($self->continuousBuffer) {
+ $self->encryptIV = $in;
+ }
+
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_decrypt . '
+ $_plaintext = "";
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
+ $_ciphertext_len = strlen($_text);
+
+ $_iv = $self->decryptIV;
+
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $in = $_block = substr($_text, $_i, '.$block_size.');
+ '.$decrypt_block.'
+ $_plaintext.= $in ^ $_iv;
+ $_iv = $_block;
+ }
+
+ if ($self->continuousBuffer) {
+ $self->decryptIV = $_iv;
+ }
+
+ return $self->_unpad($_plaintext);
+ ';
+ break;
+ }
+
+ // Create the $inline function and return its name as string. Ready to run!
+ return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
+ }
+
+ /**
+ * Holds the lambda_functions table (classwide)
+ *
+ * Each name of the lambda function, created from
+ * _setupInlineCrypt() && _createInlineCryptFunction()
+ * is stored, classwide (!), here for reusing.
+ *
+ * The string-based index of $function is a classwide
+ * uniqe value representing, at least, the $mode of
+ * operation (or more... depends of the optimizing level)
+ * for which $mode the lambda function was created.
+ *
+ * @access private
+ * @return &Array
+ */
+ function &_getLambdaFunctions()
+ {
+ static $functions = array();
+ return $functions;
+ }
+}
+
+// vim: ts=4:sw=4:et:
+// vim6: fdl=1:
diff --git a/inc/phpseclib/Crypt_Hash.php b/inc/phpseclib/Crypt_Hash.php
new file mode 100644
index 000000000..840fcd508
--- /dev/null
+++ b/inc/phpseclib/Crypt_Hash.php
@@ -0,0 +1,823 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
+ *
+ * Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
+ *
+ * md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
+ *
+ * If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
+ * the hash. If no valid algorithm is provided, sha1 will be used.
+ *
+ * PHP versions 4 and 5
+ *
+ * {@internal The variable names are the same as those in
+ * {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include('Crypt/Hash.php');
+ *
+ * $hash = new Crypt_Hash('sha1');
+ *
+ * $hash->setKey('abcdefg');
+ *
+ * echo base64_encode($hash->hash('abcdefg'));
+ * ?>
+ * </code>
+ *
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @category Crypt
+ * @package Crypt_Hash
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright MMVII Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+/**#@+
+ * @access private
+ * @see Crypt_Hash::Crypt_Hash()
+ */
+/**
+ * Toggles the internal implementation
+ */
+define('CRYPT_HASH_MODE_INTERNAL', 1);
+/**
+ * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
+ */
+define('CRYPT_HASH_MODE_MHASH', 2);
+/**
+ * Toggles the hash() implementation, which works on PHP 5.1.2+.
+ */
+define('CRYPT_HASH_MODE_HASH', 3);
+/**#@-*/
+
+/**
+ * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
+ *
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @version 0.1.0
+ * @access public
+ * @package Crypt_Hash
+ */
+class Crypt_Hash {
+ /**
+ * Byte-length of compression blocks / key (Internal HMAC)
+ *
+ * @see Crypt_Hash::setAlgorithm()
+ * @var Integer
+ * @access private
+ */
+ var $b;
+
+ /**
+ * Byte-length of hash output (Internal HMAC)
+ *
+ * @see Crypt_Hash::setHash()
+ * @var Integer
+ * @access private
+ */
+ var $l = false;
+
+ /**
+ * Hash Algorithm
+ *
+ * @see Crypt_Hash::setHash()
+ * @var String
+ * @access private
+ */
+ var $hash;
+
+ /**
+ * Key
+ *
+ * @see Crypt_Hash::setKey()
+ * @var String
+ * @access private
+ */
+ var $key = false;
+
+ /**
+ * Outer XOR (Internal HMAC)
+ *
+ * @see Crypt_Hash::setKey()
+ * @var String
+ * @access private
+ */
+ var $opad;
+
+ /**
+ * Inner XOR (Internal HMAC)
+ *
+ * @see Crypt_Hash::setKey()
+ * @var String
+ * @access private
+ */
+ var $ipad;
+
+ /**
+ * Default Constructor.
+ *
+ * @param optional String $hash
+ * @return Crypt_Hash
+ * @access public
+ */
+ function Crypt_Hash($hash = 'sha1')
+ {
+ if ( !defined('CRYPT_HASH_MODE') ) {
+ switch (true) {
+ case extension_loaded('hash'):
+ define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
+ break;
+ case extension_loaded('mhash'):
+ define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
+ break;
+ default:
+ define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
+ }
+ }
+
+ $this->setHash($hash);
+ }
+
+ /**
+ * Sets the key for HMACs
+ *
+ * Keys can be of any length.
+ *
+ * @access public
+ * @param optional String $key
+ */
+ function setKey($key = false)
+ {
+ $this->key = $key;
+ }
+
+ /**
+ * Sets the hash function.
+ *
+ * @access public
+ * @param String $hash
+ */
+ function setHash($hash)
+ {
+ $hash = strtolower($hash);
+ switch ($hash) {
+ case 'md5-96':
+ case 'sha1-96':
+ $this->l = 12; // 96 / 8 = 12
+ break;
+ case 'md2':
+ case 'md5':
+ $this->l = 16;
+ break;
+ case 'sha1':
+ $this->l = 20;
+ break;
+ case 'sha256':
+ $this->l = 32;
+ break;
+ case 'sha384':
+ $this->l = 48;
+ break;
+ case 'sha512':
+ $this->l = 64;
+ }
+
+ switch ($hash) {
+ case 'md2':
+ $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
+ CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
+ break;
+ case 'sha384':
+ case 'sha512':
+ $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
+ break;
+ default:
+ $mode = CRYPT_HASH_MODE;
+ }
+
+ switch ( $mode ) {
+ case CRYPT_HASH_MODE_MHASH:
+ switch ($hash) {
+ case 'md5':
+ case 'md5-96':
+ $this->hash = MHASH_MD5;
+ break;
+ case 'sha256':
+ $this->hash = MHASH_SHA256;
+ break;
+ case 'sha1':
+ case 'sha1-96':
+ default:
+ $this->hash = MHASH_SHA1;
+ }
+ return;
+ case CRYPT_HASH_MODE_HASH:
+ switch ($hash) {
+ case 'md5':
+ case 'md5-96':
+ $this->hash = 'md5';
+ return;
+ case 'md2':
+ case 'sha256':
+ case 'sha384':
+ case 'sha512':
+ $this->hash = $hash;
+ return;
+ case 'sha1':
+ case 'sha1-96':
+ default:
+ $this->hash = 'sha1';
+ }
+ return;
+ }
+
+ switch ($hash) {
+ case 'md2':
+ $this->b = 16;
+ $this->hash = array($this, '_md2');
+ break;
+ case 'md5':
+ case 'md5-96':
+ $this->b = 64;
+ $this->hash = array($this, '_md5');
+ break;
+ case 'sha256':
+ $this->b = 64;
+ $this->hash = array($this, '_sha256');
+ break;
+ case 'sha384':
+ case 'sha512':
+ $this->b = 128;
+ $this->hash = array($this, '_sha512');
+ break;
+ case 'sha1':
+ case 'sha1-96':
+ default:
+ $this->b = 64;
+ $this->hash = array($this, '_sha1');
+ }
+
+ $this->ipad = str_repeat(chr(0x36), $this->b);
+ $this->opad = str_repeat(chr(0x5C), $this->b);
+ }
+
+ /**
+ * Compute the HMAC.
+ *
+ * @access public
+ * @param String $text
+ * @return String
+ */
+ function hash($text)
+ {
+ $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
+
+ if (!empty($this->key) || is_string($this->key)) {
+ switch ( $mode ) {
+ case CRYPT_HASH_MODE_MHASH:
+ $output = mhash($this->hash, $text, $this->key);
+ break;
+ case CRYPT_HASH_MODE_HASH:
+ $output = hash_hmac($this->hash, $text, $this->key, true);
+ break;
+ case CRYPT_HASH_MODE_INTERNAL:
+ /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
+ resultant L byte string as the actual key to HMAC."
+
+ -- http://tools.ietf.org/html/rfc2104#section-2 */
+ $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
+
+ $key = str_pad($key, $this->b, chr(0)); // step 1
+ $temp = $this->ipad ^ $key; // step 2
+ $temp .= $text; // step 3
+ $temp = call_user_func($this->hash, $temp); // step 4
+ $output = $this->opad ^ $key; // step 5
+ $output.= $temp; // step 6
+ $output = call_user_func($this->hash, $output); // step 7
+ }
+ } else {
+ switch ( $mode ) {
+ case CRYPT_HASH_MODE_MHASH:
+ $output = mhash($this->hash, $text);
+ break;
+ case CRYPT_HASH_MODE_HASH:
+ $output = hash($this->hash, $text, true);
+ break;
+ case CRYPT_HASH_MODE_INTERNAL:
+ $output = call_user_func($this->hash, $text);
+ }
+ }
+
+ return substr($output, 0, $this->l);
+ }
+
+ /**
+ * Returns the hash length (in bytes)
+ *
+ * @access public
+ * @return Integer
+ */
+ function getLength()
+ {
+ return $this->l;
+ }
+
+ /**
+ * Wrapper for MD5
+ *
+ * @access private
+ * @param String $m
+ */
+ function _md5($m)
+ {
+ return pack('H*', md5($m));
+ }
+
+ /**
+ * Wrapper for SHA1
+ *
+ * @access private
+ * @param String $m
+ */
+ function _sha1($m)
+ {
+ return pack('H*', sha1($m));
+ }
+
+ /**
+ * Pure-PHP implementation of MD2
+ *
+ * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
+ *
+ * @access private
+ * @param String $m
+ */
+ function _md2($m)
+ {
+ static $s = array(
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+ );
+
+ // Step 1. Append Padding Bytes
+ $pad = 16 - (strlen($m) & 0xF);
+ $m.= str_repeat(chr($pad), $pad);
+
+ $length = strlen($m);
+
+ // Step 2. Append Checksum
+ $c = str_repeat(chr(0), 16);
+ $l = chr(0);
+ for ($i = 0; $i < $length; $i+= 16) {
+ for ($j = 0; $j < 16; $j++) {
+ // RFC1319 incorrectly states that C[j] should be set to S[c xor L]
+ //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
+ // per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
+ $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
+ $l = $c[$j];
+ }
+ }
+ $m.= $c;
+
+ $length+= 16;
+
+ // Step 3. Initialize MD Buffer
+ $x = str_repeat(chr(0), 48);
+
+ // Step 4. Process Message in 16-Byte Blocks
+ for ($i = 0; $i < $length; $i+= 16) {
+ for ($j = 0; $j < 16; $j++) {
+ $x[$j + 16] = $m[$i + $j];
+ $x[$j + 32] = $x[$j + 16] ^ $x[$j];
+ }
+ $t = chr(0);
+ for ($j = 0; $j < 18; $j++) {
+ for ($k = 0; $k < 48; $k++) {
+ $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
+ //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
+ }
+ $t = chr(ord($t) + $j);
+ }
+ }
+
+ // Step 5. Output
+ return substr($x, 0, 16);
+ }
+
+ /**
+ * Pure-PHP implementation of SHA256
+ *
+ * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
+ *
+ * @access private
+ * @param String $m
+ */
+ function _sha256($m)
+ {
+ if (extension_loaded('suhosin')) {
+ return pack('H*', sha256($m));
+ }
+
+ // Initialize variables
+ $hash = array(
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+ );
+ // Initialize table of round constants
+ // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
+ static $k = array(
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ );
+
+ // Pre-processing
+ $length = strlen($m);
+ // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
+ $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
+ $m[$length] = chr(0x80);
+ // we don't support hashing strings 512MB long
+ $m.= pack('N2', 0, $length << 3);
+
+ // Process the message in successive 512-bit chunks
+ $chunks = str_split($m, 64);
+ foreach ($chunks as $chunk) {
+ $w = array();
+ for ($i = 0; $i < 16; $i++) {
+ extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
+ $w[] = $temp;
+ }
+
+ // Extend the sixteen 32-bit words into sixty-four 32-bit words
+ for ($i = 16; $i < 64; $i++) {
+ $s0 = $this->_rightRotate($w[$i - 15], 7) ^
+ $this->_rightRotate($w[$i - 15], 18) ^
+ $this->_rightShift( $w[$i - 15], 3);
+ $s1 = $this->_rightRotate($w[$i - 2], 17) ^
+ $this->_rightRotate($w[$i - 2], 19) ^
+ $this->_rightShift( $w[$i - 2], 10);
+ $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
+
+ }
+
+ // Initialize hash value for this chunk
+ list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
+
+ // Main loop
+ for ($i = 0; $i < 64; $i++) {
+ $s0 = $this->_rightRotate($a, 2) ^
+ $this->_rightRotate($a, 13) ^
+ $this->_rightRotate($a, 22);
+ $maj = ($a & $b) ^
+ ($a & $c) ^
+ ($b & $c);
+ $t2 = $this->_add($s0, $maj);
+
+ $s1 = $this->_rightRotate($e, 6) ^
+ $this->_rightRotate($e, 11) ^
+ $this->_rightRotate($e, 25);
+ $ch = ($e & $f) ^
+ ($this->_not($e) & $g);
+ $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
+
+ $h = $g;
+ $g = $f;
+ $f = $e;
+ $e = $this->_add($d, $t1);
+ $d = $c;
+ $c = $b;
+ $b = $a;
+ $a = $this->_add($t1, $t2);
+ }
+
+ // Add this chunk's hash to result so far
+ $hash = array(
+ $this->_add($hash[0], $a),
+ $this->_add($hash[1], $b),
+ $this->_add($hash[2], $c),
+ $this->_add($hash[3], $d),
+ $this->_add($hash[4], $e),
+ $this->_add($hash[5], $f),
+ $this->_add($hash[6], $g),
+ $this->_add($hash[7], $h)
+ );
+ }
+
+ // Produce the final hash value (big-endian)
+ return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
+ }
+
+ /**
+ * Pure-PHP implementation of SHA384 and SHA512
+ *
+ * @access private
+ * @param String $m
+ */
+ function _sha512($m)
+ {
+ if (!class_exists('Math_BigInteger')) {
+ require_once('Math/BigInteger.php');
+ }
+
+ static $init384, $init512, $k;
+
+ if (!isset($k)) {
+ // Initialize variables
+ $init384 = array( // initial values for SHA384
+ 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
+ '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
+ );
+ $init512 = array( // initial values for SHA512
+ '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
+ '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
+ );
+
+ for ($i = 0; $i < 8; $i++) {
+ $init384[$i] = new Math_BigInteger($init384[$i], 16);
+ $init384[$i]->setPrecision(64);
+ $init512[$i] = new Math_BigInteger($init512[$i], 16);
+ $init512[$i]->setPrecision(64);
+ }
+
+ // Initialize table of round constants
+ // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
+ $k = array(
+ '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
+ '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
+ 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
+ '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
+ 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
+ '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
+ '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
+ 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
+ '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
+ '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
+ 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
+ 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
+ '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
+ '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
+ '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
+ '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
+ 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
+ '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
+ '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
+ '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
+ );
+
+ for ($i = 0; $i < 80; $i++) {
+ $k[$i] = new Math_BigInteger($k[$i], 16);
+ }
+ }
+
+ $hash = $this->l == 48 ? $init384 : $init512;
+
+ // Pre-processing
+ $length = strlen($m);
+ // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
+ $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
+ $m[$length] = chr(0x80);
+ // we don't support hashing strings 512MB long
+ $m.= pack('N4', 0, 0, 0, $length << 3);
+
+ // Process the message in successive 1024-bit chunks
+ $chunks = str_split($m, 128);
+ foreach ($chunks as $chunk) {
+ $w = array();
+ for ($i = 0; $i < 16; $i++) {
+ $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
+ $temp->setPrecision(64);
+ $w[] = $temp;
+ }
+
+ // Extend the sixteen 32-bit words into eighty 32-bit words
+ for ($i = 16; $i < 80; $i++) {
+ $temp = array(
+ $w[$i - 15]->bitwise_rightRotate(1),
+ $w[$i - 15]->bitwise_rightRotate(8),
+ $w[$i - 15]->bitwise_rightShift(7)
+ );
+ $s0 = $temp[0]->bitwise_xor($temp[1]);
+ $s0 = $s0->bitwise_xor($temp[2]);
+ $temp = array(
+ $w[$i - 2]->bitwise_rightRotate(19),
+ $w[$i - 2]->bitwise_rightRotate(61),
+ $w[$i - 2]->bitwise_rightShift(6)
+ );
+ $s1 = $temp[0]->bitwise_xor($temp[1]);
+ $s1 = $s1->bitwise_xor($temp[2]);
+ $w[$i] = $w[$i - 16]->copy();
+ $w[$i] = $w[$i]->add($s0);
+ $w[$i] = $w[$i]->add($w[$i - 7]);
+ $w[$i] = $w[$i]->add($s1);
+ }
+
+ // Initialize hash value for this chunk
+ $a = $hash[0]->copy();
+ $b = $hash[1]->copy();
+ $c = $hash[2]->copy();
+ $d = $hash[3]->copy();
+ $e = $hash[4]->copy();
+ $f = $hash[5]->copy();
+ $g = $hash[6]->copy();
+ $h = $hash[7]->copy();
+
+ // Main loop
+ for ($i = 0; $i < 80; $i++) {
+ $temp = array(
+ $a->bitwise_rightRotate(28),
+ $a->bitwise_rightRotate(34),
+ $a->bitwise_rightRotate(39)
+ );
+ $s0 = $temp[0]->bitwise_xor($temp[1]);
+ $s0 = $s0->bitwise_xor($temp[2]);
+ $temp = array(
+ $a->bitwise_and($b),
+ $a->bitwise_and($c),
+ $b->bitwise_and($c)
+ );
+ $maj = $temp[0]->bitwise_xor($temp[1]);
+ $maj = $maj->bitwise_xor($temp[2]);
+ $t2 = $s0->add($maj);
+
+ $temp = array(
+ $e->bitwise_rightRotate(14),
+ $e->bitwise_rightRotate(18),
+ $e->bitwise_rightRotate(41)
+ );
+ $s1 = $temp[0]->bitwise_xor($temp[1]);
+ $s1 = $s1->bitwise_xor($temp[2]);
+ $temp = array(
+ $e->bitwise_and($f),
+ $g->bitwise_and($e->bitwise_not())
+ );
+ $ch = $temp[0]->bitwise_xor($temp[1]);
+ $t1 = $h->add($s1);
+ $t1 = $t1->add($ch);
+ $t1 = $t1->add($k[$i]);
+ $t1 = $t1->add($w[$i]);
+
+ $h = $g->copy();
+ $g = $f->copy();
+ $f = $e->copy();
+ $e = $d->add($t1);
+ $d = $c->copy();
+ $c = $b->copy();
+ $b = $a->copy();
+ $a = $t1->add($t2);
+ }
+
+ // Add this chunk's hash to result so far
+ $hash = array(
+ $hash[0]->add($a),
+ $hash[1]->add($b),
+ $hash[2]->add($c),
+ $hash[3]->add($d),
+ $hash[4]->add($e),
+ $hash[5]->add($f),
+ $hash[6]->add($g),
+ $hash[7]->add($h)
+ );
+ }
+
+ // Produce the final hash value (big-endian)
+ // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
+ $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
+ $hash[4]->toBytes() . $hash[5]->toBytes();
+ if ($this->l != 48) {
+ $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
+ }
+
+ return $temp;
+ }
+
+ /**
+ * Right Rotate
+ *
+ * @access private
+ * @param Integer $int
+ * @param Integer $amt
+ * @see _sha256()
+ * @return Integer
+ */
+ function _rightRotate($int, $amt)
+ {
+ $invamt = 32 - $amt;
+ $mask = (1 << $invamt) - 1;
+ return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
+ }
+
+ /**
+ * Right Shift
+ *
+ * @access private
+ * @param Integer $int
+ * @param Integer $amt
+ * @see _sha256()
+ * @return Integer
+ */
+ function _rightShift($int, $amt)
+ {
+ $mask = (1 << (32 - $amt)) - 1;
+ return ($int >> $amt) & $mask;
+ }
+
+ /**
+ * Not
+ *
+ * @access private
+ * @param Integer $int
+ * @see _sha256()
+ * @return Integer
+ */
+ function _not($int)
+ {
+ return ~$int & 0xFFFFFFFF;
+ }
+
+ /**
+ * Add
+ *
+ * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
+ * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
+ *
+ * @param Integer $...
+ * @return Integer
+ * @see _sha256()
+ * @access private
+ */
+ function _add()
+ {
+ static $mod;
+ if (!isset($mod)) {
+ $mod = pow(2, 32);
+ }
+
+ $result = 0;
+ $arguments = func_get_args();
+ foreach ($arguments as $argument) {
+ $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
+ }
+
+ return fmod($result, $mod);
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param String $string
+ * @param optional Integer $index
+ * @return String
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+}
diff --git a/inc/phpseclib/Crypt_Rijndael.php b/inc/phpseclib/Crypt_Rijndael.php
new file mode 100644
index 000000000..c63e0ff7e
--- /dev/null
+++ b/inc/phpseclib/Crypt_Rijndael.php
@@ -0,0 +1,1374 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Pure-PHP implementation of Rijndael.
+ *
+ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
+ *
+ * PHP versions 4 and 5
+ *
+ * If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
+ * {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
+ * {@link Crypt_Rijndael::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
+ * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
+ * {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.
+ *
+ * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
+ * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
+ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
+ * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224. Indeed, 160 and 224
+ * are first defined as valid key / block lengths in
+ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
+ * Extensions: Other block and Cipher Key lengths.
+ * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
+ *
+ * {@internal The variable names are the same as those in
+ * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include('Crypt/Rijndael.php');
+ *
+ * $rijndael = new Crypt_Rijndael();
+ *
+ * $rijndael->setKey('abcdefghijklmnop');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $rijndael->decrypt($rijndael->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @category Crypt
+ * @package Crypt_Rijndael
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright MMVIII Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+/**
+ * Include Crypt_Base
+ *
+ * Base cipher class
+ */
+if (!class_exists('Crypt_Base')) {
+ require_once('Base.php');
+}
+
+/**#@+
+ * @access public
+ * @see Crypt_Rijndael::encrypt()
+ * @see Crypt_Rijndael::decrypt()
+ */
+/**
+ * Encrypt / decrypt using the Counter mode.
+ *
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
+ */
+define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR);
+/**
+ * Encrypt / decrypt using the Electronic Code Book mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
+ */
+define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB);
+/**
+ * Encrypt / decrypt using the Code Book Chaining mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
+ */
+define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC);
+/**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
+ */
+define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB);
+/**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
+ */
+define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
+/**#@-*/
+
+/**#@+
+ * @access private
+ * @see Crypt_Rijndael::Crypt_Rijndael()
+ */
+/**
+ * Toggles the internal implementation
+ */
+define('CRYPT_RIJNDAEL_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
+/**
+ * Toggles the mcrypt implementation
+ */
+define('CRYPT_RIJNDAEL_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
+/**#@-*/
+
+/**
+ * Pure-PHP implementation of Rijndael.
+ *
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @version 0.1.0
+ * @access public
+ * @package Crypt_Rijndael
+ */
+class Crypt_Rijndael extends Crypt_Base {
+ /**
+ * The default password key_size used by setPassword()
+ *
+ * @see Crypt_Base::password_key_size
+ * @see Crypt_Base::setPassword()
+ * @var Integer
+ * @access private
+ */
+ var $password_key_size = 16;
+
+ /**
+ * The namespace used by the cipher for its constants.
+ *
+ * @see Crypt_Base::const_namespace
+ * @var String
+ * @access private
+ */
+ var $const_namespace = 'RIJNDAEL';
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not.
+ * Crypt_Rijndael determines automatically whether mcrypt is useable
+ * or not for the current $block_size/$key_size.
+ * In case of, $cipher_name_mcrypt will be set dynamicaly at run time accordingly.
+ *
+ * @see Crypt_Base::cipher_name_mcrypt
+ * @see Crypt_Base::engine
+ * @see _setupEngine()
+ * @var String
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'rijndael-128';
+
+ /**
+ * The default salt used by setPassword()
+ *
+ * @see Crypt_Base::password_default_salt
+ * @see Crypt_Base::setPassword()
+ * @var String
+ * @access private
+ */
+ var $password_default_salt = 'phpseclib';
+
+ /**
+ * Has the key length explicitly been set or should it be derived from the key, itself?
+ *
+ * @see setKeyLength()
+ * @var Boolean
+ * @access private
+ */
+ var $explicit_key_length = false;
+
+ /**
+ * The Key Schedule
+ *
+ * @see _setup()
+ * @var Array
+ * @access private
+ */
+ var $w;
+
+ /**
+ * The Inverse Key Schedule
+ *
+ * @see _setup()
+ * @var Array
+ * @access private
+ */
+ var $dw;
+
+ /**
+ * The Block Length divided by 32
+ *
+ * @see setBlockLength()
+ * @var Integer
+ * @access private
+ * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
+ * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
+ * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
+ * of that, we'll just precompute it once.
+ *
+ */
+ var $Nb = 4;
+
+ /**
+ * The Key Length
+ *
+ * @see setKeyLength()
+ * @var Integer
+ * @access private
+ * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
+ * because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
+ * derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
+ * of that, we'll just precompute it once.
+ */
+ var $key_size = 16;
+
+ /**
+ * The Key Length divided by 32
+ *
+ * @see setKeyLength()
+ * @var Integer
+ * @access private
+ * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
+ */
+ var $Nk = 4;
+
+ /**
+ * The Number of Rounds
+ *
+ * @var Integer
+ * @access private
+ * @internal The max value is 14, the min value is 10.
+ */
+ var $Nr;
+
+ /**
+ * Shift offsets
+ *
+ * @var Array
+ * @access private
+ */
+ var $c;
+
+ /**
+ * Holds the last used key- and block_size information
+ *
+ * @var Array
+ * @access private
+ */
+ var $kl;
+
+ /**
+ * Precomputed mixColumns table
+ *
+ * According to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
+ * precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
+ * those are the names we'll use.
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $t0 = array(
+ 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554,
+ 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A,
+ 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
+ 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B,
+ 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F,
+ 0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
+ 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5,
+ 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F,
+ 0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
+ 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497,
+ 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED,
+ 0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
+ 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594,
+ 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3,
+ 0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
+ 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D,
+ 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739,
+ 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
+ 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883,
+ 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76,
+ 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
+ 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B,
+ 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0,
+ 0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
+ 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651,
+ 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85,
+ 0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
+ 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9,
+ 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7,
+ 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
+ 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, 0x844242C6, 0xD06868B8,
+ 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A
+ );
+
+ /**
+ * Precomputed mixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $t1 = array(
+ 0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5,
+ 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676,
+ 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0,
+ 0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0,
+ 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC,
+ 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515,
+ 0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A,
+ 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575,
+ 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0,
+ 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484,
+ 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B,
+ 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF,
+ 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585,
+ 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8,
+ 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5,
+ 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2,
+ 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717,
+ 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373,
+ 0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888,
+ 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB,
+ 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C,
+ 0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979,
+ 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9,
+ 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808,
+ 0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6,
+ 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A,
+ 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E,
+ 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E,
+ 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494,
+ 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF,
+ 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868,
+ 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616
+ );
+
+ /**
+ * Precomputed mixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $t2 = array(
+ 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5,
+ 0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76,
+ 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0,
+ 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0,
+ 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC,
+ 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15,
+ 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A,
+ 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75,
+ 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0,
+ 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384,
+ 0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B,
+ 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF,
+ 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185,
+ 0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8,
+ 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5,
+ 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2,
+ 0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17,
+ 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673,
+ 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88,
+ 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB,
+ 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C,
+ 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279,
+ 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9,
+ 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008,
+ 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6,
+ 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A,
+ 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E,
+ 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E,
+ 0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394,
+ 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF,
+ 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068,
+ 0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16
+ );
+
+ /**
+ * Precomputed mixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $t3 = array(
+ 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
+ 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
+ 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
+ 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
+ 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
+ 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
+ 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
+ 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
+ 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
+ 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
+ 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
+ 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
+ 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
+ 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
+ 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
+ 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
+ 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
+ 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
+ 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
+ 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
+ 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
+ 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
+ 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
+ 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
+ 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
+ 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
+ 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
+ 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
+ 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
+ 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
+ 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
+ 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
+ );
+
+ /**
+ * Precomputed invMixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $dt0 = array(
+ 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1, 0xACFA58AB, 0x4BE30393,
+ 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25, 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F,
+ 0xDEB15A49, 0x25BA1B67, 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6,
+ 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3, 0x49E06929, 0x8EC9C844,
+ 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD, 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4,
+ 0x63DF4A18, 0xE51A3182, 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94,
+ 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2, 0xE31F8F57, 0x6655AB2A,
+ 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C,
+ 0x8ACF1C2B, 0xA779B492, 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A,
+ 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA, 0x5E719F06, 0xBD6E1051,
+ 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF,
+ 0x1998FB24, 0xD6BDE997, 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB,
+ 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48, 0x1E1170AC, 0x6C5A724E,
+ 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927, 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A,
+ 0x0C0A67B1, 0x9357E70F, 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16,
+ 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD, 0x2DB6A8B9, 0x141EA9C8,
+ 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD, 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34,
+ 0x8B432976, 0xCB23C6DC, 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120,
+ 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3, 0x0D8652EC, 0x77C1E3D0,
+ 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422, 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF,
+ 0x87494EC7, 0xD938D1C1, 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4,
+ 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8, 0x2E39F75E, 0x82C3AFF5,
+ 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B,
+ 0xCD267809, 0x6E5918F4, 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6,
+ 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331, 0xC6A59430, 0x35A266C0,
+ 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F,
+ 0x764DD68D, 0x43EFB04D, 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F,
+ 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252, 0xE9105633, 0x6DD64713,
+ 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89, 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C,
+ 0x9CD2DF59, 0x55F2733F, 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86,
+ 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C, 0x283C498B, 0xFF0D9541,
+ 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190, 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742
+ );
+
+ /**
+ * Precomputed invMixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $dt1 = array(
+ 0x5051F4A7, 0x537E4165, 0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45, 0xABACFA58, 0x934BE303,
+ 0x552030FA, 0xF6AD766D, 0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB, 0x80263544, 0x8FB562A3,
+ 0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0, 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9,
+ 0xE7038F5F, 0x9515929C, 0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421, 0x2949E069, 0x448EC9C8,
+ 0x6A75C289, 0x78F48E79, 0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD, 0x66C920AC, 0xB47DCE3A,
+ 0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F, 0xE0B16477, 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B,
+ 0x58704868, 0x198F45FD, 0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02, 0x57E31F8F, 0x2A6655AB,
+ 0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5, 0xBA02036A, 0x5CED1682,
+ 0x2B8ACF1C, 0x92A779B4, 0xF0F307F2, 0xA14E69E2, 0xCD65DAF4, 0xD50605BE, 0x1FD13462, 0x8AC4A6FE,
+ 0x9D342E53, 0xA0A2F355, 0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10,
+ 0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D, 0x6F0406D4, 0xFF605015,
+ 0x241998FB, 0x97D6BDE9, 0xCC894043, 0x7767D99E, 0xBDB0E842, 0x8807898B, 0x38E7195B, 0xDB79C8EE,
+ 0x47A17C0A, 0xE97C420F, 0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72,
+ 0xFBFD0EFF, 0x560F8538, 0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6, 0xD19B5B54, 0x3A24362E,
+ 0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, 0x9E1B9B91, 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A,
+ 0x0AE293BA, 0xE5C0A02A, 0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9,
+ 0x8557F119, 0x4CAF7507, 0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5, 0xC544663B, 0x345BFB7E,
+ 0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1, 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611,
+ 0x7D854A24, 0xF8D2BB3D, 0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230, 0xEC0D8652, 0xD077C1E3,
+ 0x6C2BB316, 0x99A970B9, 0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F, 0xD8567D2C, 0xEF223390,
+ 0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B, 0xCFA6F581, 0x28A57ADE, 0x26DAB78E, 0xA43FADBF,
+ 0xE42C3A9D, 0x0D507892, 0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, 0xF582C3AF,
+ 0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D, 0x6EE89C63, 0x7BDB3BBB,
+ 0x09CD2678, 0xF46E5918, 0x01EC9AB7, 0xA8834F9A, 0x65E6956E, 0x7EAAFFE6, 0x0821BCCF, 0xE6EF15E8,
+ 0xD9BAE79B, 0xCE4A6F36, 0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266,
+ 0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA, 0x0E7FCD50, 0x2F1791F6,
+ 0x8D764DD6, 0x4D43EFB0, 0x54CCAA4D, 0xDFE49604, 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, 0x7F466551,
+ 0x049D5EEA, 0x5D018C35, 0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647,
+ 0x8C9AD761, 0x7A37A10C, 0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9, 0xEDE11CE5, 0x3C7A47B1,
+ 0x599CD2DF, 0x3F55F273, 0x791814CE, 0xBF73C737, 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB,
+ 0x81CAAFF3, 0x3EB968C4, 0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225, 0x8B283C49, 0x41FF0D95,
+ 0x7139A801, 0xDE080CB3, 0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6, 0x74486C5C, 0x42D0B857
+ );
+
+ /**
+ * Precomputed invMixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $dt2 = array(
+ 0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27, 0x6BCB3BAB, 0x45F11F9D, 0x58ABACFA, 0x03934BE3,
+ 0xFA552030, 0x6DF6AD76, 0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, 0xA38FB562,
+ 0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C, 0x97A38D46, 0xF9C66BD3,
+ 0x5FE7038F, 0x9C951592, 0x7AEBBF6D, 0x59DA9552, 0x832DD4BE, 0x21D35874, 0x692949E0, 0xC8448EC9,
+ 0x896A75C2, 0x7978F48E, 0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE,
+ 0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B, 0xA01CFE81, 0x2B94F908,
+ 0x68587048, 0xFD198F45, 0x6C8794DE, 0xF8B7527B, 0xD323AB73, 0x02E2724B, 0x8F57E31F, 0xAB2A6655,
+ 0x2807B2EB, 0xC2032FB5, 0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16,
+ 0x1C2B8ACF, 0xB492A779, 0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605, 0x621FD134, 0xFE8AC4A6,
+ 0x539D342E, 0x55A0A2F3, 0xE132058A, 0xEB75A4F6, 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E,
+ 0x8AF93E21, 0x063D96DD, 0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4, 0xD46F0406, 0x15FF6050,
+ 0xFB241998, 0xE997D6BD, 0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789, 0x5B38E719, 0xEEDB79C8,
+ 0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000, 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A,
+ 0xFFFBFD0E, 0x38560F85, 0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C, 0x54D19B5B, 0x2E3A2436,
+ 0x67B10C0A, 0xE70F9357, 0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC, 0x4B695A77, 0x1A161C12,
+ 0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B, 0x0D0B0E09, 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E,
+ 0x198557F1, 0x074CAF75, 0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72, 0x3BC54466, 0x7E345BFB,
+ 0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263, 0x22401397, 0x112084C6,
+ 0x247D854A, 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729, 0x2F4B1D9E, 0x30F3DCB2, 0x52EC0D86, 0xE3D077C1,
+ 0x166C2BB3, 0xB999A970, 0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233,
+ 0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A, 0x8E26DAB7, 0xBFA43FAD,
+ 0x9DE42C3A, 0x920D5078, 0xCC9B6A5F, 0x4662547E, 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, 0xAFF582C3,
+ 0x80BE9F5D, 0x937C69D0, 0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B,
+ 0x7809CD26, 0x18F46E59, 0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF, 0xCF0821BC, 0xE8E6EF15,
+ 0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, 0x7CD629B0, 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2,
+ 0xBC37744E, 0xCAA6FC82, 0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC, 0x500E7FCD, 0xF62F1791,
+ 0xD68D764D, 0xB04D43EF, 0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A, 0x1FB8C12C, 0x517F4665,
+ 0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B, 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6,
+ 0x618C9AD7, 0x0C7A37A1, 0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761, 0xE5EDE11C, 0xB13C7A47,
+ 0xDF599CD2, 0x733F55F2, 0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD, 0x6F14DF3D, 0xDB867844,
+ 0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3, 0xC372161D, 0x250CBCE2, 0x498B283C, 0x9541FF0D,
+ 0x017139A8, 0xB3DE080C, 0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532, 0x5C74486C, 0x5742D0B8
+ );
+
+ /**
+ * Precomputed invMixColumns table
+ *
+ * @see Crypt_Rijndael:_encryptBlock()
+ * @see Crypt_Rijndael:_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $dt3 = array(
+ 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
+ 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
+ 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
+ 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
+ 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
+ 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
+ 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
+ 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
+ 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
+ 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
+ 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
+ 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
+ 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
+ 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
+ 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
+ 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
+ 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
+ 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
+ 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
+ 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
+ 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
+ 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
+ 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
+ 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
+ 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
+ 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
+ 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
+ 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
+ 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
+ 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
+ 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
+ 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
+ );
+
+ /**
+ * The SubByte S-Box
+ *
+ * @see Crypt_Rijndael::_encryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $sbox = array(
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+ );
+
+ /**
+ * The inverse SubByte S-Box
+ *
+ * @see Crypt_Rijndael::_decryptBlock()
+ * @var Array
+ * @access private
+ */
+ var $isbox = array(
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+ );
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * $mode could be:
+ *
+ * - CRYPT_RIJNDAEL_MODE_ECB
+ *
+ * - CRYPT_RIJNDAEL_MODE_CBC
+ *
+ * - CRYPT_RIJNDAEL_MODE_CTR
+ *
+ * - CRYPT_RIJNDAEL_MODE_CFB
+ *
+ * - CRYPT_RIJNDAEL_MODE_OFB
+ *
+ * If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
+ *
+ * @see Crypt_Base::Crypt_Base()
+ * @param optional Integer $mode
+ * @access public
+ */
+ function Crypt_Rijndael($mode = CRYPT_RIJNDAEL_MODE_CBC)
+ {
+ parent::Crypt_Base($mode);
+ }
+
+ /**
+ * Sets the key.
+ *
+ * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
+ * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
+ * up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
+ * excess bits.
+ *
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
+ *
+ * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
+ *
+ * @see Crypt_Base:setKey()
+ * @see setKeyLength()
+ * @access public
+ * @param String $key
+ */
+ function setKey($key)
+ {
+ parent::setKey($key);
+
+ if (!$this->explicit_key_length) {
+ $length = strlen($key);
+ switch (true) {
+ case $length <= 16:
+ $this->key_size = 16;
+ break;
+ case $length <= 24:
+ $this->key_size = 24;
+ break;
+ default:
+ $this->key_size = 32;
+ }
+ $this->_setupEngine();
+ }
+ }
+
+ /**
+ * Sets the key length
+ *
+ * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
+ *
+ * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
+ * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
+ * 192/256 bits as, for example, mcrypt will do.
+ *
+ * That said, if you want be compatible with other Rijndael and AES implementations,
+ * you should not setKeyLength(160) or setKeyLength(224).
+ *
+ * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
+ * the mcrypt php extention, even if available.
+ * This results then in slower encryption.
+ *
+ * @access public
+ * @param Integer $length
+ */
+ function setKeyLength($length)
+ {
+ switch (true) {
+ case $length == 160:
+ $this->key_size = 20;
+ break;
+ case $length == 224:
+ $this->key_size = 28;
+ break;
+ case $length <= 128:
+ $this->key_size = 16;
+ break;
+ case $length <= 192:
+ $this->key_size = 24;
+ break;
+ default:
+ $this->key_size = 32;
+ }
+
+ $this->explicit_key_length = true;
+ $this->changed = true;
+ $this->_setupEngine();
+ }
+
+ /**
+ * Sets the block length
+ *
+ * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
+ *
+ * @access public
+ * @param Integer $length
+ */
+ function setBlockLength($length)
+ {
+ $length >>= 5;
+ if ($length > 8) {
+ $length = 8;
+ } else if ($length < 4) {
+ $length = 4;
+ }
+ $this->Nb = $length;
+ $this->block_size = $length << 2;
+ $this->changed = true;
+ $this->_setupEngine();
+ }
+
+ /**
+ * Setup the fastest possible $engine
+ *
+ * Determines if the mcrypt (MODE_MCRYPT) $engine available
+ * and usable for the current $block_size and $key_size.
+ *
+ * If not, the slower MODE_INTERNAL $engine will be set.
+ *
+ * @see setKey()
+ * @see setKeyLength()
+ * @see setBlockLength()
+ * @access private
+ */
+ function _setupEngine()
+ {
+ if (constant('CRYPT_' . $this->const_namespace . '_MODE') == CRYPT_MODE_INTERNAL) {
+ // No mcrypt support at all for rijndael
+ return;
+ }
+
+ // The required mcrypt module name for the current $block_size of rijndael
+ $cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
+
+ // Determining the availibility/usability of $cipher_name_mcrypt
+ switch (true) {
+ case $this->key_size % 8: // mcrypt is not usable for 160/224-bit keys, only for 128/192/256-bit keys
+ case !in_array($cipher_name_mcrypt, mcrypt_list_algorithms()): // $cipher_name_mcrypt is not available for the current $block_size
+ $engine = CRYPT_MODE_INTERNAL;
+ break;
+ default:
+ $engine = CRYPT_MODE_MCRYPT;
+ }
+
+ if ($this->engine == $engine && $this->cipher_name_mcrypt == $cipher_name_mcrypt) {
+ // allready set, so we not unnecessary close $this->enmcrypt/demcrypt/ecb
+ return;
+ }
+
+ // Set the $engine
+ $this->engine = $engine;
+ $this->cipher_name_mcrypt = $cipher_name_mcrypt;
+
+ if ($this->enmcrypt) {
+ // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
+ // (re)open them with the module named in $this->cipher_name_mcrypt
+ mcrypt_module_close($this->enmcrypt);
+ mcrypt_module_close($this->demcrypt);
+ $this->enmcrypt = null;
+ $this->demcrypt = null;
+
+ if ($this->ecb) {
+ mcrypt_module_close($this->ecb);
+ $this->ecb = null;
+ }
+ }
+ }
+
+ /**
+ * Setup the CRYPT_MODE_MCRYPT $engine
+ *
+ * @see Crypt_Base::_setupMcrypt()
+ * @access private
+ */
+ function _setupMcrypt()
+ {
+ $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
+ parent::_setupMcrypt();
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @access private
+ * @param String $in
+ * @return String
+ */
+ function _encryptBlock($in)
+ {
+ static $t0, $t1, $t2, $t3, $sbox;
+ if (!$t0) {
+ for ($i = 0; $i < 256; ++$i) {
+ $t0[] = (int)$this->t0[$i];
+ $t1[] = (int)$this->t1[$i];
+ $t2[] = (int)$this->t2[$i];
+ $t3[] = (int)$this->t3[$i];
+ $sbox[] = (int)$this->sbox[$i];
+ }
+ }
+
+ $state = array();
+ $words = unpack('N*', $in);
+
+ $c = $this->c;
+ $w = $this->w;
+ $Nb = $this->Nb;
+ $Nr = $this->Nr;
+
+ // addRoundKey
+ $i = -1;
+ foreach ($words as $word) {
+ $state[] = $word ^ $w[0][++$i];
+ }
+
+ // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
+ // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
+ // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
+ // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
+ // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
+ // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
+
+ // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
+ $temp = array();
+ for ($round = 1; $round < $Nr; ++$round) {
+ $i = 0; // $c[0] == 0
+ $j = $c[1];
+ $k = $c[2];
+ $l = $c[3];
+
+ while ($i < $Nb) {
+ $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
+ $t1[$state[$j] >> 16 & 0x000000FF] ^
+ $t2[$state[$k] >> 8 & 0x000000FF] ^
+ $t3[$state[$l] & 0x000000FF] ^
+ $w[$round][$i];
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+ $state = $temp;
+ }
+
+ // subWord
+ for ($i = 0; $i < $Nb; ++$i) {
+ $state[$i] = $sbox[$state[$i] & 0x000000FF] |
+ ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) |
+ ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
+ ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
+ }
+
+ // shiftRows + addRoundKey
+ $i = 0; // $c[0] == 0
+ $j = $c[1];
+ $k = $c[2];
+ $l = $c[3];
+ while ($i < $Nb) {
+ $temp[$i] = ($state[$i] & 0xFF000000) ^
+ ($state[$j] & 0x00FF0000) ^
+ ($state[$k] & 0x0000FF00) ^
+ ($state[$l] & 0x000000FF) ^
+ $w[$Nr][$i];
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+
+ switch ($Nb) {
+ case 8:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
+ case 7:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
+ case 6:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
+ case 5:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
+ default:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
+ }
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @access private
+ * @param String $in
+ * @return String
+ */
+ function _decryptBlock($in)
+ {
+ static $dt0, $dt1, $dt2, $dt3, $isbox;
+ if (!$dt0) {
+ for ($i = 0; $i < 256; ++$i) {
+ $dt0[] = (int)$this->dt0[$i];
+ $dt1[] = (int)$this->dt1[$i];
+ $dt2[] = (int)$this->dt2[$i];
+ $dt3[] = (int)$this->dt3[$i];
+ $isbox[] = (int)$this->isbox[$i];
+ }
+ }
+
+ $state = array();
+ $words = unpack('N*', $in);
+
+ $c = $this->c;
+ $dw = $this->dw;
+ $Nb = $this->Nb;
+ $Nr = $this->Nr;
+
+ // addRoundKey
+ $i = -1;
+ foreach ($words as $word) {
+ $state[] = $word ^ $dw[$Nr][++$i];
+ }
+
+ $temp = array();
+ for ($round = $Nr - 1; $round > 0; --$round) {
+ $i = 0; // $c[0] == 0
+ $j = $Nb - $c[1];
+ $k = $Nb - $c[2];
+ $l = $Nb - $c[3];
+
+ while ($i < $Nb) {
+ $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
+ $dt1[$state[$j] >> 16 & 0x000000FF] ^
+ $dt2[$state[$k] >> 8 & 0x000000FF] ^
+ $dt3[$state[$l] & 0x000000FF] ^
+ $dw[$round][$i];
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+ $state = $temp;
+ }
+
+ // invShiftRows + invSubWord + addRoundKey
+ $i = 0; // $c[0] == 0
+ $j = $Nb - $c[1];
+ $k = $Nb - $c[2];
+ $l = $Nb - $c[3];
+
+ while ($i < $Nb) {
+ $word = ($state[$i] & 0xFF000000) |
+ ($state[$j] & 0x00FF0000) |
+ ($state[$k] & 0x0000FF00) |
+ ($state[$l] & 0x000000FF);
+
+ $temp[$i] = $dw[0][$i] ^ ($isbox[$word & 0x000000FF] |
+ ($isbox[$word >> 8 & 0x000000FF] << 8) |
+ ($isbox[$word >> 16 & 0x000000FF] << 16) |
+ ($isbox[$word >> 24 & 0x000000FF] << 24));
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+
+ switch ($Nb) {
+ case 8:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
+ case 7:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
+ case 6:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
+ case 5:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
+ default:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
+ }
+ }
+
+ /**
+ * Setup the key (expansion)
+ *
+ * @see Crypt_Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
+ // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
+ static $rcon = array(0,
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+ 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
+ 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
+ 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
+ 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
+ 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
+ );
+
+ $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
+
+ if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) {
+ // already expanded
+ return;
+ }
+ $this->kl = array('key' => $this->key, 'key_size' => $this->key_size, 'block_size' => $this->block_size);
+
+ $this->Nk = $this->key_size >> 2;
+ // see Rijndael-ammended.pdf#page=44
+ $this->Nr = max($this->Nk, $this->Nb) + 6;
+
+ // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
+ // "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
+ // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
+ // "Table 2: Shift offsets for different block lengths"
+ switch ($this->Nb) {
+ case 4:
+ case 5:
+ case 6:
+ $this->c = array(0, 1, 2, 3);
+ break;
+ case 7:
+ $this->c = array(0, 1, 2, 4);
+ break;
+ case 8:
+ $this->c = array(0, 1, 3, 4);
+ }
+
+ $w = array_values(unpack('N*words', $this->key));
+
+ $length = $this->Nb * ($this->Nr + 1);
+ for ($i = $this->Nk; $i < $length; $i++) {
+ $temp = $w[$i - 1];
+ if ($i % $this->Nk == 0) {
+ // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
+ // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
+ // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
+ // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
+ $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
+ $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
+ } else if ($this->Nk > 6 && $i % $this->Nk == 4) {
+ $temp = $this->_subWord($temp);
+ }
+ $w[$i] = $w[$i - $this->Nk] ^ $temp;
+ }
+
+ // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
+ // and generate the inverse key schedule. more specifically,
+ // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
+ // "The key expansion for the Inverse Cipher is defined as follows:
+ // 1. Apply the Key Expansion.
+ // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
+ // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
+ $temp = $this->w = $this->dw = array();
+ for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
+ if ($col == $this->Nb) {
+ if ($row == 0) {
+ $this->dw[0] = $this->w[0];
+ } else {
+ // subWord + invMixColumn + invSubWord = invMixColumn
+ $j = 0;
+ while ($j < $this->Nb) {
+ $dw = $this->_subWord($this->w[$row][$j]);
+ $temp[$j] = $this->dt0[$dw >> 24 & 0x000000FF] ^
+ $this->dt1[$dw >> 16 & 0x000000FF] ^
+ $this->dt2[$dw >> 8 & 0x000000FF] ^
+ $this->dt3[$dw & 0x000000FF];
+ $j++;
+ }
+ $this->dw[$row] = $temp;
+ }
+
+ $col = 0;
+ $row++;
+ }
+ $this->w[$row][$col] = $w[$i];
+ }
+
+ $this->dw[$row] = $this->w[$row];
+
+ // In case of $this->use_inline_crypt === true we have to use 1-dim key arrays (both ascending)
+ if ($this->use_inline_crypt) {
+ $this->dw = array_reverse($this->dw);
+ $w = array_pop($this->w);
+ $dw = array_pop($this->dw);
+ foreach ($this->w as $r => $wr) {
+ foreach ($wr as $c => $wc) {
+ $w[] = $wc;
+ $dw[] = $this->dw[$r][$c];
+ }
+ }
+ $this->w = $w;
+ $this->dw = $dw;
+ }
+ }
+
+ /**
+ * Performs S-Box substitutions
+ *
+ * @access private
+ * @param Integer $word
+ */
+ function _subWord($word)
+ {
+ $sbox = $this->sbox;
+
+ return $sbox[$word & 0x000000FF] |
+ ($sbox[$word >> 8 & 0x000000FF] << 8) |
+ ($sbox[$word >> 16 & 0x000000FF] << 16) |
+ ($sbox[$word >> 24 & 0x000000FF] << 24);
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * @see Crypt_Base::_setupInlineCrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ // Note: _setupInlineCrypt() will be called only if $this->changed === true
+ // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
+ // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
+
+ $lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();
+
+ // The first 10 generated $lambda_functions will use the key-words hardcoded for better performance.
+ // For memory reason we limit those ultra-optimized functions.
+ // After that, we use pure (extracted) integer vars for the key-words which is faster than accessing them via array.
+ if (count($lambda_functions) < 10) {
+ $w = $this->w;
+ $dw = $this->dw;
+ $init_encrypt = '';
+ $init_decrypt = '';
+ } else {
+ for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
+ $w[] = '$w[' . $i . ']';
+ $dw[] = '$dw[' . $i . ']';
+ }
+ $init_encrypt = '$w = $self->w;';
+ $init_decrypt = '$dw = $self->dw;';
+ }
+
+ $code_hash = md5(str_pad("Crypt_Rijndael, {$this->mode}, {$this->block_size}, ", 32, "\0") . implode(',', $w));
+
+ if (!isset($lambda_functions[$code_hash])) {
+ $Nr = $this->Nr;
+ $Nb = $this->Nb;
+ $c = $this->c;
+
+ // Generating encrypt code:
+ $init_encrypt.= '
+ static $t0, $t1, $t2, $t3, $sbox;
+ if (!$t0) {
+ for ($i = 0; $i < 256; ++$i) {
+ $t0[$i] = (int)$self->t0[$i];
+ $t1[$i] = (int)$self->t1[$i];
+ $t2[$i] = (int)$self->t2[$i];
+ $t3[$i] = (int)$self->t3[$i];
+ $sbox[$i] = (int)$self->sbox[$i];
+ }
+ }
+ ';
+
+ $s = 'e';
+ $e = 's';
+ $wc = $Nb - 1;
+
+ // Preround: addRoundKey
+ $encrypt_block = '$in = unpack("N*", $in);'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
+ }
+
+ // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
+ for ($round = 1; $round < $Nr; ++$round) {
+ list($s, $e) = array($e, $s);
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block.=
+ '$'.$e.$i.' =
+ $t0[($'.$s.$i .' >> 24) & 0xff] ^
+ $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
+ $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^
+ $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^
+ '.$w[++$wc].";\n";
+ }
+ }
+
+ // Finalround: subWord + shiftRows + addRoundKey
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block.=
+ '$'.$e.$i.' =
+ $sbox[ $'.$e.$i.' & 0xff] |
+ ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
+ ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
+ ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
+ }
+ $encrypt_block .= '$in = pack("N*"'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block.= ',
+ ($'.$e.$i .' & 0xFF000000) ^
+ ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000) ^
+ ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00) ^
+ ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF) ^
+ '.$w[$i]."\n";
+ }
+ $encrypt_block .= ');';
+
+ // Generating decrypt code:
+ $init_decrypt.= '
+ static $dt0, $dt1, $dt2, $dt3, $isbox;
+ if (!$dt0) {
+ for ($i = 0; $i < 256; ++$i) {
+ $dt0[$i] = (int)$self->dt0[$i];
+ $dt1[$i] = (int)$self->dt1[$i];
+ $dt2[$i] = (int)$self->dt2[$i];
+ $dt3[$i] = (int)$self->dt3[$i];
+ $isbox[$i] = (int)$self->isbox[$i];
+ }
+ }
+ ';
+
+ $s = 'e';
+ $e = 's';
+ $wc = $Nb - 1;
+
+ // Preround: addRoundKey
+ $decrypt_block = '$in = unpack("N*", $in);'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
+ }
+
+ // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
+ for ($round = 1; $round < $Nr; ++$round) {
+ list($s, $e) = array($e, $s);
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block.=
+ '$'.$e.$i.' =
+ $dt0[($'.$s.$i .' >> 24) & 0xff] ^
+ $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
+ $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^
+ $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^
+ '.$dw[++$wc].";\n";
+ }
+ }
+
+ // Finalround: subWord + shiftRows + addRoundKey
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block.=
+ '$'.$e.$i.' =
+ $isbox[ $'.$e.$i.' & 0xff] |
+ ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
+ ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
+ ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
+ }
+ $decrypt_block .= '$in = pack("N*"'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block.= ',
+ ($'.$e.$i. ' & 0xFF000000) ^
+ ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000) ^
+ ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00) ^
+ ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF) ^
+ '.$dw[$i]."\n";
+ }
+ $decrypt_block .= ');';
+
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
+ array(
+ 'init_crypt' => '',
+ 'init_encrypt' => $init_encrypt,
+ 'init_decrypt' => $init_decrypt,
+ 'encrypt_block' => $encrypt_block,
+ 'decrypt_block' => $decrypt_block
+ )
+ );
+ }
+ $this->inline_crypt = $lambda_functions[$code_hash];
+ }
+}
+
+// vim: ts=4:sw=4:et:
+// vim6: fdl=1:
diff --git a/inc/phpseclib/LICENSE b/inc/phpseclib/LICENSE
new file mode 100644
index 000000000..6ecd9b9be
--- /dev/null
+++ b/inc/phpseclib/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2007-2012 TerraFrost and other contributors
+http://phpseclib.sourceforge.net/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/inc/phpseclib/Math_BigInteger.php b/inc/phpseclib/Math_BigInteger.php
new file mode 100644
index 000000000..a37662da9
--- /dev/null
+++ b/inc/phpseclib/Math_BigInteger.php
@@ -0,0 +1,3651 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Pure-PHP arbitrary precision integer arithmetic library.
+ *
+ * Supports base-2, base-10, base-16, and base-256 numbers. Uses the GMP or BCMath extensions, if available,
+ * and an internal implementation, otherwise.
+ *
+ * PHP versions 4 and 5
+ *
+ * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
+ * {@link MATH_BIGINTEGER_MODE_INTERNAL MATH_BIGINTEGER_MODE_INTERNAL} mode)
+ *
+ * Math_BigInteger uses base-2**26 to perform operations such as multiplication and division and
+ * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction. Because the largest possible
+ * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
+ * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
+ * used. As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %,
+ * which only supports integers. Although this fact will slow this library down, the fact that such a high
+ * base is being used should more than compensate.
+ *
+ * When PHP version 6 is officially released, we'll be able to use 64-bit integers. This should, once again,
+ * allow bitwise operators, and will increase the maximum possible base to 2**31 (or 2**62 for addition /
+ * subtraction).
+ *
+ * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie.
+ * (new Math_BigInteger(pow(2, 26)))->value = array(0, 1)
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}
+ * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}
+ * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip
+ *
+ * Here's an example of how to use this library:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger(2);
+ * $b = new Math_BigInteger(3);
+ *
+ * $c = $a->add($b);
+ *
+ * echo $c->toString(); // outputs 5
+ * ?>
+ * </code>
+ *
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @category Math
+ * @package Math_BigInteger
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright MMVI Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://pear.php.net/package/Math_BigInteger
+ */
+
+/**#@+
+ * Reduction constants
+ *
+ * @access private
+ * @see Math_BigInteger::_reduce()
+ */
+/**
+ * @see Math_BigInteger::_montgomery()
+ * @see Math_BigInteger::_prepMontgomery()
+ */
+define('MATH_BIGINTEGER_MONTGOMERY', 0);
+/**
+ * @see Math_BigInteger::_barrett()
+ */
+define('MATH_BIGINTEGER_BARRETT', 1);
+/**
+ * @see Math_BigInteger::_mod2()
+ */
+define('MATH_BIGINTEGER_POWEROF2', 2);
+/**
+ * @see Math_BigInteger::_remainder()
+ */
+define('MATH_BIGINTEGER_CLASSIC', 3);
+/**
+ * @see Math_BigInteger::__clone()
+ */
+define('MATH_BIGINTEGER_NONE', 4);
+/**#@-*/
+
+/**#@+
+ * Array constants
+ *
+ * Rather than create a thousands and thousands of new Math_BigInteger objects in repeated function calls to add() and
+ * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
+ *
+ * @access private
+ */
+/**
+ * $result[MATH_BIGINTEGER_VALUE] contains the value.
+ */
+define('MATH_BIGINTEGER_VALUE', 0);
+/**
+ * $result[MATH_BIGINTEGER_SIGN] contains the sign.
+ */
+define('MATH_BIGINTEGER_SIGN', 1);
+/**#@-*/
+
+/**#@+
+ * @access private
+ * @see Math_BigInteger::_montgomery()
+ * @see Math_BigInteger::_barrett()
+ */
+/**
+ * Cache constants
+ *
+ * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.
+ */
+define('MATH_BIGINTEGER_VARIABLE', 0);
+/**
+ * $cache[MATH_BIGINTEGER_DATA] contains the cached data.
+ */
+define('MATH_BIGINTEGER_DATA', 1);
+/**#@-*/
+
+/**#@+
+ * Mode constants.
+ *
+ * @access private
+ * @see Math_BigInteger::Math_BigInteger()
+ */
+/**
+ * To use the pure-PHP implementation
+ */
+define('MATH_BIGINTEGER_MODE_INTERNAL', 1);
+/**
+ * To use the BCMath library
+ *
+ * (if enabled; otherwise, the internal implementation will be used)
+ */
+define('MATH_BIGINTEGER_MODE_BCMATH', 2);
+/**
+ * To use the GMP library
+ *
+ * (if present; otherwise, either the BCMath or the internal implementation will be used)
+ */
+define('MATH_BIGINTEGER_MODE_GMP', 3);
+/**#@-*/
+
+/**
+ * Karatsuba Cutoff
+ *
+ * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
+ *
+ * @access private
+ */
+define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25);
+
+/**
+ * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
+ * numbers.
+ *
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @version 1.0.0RC4
+ * @access public
+ * @package Math_BigInteger
+ */
+class Math_BigInteger {
+ /**
+ * Holds the BigInteger's value.
+ *
+ * @var Array
+ * @access private
+ */
+ var $value;
+
+ /**
+ * Holds the BigInteger's magnitude.
+ *
+ * @var Boolean
+ * @access private
+ */
+ var $is_negative = false;
+
+ /**
+ * Random number generator function
+ *
+ * @see setRandomGenerator()
+ * @access private
+ */
+ var $generator = 'mt_rand';
+
+ /**
+ * Precision
+ *
+ * @see setPrecision()
+ * @access private
+ */
+ var $precision = -1;
+
+ /**
+ * Precision Bitmask
+ *
+ * @see setPrecision()
+ * @access private
+ */
+ var $bitmask = false;
+
+ /**
+ * Mode independent value used for serialization.
+ *
+ * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
+ * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
+ * however, $this->hex is only calculated when $this->__sleep() is called.
+ *
+ * @see __sleep()
+ * @see __wakeup()
+ * @var String
+ * @access private
+ */
+ var $hex;
+
+ /**
+ * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
+ *
+ * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
+ * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
+ *
+ * Here's an example:
+ * <code>
+ * &lt;?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('0x32', 16); // 50 in base-16
+ *
+ * echo $a->toString(); // outputs 50
+ * ?&gt;
+ * </code>
+ *
+ * @param optional $x base-10 number or base-$base number if $base set.
+ * @param optional integer $base
+ * @return Math_BigInteger
+ * @access public
+ */
+ function Math_BigInteger($x = 0, $base = 10)
+ {
+ if ( !defined('MATH_BIGINTEGER_MODE') ) {
+ switch (true) {
+ case extension_loaded('gmp'):
+ define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
+ break;
+ case extension_loaded('bcmath'):
+ define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);
+ break;
+ default:
+ define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);
+ }
+ }
+
+ if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
+ define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
+ }
+
+ if (!defined('PHP_INT_SIZE')) {
+ define('PHP_INT_SIZE', 4);
+ }
+
+ if (!defined('MATH_BIGINTEGER_BASE') && MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL) {
+ switch (PHP_INT_SIZE) {
+ case 8: // use 64-bit integers if int size is 8 bytes
+ define('MATH_BIGINTEGER_BASE', 31);
+ define('MATH_BIGINTEGER_BASE_FULL', 0x80000000);
+ define('MATH_BIGINTEGER_MAX_DIGIT', 0x7FFFFFFF);
+ define('MATH_BIGINTEGER_MSB', 0x40000000);
+ // 10**9 is the closest we can get to 2**31 without passing it
+ define('MATH_BIGINTEGER_MAX10', 1000000000);
+ define('MATH_BIGINTEGER_MAX10_LEN', 9);
+ // the largest digit that may be used in addition / subtraction
+ define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 62));
+ break;
+ //case 4: // use 64-bit floats if int size is 4 bytes
+ default:
+ define('MATH_BIGINTEGER_BASE', 26);
+ define('MATH_BIGINTEGER_BASE_FULL', 0x4000000);
+ define('MATH_BIGINTEGER_MAX_DIGIT', 0x3FFFFFF);
+ define('MATH_BIGINTEGER_MSB', 0x2000000);
+ // 10**7 is the closest to 2**26 without passing it
+ define('MATH_BIGINTEGER_MAX10', 10000000);
+ define('MATH_BIGINTEGER_MAX10_LEN', 7);
+ // the largest digit that may be used in addition / subtraction
+ // we do pow(2, 52) instead of using 4503599627370496 directly because some
+ // PHP installations will truncate 4503599627370496.
+ define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 52));
+ }
+ }
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ if (is_resource($x) && get_resource_type($x) == 'GMP integer') {
+ $this->value = $x;
+ return;
+ }
+ $this->value = gmp_init(0);
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $this->value = '0';
+ break;
+ default:
+ $this->value = array();
+ }
+
+ // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
+ // '0' is the only value like this per http://php.net/empty
+ if (empty($x) && (abs($base) != 256 || $x !== '0')) {
+ return;
+ }
+
+ switch ($base) {
+ case -256:
+ if (ord($x[0]) & 0x80) {
+ $x = ~$x;
+ $this->is_negative = true;
+ }
+ case 256:
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $sign = $this->is_negative ? '-' : '';
+ $this->value = gmp_init($sign . '0x' . bin2hex($x));
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ // round $len to the nearest 4 (thanks, DavidMJ!)
+ $len = (strlen($x) + 3) & 0xFFFFFFFC;
+
+ $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
+
+ for ($i = 0; $i < $len; $i+= 4) {
+ $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32
+ $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0);
+ }
+
+ if ($this->is_negative) {
+ $this->value = '-' . $this->value;
+ }
+
+ break;
+ // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
+ default:
+ while (strlen($x)) {
+ $this->value[] = $this->_bytes2int($this->_base256_rshift($x, MATH_BIGINTEGER_BASE));
+ }
+ }
+
+ if ($this->is_negative) {
+ if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
+ $this->is_negative = false;
+ }
+ $temp = $this->add(new Math_BigInteger('-1'));
+ $this->value = $temp->value;
+ }
+ break;
+ case 16:
+ case -16:
+ if ($base > 0 && $x[0] == '-') {
+ $this->is_negative = true;
+ $x = substr($x, 1);
+ }
+
+ $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
+
+ $is_negative = false;
+ if ($base < 0 && hexdec($x[0]) >= 8) {
+ $this->is_negative = $is_negative = true;
+ $x = bin2hex(~pack('H*', $x));
+ }
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
+ $this->value = gmp_init($temp);
+ $this->is_negative = false;
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
+ $temp = new Math_BigInteger(pack('H*', $x), 256);
+ $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
+ $this->is_negative = false;
+ break;
+ default:
+ $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
+ $temp = new Math_BigInteger(pack('H*', $x), 256);
+ $this->value = $temp->value;
+ }
+
+ if ($is_negative) {
+ $temp = $this->add(new Math_BigInteger('-1'));
+ $this->value = $temp->value;
+ }
+ break;
+ case 10:
+ case -10:
+ // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
+ // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
+ // [^-0-9].*: find any non-numeric characters and then any characters that follow that
+ $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $this->value = gmp_init($x);
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
+ // results then doing it on '-1' does (modInverse does $x[0])
+ $this->value = $x === '-' ? '0' : (string) $x;
+ break;
+ default:
+ $temp = new Math_BigInteger();
+
+ $multiplier = new Math_BigInteger();
+ $multiplier->value = array(MATH_BIGINTEGER_MAX10);
+
+ if ($x[0] == '-') {
+ $this->is_negative = true;
+ $x = substr($x, 1);
+ }
+
+ $x = str_pad($x, strlen($x) + ((MATH_BIGINTEGER_MAX10_LEN - 1) * strlen($x)) % MATH_BIGINTEGER_MAX10_LEN, 0, STR_PAD_LEFT);
+
+ while (strlen($x)) {
+ $temp = $temp->multiply($multiplier);
+ $temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, MATH_BIGINTEGER_MAX10_LEN)), 256));
+ $x = substr($x, MATH_BIGINTEGER_MAX10_LEN);
+ }
+
+ $this->value = $temp->value;
+ }
+ break;
+ case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
+ case -2:
+ if ($base > 0 && $x[0] == '-') {
+ $this->is_negative = true;
+ $x = substr($x, 1);
+ }
+
+ $x = preg_replace('#^([01]*).*#', '$1', $x);
+ $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
+
+ $str = '0x';
+ while (strlen($x)) {
+ $part = substr($x, 0, 4);
+ $str.= dechex(bindec($part));
+ $x = substr($x, 4);
+ }
+
+ if ($this->is_negative) {
+ $str = '-' . $str;
+ }
+
+ $temp = new Math_BigInteger($str, 8 * $base); // ie. either -16 or +16
+ $this->value = $temp->value;
+ $this->is_negative = $temp->is_negative;
+
+ break;
+ default:
+ // base not supported, so we'll let $this == 0
+ }
+ }
+
+ /**
+ * Converts a BigInteger to a byte string (eg. base-256).
+ *
+ * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
+ * saved as two's compliment.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('65');
+ *
+ * echo $a->toBytes(); // outputs chr(65)
+ * ?>
+ * </code>
+ *
+ * @param Boolean $twos_compliment
+ * @return String
+ * @access public
+ * @internal Converts a base-2**26 number to base-2**8
+ */
+ function toBytes($twos_compliment = false)
+ {
+ if ($twos_compliment) {
+ $comparison = $this->compare(new Math_BigInteger());
+ if ($comparison == 0) {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+
+ $temp = $comparison < 0 ? $this->add(new Math_BigInteger(1)) : $this->copy();
+ $bytes = $temp->toBytes();
+
+ if (empty($bytes)) { // eg. if the number we're trying to convert is -1
+ $bytes = chr(0);
+ }
+
+ if (ord($bytes[0]) & 0x80) {
+ $bytes = chr(0) . $bytes;
+ }
+
+ return $comparison < 0 ? ~$bytes : $bytes;
+ }
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ if (gmp_cmp($this->value, gmp_init(0)) == 0) {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+
+ $temp = gmp_strval(gmp_abs($this->value), 16);
+ $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
+ $temp = pack('H*', $temp);
+
+ return $this->precision > 0 ?
+ substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
+ ltrim($temp, chr(0));
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ if ($this->value === '0') {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+
+ $value = '';
+ $current = $this->value;
+
+ if ($current[0] == '-') {
+ $current = substr($current, 1);
+ }
+
+ while (bccomp($current, '0', 0) > 0) {
+ $temp = bcmod($current, '16777216');
+ $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
+ $current = bcdiv($current, '16777216', 0);
+ }
+
+ return $this->precision > 0 ?
+ substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
+ ltrim($value, chr(0));
+ }
+
+ if (!count($this->value)) {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+ $result = $this->_int2bytes($this->value[count($this->value) - 1]);
+
+ $temp = $this->copy();
+
+ for ($i = count($temp->value) - 2; $i >= 0; --$i) {
+ $temp->_base256_lshift($result, MATH_BIGINTEGER_BASE);
+ $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
+ }
+
+ return $this->precision > 0 ?
+ str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) :
+ $result;
+ }
+
+ /**
+ * Converts a BigInteger to a hex string (eg. base-16)).
+ *
+ * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
+ * saved as two's compliment.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('65');
+ *
+ * echo $a->toHex(); // outputs '41'
+ * ?>
+ * </code>
+ *
+ * @param Boolean $twos_compliment
+ * @return String
+ * @access public
+ * @internal Converts a base-2**26 number to base-2**8
+ */
+ function toHex($twos_compliment = false)
+ {
+ return bin2hex($this->toBytes($twos_compliment));
+ }
+
+ /**
+ * Converts a BigInteger to a bit string (eg. base-2).
+ *
+ * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
+ * saved as two's compliment.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('65');
+ *
+ * echo $a->toBits(); // outputs '1000001'
+ * ?>
+ * </code>
+ *
+ * @param Boolean $twos_compliment
+ * @return String
+ * @access public
+ * @internal Converts a base-2**26 number to base-2**2
+ */
+ function toBits($twos_compliment = false)
+ {
+ $hex = $this->toHex($twos_compliment);
+ $bits = '';
+ for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
+ $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
+ }
+ if ($start) { // hexdec('') == 0
+ $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
+ }
+ $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
+
+ if ($twos_compliment && $this->compare(new Math_BigInteger()) > 0 && $this->precision <= 0) {
+ return '0' . $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Converts a BigInteger to a base-10 number.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('50');
+ *
+ * echo $a->toString(); // outputs 50
+ * ?>
+ * </code>
+ *
+ * @return String
+ * @access public
+ * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
+ */
+ function toString()
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ return gmp_strval($this->value);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ if ($this->value === '0') {
+ return '0';
+ }
+
+ return ltrim($this->value, '0');
+ }
+
+ if (!count($this->value)) {
+ return '0';
+ }
+
+ $temp = $this->copy();
+ $temp->is_negative = false;
+
+ $divisor = new Math_BigInteger();
+ $divisor->value = array(MATH_BIGINTEGER_MAX10);
+ $result = '';
+ while (count($temp->value)) {
+ list($temp, $mod) = $temp->divide($divisor);
+ $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', MATH_BIGINTEGER_MAX10_LEN, '0', STR_PAD_LEFT) . $result;
+ }
+ $result = ltrim($result, '0');
+ if (empty($result)) {
+ $result = '0';
+ }
+
+ if ($this->is_negative) {
+ $result = '-' . $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Copy an object
+ *
+ * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee
+ * that all objects are passed by value, when appropriate. More information can be found here:
+ *
+ * {@link http://php.net/language.oop5.basic#51624}
+ *
+ * @access public
+ * @see __clone()
+ * @return Math_BigInteger
+ */
+ function copy()
+ {
+ $temp = new Math_BigInteger();
+ $temp->value = $this->value;
+ $temp->is_negative = $this->is_negative;
+ $temp->generator = $this->generator;
+ $temp->precision = $this->precision;
+ $temp->bitmask = $this->bitmask;
+ return $temp;
+ }
+
+ /**
+ * __toString() magic method
+ *
+ * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
+ * toString().
+ *
+ * @access public
+ * @internal Implemented per a suggestion by Techie-Michael - thanks!
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * __clone() magic method
+ *
+ * Although you can call Math_BigInteger::__toString() directly in PHP5, you cannot call Math_BigInteger::__clone()
+ * directly in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5
+ * only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and PHP5,
+ * call Math_BigInteger::copy(), instead.
+ *
+ * @access public
+ * @see copy()
+ * @return Math_BigInteger
+ */
+ function __clone()
+ {
+ return $this->copy();
+ }
+
+ /**
+ * __sleep() magic method
+ *
+ * Will be called, automatically, when serialize() is called on a Math_BigInteger object.
+ *
+ * @see __wakeup()
+ * @access public
+ */
+ function __sleep()
+ {
+ $this->hex = $this->toHex(true);
+ $vars = array('hex');
+ if ($this->generator != 'mt_rand') {
+ $vars[] = 'generator';
+ }
+ if ($this->precision > 0) {
+ $vars[] = 'precision';
+ }
+ return $vars;
+
+ }
+
+ /**
+ * __wakeup() magic method
+ *
+ * Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
+ *
+ * @see __sleep()
+ * @access public
+ */
+ function __wakeup()
+ {
+ $temp = new Math_BigInteger($this->hex, -16);
+ $this->value = $temp->value;
+ $this->is_negative = $temp->is_negative;
+ $this->setRandomGenerator($this->generator);
+ if ($this->precision > 0) {
+ // recalculate $this->bitmask
+ $this->setPrecision($this->precision);
+ }
+ }
+
+ /**
+ * Adds two BigIntegers.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('10');
+ * $b = new Math_BigInteger('20');
+ *
+ * $c = $a->add($b);
+ *
+ * echo $c->toString(); // outputs 30
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $y
+ * @return Math_BigInteger
+ * @access public
+ * @internal Performs base-2**52 addition
+ */
+ function add($y)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_add($this->value, $y->value);
+
+ return $this->_normalize($temp);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $temp = new Math_BigInteger();
+ $temp->value = bcadd($this->value, $y->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative);
+
+ $result = new Math_BigInteger();
+ $result->value = $temp[MATH_BIGINTEGER_VALUE];
+ $result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Performs addition.
+ *
+ * @param Array $x_value
+ * @param Boolean $x_negative
+ * @param Array $y_value
+ * @param Boolean $y_negative
+ * @return Array
+ * @access private
+ */
+ function _add($x_value, $x_negative, $y_value, $y_negative)
+ {
+ $x_size = count($x_value);
+ $y_size = count($y_value);
+
+ if ($x_size == 0) {
+ return array(
+ MATH_BIGINTEGER_VALUE => $y_value,
+ MATH_BIGINTEGER_SIGN => $y_negative
+ );
+ } else if ($y_size == 0) {
+ return array(
+ MATH_BIGINTEGER_VALUE => $x_value,
+ MATH_BIGINTEGER_SIGN => $x_negative
+ );
+ }
+
+ // subtract, if appropriate
+ if ( $x_negative != $y_negative ) {
+ if ( $x_value == $y_value ) {
+ return array(
+ MATH_BIGINTEGER_VALUE => array(),
+ MATH_BIGINTEGER_SIGN => false
+ );
+ }
+
+ $temp = $this->_subtract($x_value, false, $y_value, false);
+ $temp[MATH_BIGINTEGER_SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
+ $x_negative : $y_negative;
+
+ return $temp;
+ }
+
+ if ($x_size < $y_size) {
+ $size = $x_size;
+ $value = $y_value;
+ } else {
+ $size = $y_size;
+ $value = $x_value;
+ }
+
+ $value[] = 0; // just in case the carry adds an extra digit
+
+ $carry = 0;
+ for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
+ $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] + $y_value[$j] * MATH_BIGINTEGER_BASE_FULL + $y_value[$i] + $carry;
+ $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
+ $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
+
+ $temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
+
+ $value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
+ $value[$j] = $temp;
+ }
+
+ if ($j == $size) { // ie. if $y_size is odd
+ $sum = $x_value[$i] + $y_value[$i] + $carry;
+ $carry = $sum >= MATH_BIGINTEGER_BASE_FULL;
+ $value[$i] = $carry ? $sum - MATH_BIGINTEGER_BASE_FULL : $sum;
+ ++$i; // ie. let $i = $j since we've just done $value[$i]
+ }
+
+ if ($carry) {
+ for (; $value[$i] == MATH_BIGINTEGER_MAX_DIGIT; ++$i) {
+ $value[$i] = 0;
+ }
+ ++$value[$i];
+ }
+
+ return array(
+ MATH_BIGINTEGER_VALUE => $this->_trim($value),
+ MATH_BIGINTEGER_SIGN => $x_negative
+ );
+ }
+
+ /**
+ * Subtracts two BigIntegers.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('10');
+ * $b = new Math_BigInteger('20');
+ *
+ * $c = $a->subtract($b);
+ *
+ * echo $c->toString(); // outputs -10
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $y
+ * @return Math_BigInteger
+ * @access public
+ * @internal Performs base-2**52 subtraction
+ */
+ function subtract($y)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_sub($this->value, $y->value);
+
+ return $this->_normalize($temp);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $temp = new Math_BigInteger();
+ $temp->value = bcsub($this->value, $y->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
+
+ $result = new Math_BigInteger();
+ $result->value = $temp[MATH_BIGINTEGER_VALUE];
+ $result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Performs subtraction.
+ *
+ * @param Array $x_value
+ * @param Boolean $x_negative
+ * @param Array $y_value
+ * @param Boolean $y_negative
+ * @return Array
+ * @access private
+ */
+ function _subtract($x_value, $x_negative, $y_value, $y_negative)
+ {
+ $x_size = count($x_value);
+ $y_size = count($y_value);
+
+ if ($x_size == 0) {
+ return array(
+ MATH_BIGINTEGER_VALUE => $y_value,
+ MATH_BIGINTEGER_SIGN => !$y_negative
+ );
+ } else if ($y_size == 0) {
+ return array(
+ MATH_BIGINTEGER_VALUE => $x_value,
+ MATH_BIGINTEGER_SIGN => $x_negative
+ );
+ }
+
+ // add, if appropriate (ie. -$x - +$y or +$x - -$y)
+ if ( $x_negative != $y_negative ) {
+ $temp = $this->_add($x_value, false, $y_value, false);
+ $temp[MATH_BIGINTEGER_SIGN] = $x_negative;
+
+ return $temp;
+ }
+
+ $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
+
+ if ( !$diff ) {
+ return array(
+ MATH_BIGINTEGER_VALUE => array(),
+ MATH_BIGINTEGER_SIGN => false
+ );
+ }
+
+ // switch $x and $y around, if appropriate.
+ if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) {
+ $temp = $x_value;
+ $x_value = $y_value;
+ $y_value = $temp;
+
+ $x_negative = !$x_negative;
+
+ $x_size = count($x_value);
+ $y_size = count($y_value);
+ }
+
+ // at this point, $x_value should be at least as big as - if not bigger than - $y_value
+
+ $carry = 0;
+ for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
+ $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] - $y_value[$j] * MATH_BIGINTEGER_BASE_FULL - $y_value[$i] - $carry;
+ $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
+ $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
+
+ $temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
+
+ $x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp);
+ $x_value[$j] = $temp;
+ }
+
+ if ($j == $y_size) { // ie. if $y_size is odd
+ $sum = $x_value[$i] - $y_value[$i] - $carry;
+ $carry = $sum < 0;
+ $x_value[$i] = $carry ? $sum + MATH_BIGINTEGER_BASE_FULL : $sum;
+ ++$i;
+ }
+
+ if ($carry) {
+ for (; !$x_value[$i]; ++$i) {
+ $x_value[$i] = MATH_BIGINTEGER_MAX_DIGIT;
+ }
+ --$x_value[$i];
+ }
+
+ return array(
+ MATH_BIGINTEGER_VALUE => $this->_trim($x_value),
+ MATH_BIGINTEGER_SIGN => $x_negative
+ );
+ }
+
+ /**
+ * Multiplies two BigIntegers
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('10');
+ * $b = new Math_BigInteger('20');
+ *
+ * $c = $a->multiply($b);
+ *
+ * echo $c->toString(); // outputs 200
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $x
+ * @return Math_BigInteger
+ * @access public
+ */
+ function multiply($x)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_mul($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $temp = new Math_BigInteger();
+ $temp->value = bcmul($this->value, $x->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
+
+ $product = new Math_BigInteger();
+ $product->value = $temp[MATH_BIGINTEGER_VALUE];
+ $product->is_negative = $temp[MATH_BIGINTEGER_SIGN];
+
+ return $this->_normalize($product);
+ }
+
+ /**
+ * Performs multiplication.
+ *
+ * @param Array $x_value
+ * @param Boolean $x_negative
+ * @param Array $y_value
+ * @param Boolean $y_negative
+ * @return Array
+ * @access private
+ */
+ function _multiply($x_value, $x_negative, $y_value, $y_negative)
+ {
+ //if ( $x_value == $y_value ) {
+ // return array(
+ // MATH_BIGINTEGER_VALUE => $this->_square($x_value),
+ // MATH_BIGINTEGER_SIGN => $x_sign != $y_value
+ // );
+ //}
+
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+
+ if ( !$x_length || !$y_length ) { // a 0 is being multiplied
+ return array(
+ MATH_BIGINTEGER_VALUE => array(),
+ MATH_BIGINTEGER_SIGN => false
+ );
+ }
+
+ return array(
+ MATH_BIGINTEGER_VALUE => min($x_length, $y_length) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
+ $this->_trim($this->_regularMultiply($x_value, $y_value)) :
+ $this->_trim($this->_karatsuba($x_value, $y_value)),
+ MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
+ );
+ }
+
+ /**
+ * Performs long multiplication on two BigIntegers
+ *
+ * Modeled after 'multiply' in MutableBigInteger.java.
+ *
+ * @param Array $x_value
+ * @param Array $y_value
+ * @return Array
+ * @access private
+ */
+ function _regularMultiply($x_value, $y_value)
+ {
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+
+ if ( !$x_length || !$y_length ) { // a 0 is being multiplied
+ return array();
+ }
+
+ if ( $x_length < $y_length ) {
+ $temp = $x_value;
+ $x_value = $y_value;
+ $y_value = $temp;
+
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+ }
+
+ $product_value = $this->_array_repeat(0, $x_length + $y_length);
+
+ // the following for loop could be removed if the for loop following it
+ // (the one with nested for loops) initially set $i to 0, but
+ // doing so would also make the result in one set of unnecessary adds,
+ // since on the outermost loops first pass, $product->value[$k] is going
+ // to always be 0
+
+ $carry = 0;
+
+ for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
+ $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
+ }
+
+ $product_value[$j] = $carry;
+
+ // the above for loop is what the previous comment was talking about. the
+ // following for loop is the "one with nested for loops"
+ for ($i = 1; $i < $y_length; ++$i) {
+ $carry = 0;
+
+ for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
+ $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
+ }
+
+ $product_value[$k] = $carry;
+ }
+
+ return $product_value;
+ }
+
+ /**
+ * Performs Karatsuba multiplication on two BigIntegers
+ *
+ * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
+ *
+ * @param Array $x_value
+ * @param Array $y_value
+ * @return Array
+ * @access private
+ */
+ function _karatsuba($x_value, $y_value)
+ {
+ $m = min(count($x_value) >> 1, count($y_value) >> 1);
+
+ if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
+ return $this->_regularMultiply($x_value, $y_value);
+ }
+
+ $x1 = array_slice($x_value, $m);
+ $x0 = array_slice($x_value, 0, $m);
+ $y1 = array_slice($y_value, $m);
+ $y0 = array_slice($y_value, 0, $m);
+
+ $z2 = $this->_karatsuba($x1, $y1);
+ $z0 = $this->_karatsuba($x0, $y0);
+
+ $z1 = $this->_add($x1, false, $x0, false);
+ $temp = $this->_add($y1, false, $y0, false);
+ $z1 = $this->_karatsuba($z1[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_VALUE]);
+ $temp = $this->_add($z2, false, $z0, false);
+ $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
+
+ $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
+ $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
+
+ $xy = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
+ $xy = $this->_add($xy[MATH_BIGINTEGER_VALUE], $xy[MATH_BIGINTEGER_SIGN], $z0, false);
+
+ return $xy[MATH_BIGINTEGER_VALUE];
+ }
+
+ /**
+ * Performs squaring
+ *
+ * @param Array $x
+ * @return Array
+ * @access private
+ */
+ function _square($x = false)
+ {
+ return count($x) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
+ $this->_trim($this->_baseSquare($x)) :
+ $this->_trim($this->_karatsubaSquare($x));
+ }
+
+ /**
+ * Performs traditional squaring on two BigIntegers
+ *
+ * Squaring can be done faster than multiplying a number by itself can be. See
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
+ *
+ * @param Array $value
+ * @return Array
+ * @access private
+ */
+ function _baseSquare($value)
+ {
+ if ( empty($value) ) {
+ return array();
+ }
+ $square_value = $this->_array_repeat(0, 2 * count($value));
+
+ for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
+ $i2 = $i << 1;
+
+ $temp = $square_value[$i2] + $value[$i] * $value[$i];
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
+
+ // note how we start from $i+1 instead of 0 as we do in multiplication.
+ for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
+ $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
+ }
+
+ // the following line can yield values larger 2**15. at this point, PHP should switch
+ // over to floats.
+ $square_value[$i + $max_index + 1] = $carry;
+ }
+
+ return $square_value;
+ }
+
+ /**
+ * Performs Karatsuba "squaring" on two BigIntegers
+ *
+ * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
+ *
+ * @param Array $value
+ * @return Array
+ * @access private
+ */
+ function _karatsubaSquare($value)
+ {
+ $m = count($value) >> 1;
+
+ if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
+ return $this->_baseSquare($value);
+ }
+
+ $x1 = array_slice($value, $m);
+ $x0 = array_slice($value, 0, $m);
+
+ $z2 = $this->_karatsubaSquare($x1);
+ $z0 = $this->_karatsubaSquare($x0);
+
+ $z1 = $this->_add($x1, false, $x0, false);
+ $z1 = $this->_karatsubaSquare($z1[MATH_BIGINTEGER_VALUE]);
+ $temp = $this->_add($z2, false, $z0, false);
+ $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
+
+ $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
+ $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
+
+ $xx = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
+ $xx = $this->_add($xx[MATH_BIGINTEGER_VALUE], $xx[MATH_BIGINTEGER_SIGN], $z0, false);
+
+ return $xx[MATH_BIGINTEGER_VALUE];
+ }
+
+ /**
+ * Divides two BigIntegers.
+ *
+ * Returns an array whose first element contains the quotient and whose second element contains the
+ * "common residue". If the remainder would be positive, the "common residue" and the remainder are the
+ * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
+ * and the divisor (basically, the "common residue" is the first positive modulo).
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('10');
+ * $b = new Math_BigInteger('20');
+ *
+ * list($quotient, $remainder) = $a->divide($b);
+ *
+ * echo $quotient->toString(); // outputs 0
+ * echo "\r\n";
+ * echo $remainder->toString(); // outputs 10
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $y
+ * @return Array
+ * @access public
+ * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
+ */
+ function divide($y)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $quotient = new Math_BigInteger();
+ $remainder = new Math_BigInteger();
+
+ list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
+
+ if (gmp_sign($remainder->value) < 0) {
+ $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
+ }
+
+ return array($this->_normalize($quotient), $this->_normalize($remainder));
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $quotient = new Math_BigInteger();
+ $remainder = new Math_BigInteger();
+
+ $quotient->value = bcdiv($this->value, $y->value, 0);
+ $remainder->value = bcmod($this->value, $y->value);
+
+ if ($remainder->value[0] == '-') {
+ $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0);
+ }
+
+ return array($this->_normalize($quotient), $this->_normalize($remainder));
+ }
+
+ if (count($y->value) == 1) {
+ list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
+ $quotient = new Math_BigInteger();
+ $remainder = new Math_BigInteger();
+ $quotient->value = $q;
+ $remainder->value = array($r);
+ $quotient->is_negative = $this->is_negative != $y->is_negative;
+ return array($this->_normalize($quotient), $this->_normalize($remainder));
+ }
+
+ static $zero;
+ if ( !isset($zero) ) {
+ $zero = new Math_BigInteger();
+ }
+
+ $x = $this->copy();
+ $y = $y->copy();
+
+ $x_sign = $x->is_negative;
+ $y_sign = $y->is_negative;
+
+ $x->is_negative = $y->is_negative = false;
+
+ $diff = $x->compare($y);
+
+ if ( !$diff ) {
+ $temp = new Math_BigInteger();
+ $temp->value = array(1);
+ $temp->is_negative = $x_sign != $y_sign;
+ return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));
+ }
+
+ if ( $diff < 0 ) {
+ // if $x is negative, "add" $y.
+ if ( $x_sign ) {
+ $x = $y->subtract($x);
+ }
+ return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));
+ }
+
+ // normalize $x and $y as described in HAC 14.23 / 14.24
+ $msb = $y->value[count($y->value) - 1];
+ for ($shift = 0; !($msb & MATH_BIGINTEGER_MSB); ++$shift) {
+ $msb <<= 1;
+ }
+ $x->_lshift($shift);
+ $y->_lshift($shift);
+ $y_value = &$y->value;
+
+ $x_max = count($x->value) - 1;
+ $y_max = count($y->value) - 1;
+
+ $quotient = new Math_BigInteger();
+ $quotient_value = &$quotient->value;
+ $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
+
+ static $temp, $lhs, $rhs;
+ if (!isset($temp)) {
+ $temp = new Math_BigInteger();
+ $lhs = new Math_BigInteger();
+ $rhs = new Math_BigInteger();
+ }
+ $temp_value = &$temp->value;
+ $rhs_value = &$rhs->value;
+
+ // $temp = $y << ($x_max - $y_max-1) in base 2**26
+ $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
+
+ while ( $x->compare($temp) >= 0 ) {
+ // calculate the "common residue"
+ ++$quotient_value[$x_max - $y_max];
+ $x = $x->subtract($temp);
+ $x_max = count($x->value) - 1;
+ }
+
+ for ($i = $x_max; $i >= $y_max + 1; --$i) {
+ $x_value = &$x->value;
+ $x_window = array(
+ isset($x_value[$i]) ? $x_value[$i] : 0,
+ isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0,
+ isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0
+ );
+ $y_window = array(
+ $y_value[$y_max],
+ ( $y_max > 0 ) ? $y_value[$y_max - 1] : 0
+ );
+
+ $q_index = $i - $y_max - 1;
+ if ($x_window[0] == $y_window[0]) {
+ $quotient_value[$q_index] = MATH_BIGINTEGER_MAX_DIGIT;
+ } else {
+ $quotient_value[$q_index] = (int) (
+ ($x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1])
+ /
+ $y_window[0]
+ );
+ }
+
+ $temp_value = array($y_window[1], $y_window[0]);
+
+ $lhs->value = array($quotient_value[$q_index]);
+ $lhs = $lhs->multiply($temp);
+
+ $rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
+
+ while ( $lhs->compare($rhs) > 0 ) {
+ --$quotient_value[$q_index];
+
+ $lhs->value = array($quotient_value[$q_index]);
+ $lhs = $lhs->multiply($temp);
+ }
+
+ $adjust = $this->_array_repeat(0, $q_index);
+ $temp_value = array($quotient_value[$q_index]);
+ $temp = $temp->multiply($y);
+ $temp_value = &$temp->value;
+ $temp_value = array_merge($adjust, $temp_value);
+
+ $x = $x->subtract($temp);
+
+ if ($x->compare($zero) < 0) {
+ $temp_value = array_merge($adjust, $y_value);
+ $x = $x->add($temp);
+
+ --$quotient_value[$q_index];
+ }
+
+ $x_max = count($x_value) - 1;
+ }
+
+ // unnormalize the remainder
+ $x->_rshift($shift);
+
+ $quotient->is_negative = $x_sign != $y_sign;
+
+ // calculate the "common residue", if appropriate
+ if ( $x_sign ) {
+ $y->_rshift($shift);
+ $x = $y->subtract($x);
+ }
+
+ return array($this->_normalize($quotient), $this->_normalize($x));
+ }
+
+ /**
+ * Divides a BigInteger by a regular integer
+ *
+ * abc / x = a00 / x + b0 / x + c / x
+ *
+ * @param Array $dividend
+ * @param Array $divisor
+ * @return Array
+ * @access private
+ */
+ function _divide_digit($dividend, $divisor)
+ {
+ $carry = 0;
+ $result = array();
+
+ for ($i = count($dividend) - 1; $i >= 0; --$i) {
+ $temp = MATH_BIGINTEGER_BASE_FULL * $carry + $dividend[$i];
+ $result[$i] = (int) ($temp / $divisor);
+ $carry = (int) ($temp - $divisor * $result[$i]);
+ }
+
+ return array($result, $carry);
+ }
+
+ /**
+ * Performs modular exponentiation.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger('10');
+ * $b = new Math_BigInteger('20');
+ * $c = new Math_BigInteger('30');
+ *
+ * $c = $a->modPow($b, $c);
+ *
+ * echo $c->toString(); // outputs 10
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $e
+ * @param Math_BigInteger $n
+ * @return Math_BigInteger
+ * @access public
+ * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
+ * and although the approach involving repeated squaring does vastly better, it, too, is impractical
+ * for our purposes. The reason being that division - by far the most complicated and time-consuming
+ * of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
+ *
+ * Modular reductions resolve this issue. Although an individual modular reduction takes more time
+ * then an individual division, when performed in succession (with the same modulo), they're a lot faster.
+ *
+ * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction,
+ * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the
+ * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
+ * the product of two odd numbers is odd), but what about when RSA isn't used?
+ *
+ * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a
+ * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the
+ * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however,
+ * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
+ * the other, a power of two - and recombine them, later. This is the method that this modPow function uses.
+ * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
+ */
+ function modPow($e, $n)
+ {
+ $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
+
+ if ($e->compare(new Math_BigInteger()) < 0) {
+ $e = $e->abs();
+
+ $temp = $this->modInverse($n);
+ if ($temp === false) {
+ return false;
+ }
+
+ return $this->_normalize($temp->modPow($e, $n));
+ }
+
+ if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP ) {
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_powm($this->value, $e->value, $n->value);
+
+ return $this->_normalize($temp);
+ }
+
+ if ($this->compare(new Math_BigInteger()) < 0 || $this->compare($n) > 0) {
+ list(, $temp) = $this->divide($n);
+ return $temp->modPow($e, $n);
+ }
+
+ if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
+ $components = array(
+ 'modulus' => $n->toBytes(true),
+ 'publicExponent' => $e->toBytes(true)
+ );
+
+ $components = array(
+ 'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']),
+ 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
+ );
+
+ $RSAPublicKey = pack('Ca*a*a*',
+ 48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
+ $components['modulus'], $components['publicExponent']
+ );
+
+ $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
+ $RSAPublicKey = chr(0) . $RSAPublicKey;
+ $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
+
+ $encapsulated = pack('Ca*a*',
+ 48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
+ );
+
+ $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
+ chunk_split(base64_encode($encapsulated)) .
+ '-----END PUBLIC KEY-----';
+
+ $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT);
+
+ if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
+ return new Math_BigInteger($result, 256);
+ }
+ }
+
+ if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
+ $temp = new Math_BigInteger();
+ $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ if ( empty($e->value) ) {
+ $temp = new Math_BigInteger();
+ $temp->value = array(1);
+ return $this->_normalize($temp);
+ }
+
+ if ( $e->value == array(1) ) {
+ list(, $temp) = $this->divide($n);
+ return $this->_normalize($temp);
+ }
+
+ if ( $e->value == array(2) ) {
+ $temp = new Math_BigInteger();
+ $temp->value = $this->_square($this->value);
+ list(, $temp) = $temp->divide($n);
+ return $this->_normalize($temp);
+ }
+
+ return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT));
+
+ // is the modulo odd?
+ if ( $n->value[0] & 1 ) {
+ return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
+ }
+ // if it's not, it's even
+
+ // find the lowest set bit (eg. the max pow of 2 that divides $n)
+ for ($i = 0; $i < count($n->value); ++$i) {
+ if ( $n->value[$i] ) {
+ $temp = decbin($n->value[$i]);
+ $j = strlen($temp) - strrpos($temp, '1') - 1;
+ $j+= 26 * $i;
+ break;
+ }
+ }
+ // at this point, 2^$j * $n/(2^$j) == $n
+
+ $mod1 = $n->copy();
+ $mod1->_rshift($j);
+ $mod2 = new Math_BigInteger();
+ $mod2->value = array(1);
+ $mod2->_lshift($j);
+
+ $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger();
+ $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);
+
+ $y1 = $mod2->modInverse($mod1);
+ $y2 = $mod1->modInverse($mod2);
+
+ $result = $part1->multiply($mod2);
+ $result = $result->multiply($y1);
+
+ $temp = $part2->multiply($mod1);
+ $temp = $temp->multiply($y2);
+
+ $result = $result->add($temp);
+ list(, $result) = $result->divide($n);
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Performs modular exponentiation.
+ *
+ * Alias for Math_BigInteger::modPow()
+ *
+ * @param Math_BigInteger $e
+ * @param Math_BigInteger $n
+ * @return Math_BigInteger
+ * @access public
+ */
+ function powMod($e, $n)
+ {
+ return $this->modPow($e, $n);
+ }
+
+ /**
+ * Sliding Window k-ary Modular Exponentiation
+ *
+ * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims,
+ * however, this function performs a modular reduction after every multiplication and squaring operation.
+ * As such, this function has the same preconditions that the reductions being used do.
+ *
+ * @param Math_BigInteger $e
+ * @param Math_BigInteger $n
+ * @param Integer $mode
+ * @return Math_BigInteger
+ * @access private
+ */
+ function _slidingWindow($e, $n, $mode)
+ {
+ static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function
+ //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
+
+ $e_value = $e->value;
+ $e_length = count($e_value) - 1;
+ $e_bits = decbin($e_value[$e_length]);
+ for ($i = $e_length - 1; $i >= 0; --$i) {
+ $e_bits.= str_pad(decbin($e_value[$i]), MATH_BIGINTEGER_BASE, '0', STR_PAD_LEFT);
+ }
+
+ $e_length = strlen($e_bits);
+
+ // calculate the appropriate window size.
+ // $window_size == 3 if $window_ranges is between 25 and 81, for example.
+ for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i);
+
+ $n_value = $n->value;
+
+ // precompute $this^0 through $this^$window_size
+ $powers = array();
+ $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode);
+ $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode);
+
+ // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
+ // in a 1. ie. it's supposed to be odd.
+ $temp = 1 << ($window_size - 1);
+ for ($i = 1; $i < $temp; ++$i) {
+ $i2 = $i << 1;
+ $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode);
+ }
+
+ $result = array(1);
+ $result = $this->_prepareReduce($result, $n_value, $mode);
+
+ for ($i = 0; $i < $e_length; ) {
+ if ( !$e_bits[$i] ) {
+ $result = $this->_squareReduce($result, $n_value, $mode);
+ ++$i;
+ } else {
+ for ($j = $window_size - 1; $j > 0; --$j) {
+ if ( !empty($e_bits[$i + $j]) ) {
+ break;
+ }
+ }
+
+ for ($k = 0; $k <= $j; ++$k) {// eg. the length of substr($e_bits, $i, $j+1)
+ $result = $this->_squareReduce($result, $n_value, $mode);
+ }
+
+ $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
+
+ $i+=$j + 1;
+ }
+ }
+
+ $temp = new Math_BigInteger();
+ $temp->value = $this->_reduce($result, $n_value, $mode);
+
+ return $temp;
+ }
+
+ /**
+ * Modular reduction
+ *
+ * For most $modes this will return the remainder.
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $n
+ * @param Integer $mode
+ * @return Array
+ */
+ function _reduce($x, $n, $mode)
+ {
+ switch ($mode) {
+ case MATH_BIGINTEGER_MONTGOMERY:
+ return $this->_montgomery($x, $n);
+ case MATH_BIGINTEGER_BARRETT:
+ return $this->_barrett($x, $n);
+ case MATH_BIGINTEGER_POWEROF2:
+ $lhs = new Math_BigInteger();
+ $lhs->value = $x;
+ $rhs = new Math_BigInteger();
+ $rhs->value = $n;
+ return $x->_mod2($n);
+ case MATH_BIGINTEGER_CLASSIC:
+ $lhs = new Math_BigInteger();
+ $lhs->value = $x;
+ $rhs = new Math_BigInteger();
+ $rhs->value = $n;
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ case MATH_BIGINTEGER_NONE:
+ return $x;
+ default:
+ // an invalid $mode was provided
+ }
+ }
+
+ /**
+ * Modular reduction preperation
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $n
+ * @param Integer $mode
+ * @return Array
+ */
+ function _prepareReduce($x, $n, $mode)
+ {
+ if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
+ return $this->_prepMontgomery($x, $n);
+ }
+ return $this->_reduce($x, $n, $mode);
+ }
+
+ /**
+ * Modular multiply
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $y
+ * @param Array $n
+ * @param Integer $mode
+ * @return Array
+ */
+ function _multiplyReduce($x, $y, $n, $mode)
+ {
+ if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
+ return $this->_montgomeryMultiply($x, $y, $n);
+ }
+ $temp = $this->_multiply($x, false, $y, false);
+ return $this->_reduce($temp[MATH_BIGINTEGER_VALUE], $n, $mode);
+ }
+
+ /**
+ * Modular square
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $n
+ * @param Integer $mode
+ * @return Array
+ */
+ function _squareReduce($x, $n, $mode)
+ {
+ if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
+ return $this->_montgomeryMultiply($x, $x, $n);
+ }
+ return $this->_reduce($this->_square($x), $n, $mode);
+ }
+
+ /**
+ * Modulos for Powers of Two
+ *
+ * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
+ * we'll just use this function as a wrapper for doing that.
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Math_BigInteger
+ * @return Math_BigInteger
+ */
+ function _mod2($n)
+ {
+ $temp = new Math_BigInteger();
+ $temp->value = array(1);
+ return $this->bitwise_and($n->subtract($temp));
+ }
+
+ /**
+ * Barrett Modular Reduction
+ *
+ * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly,
+ * so as not to require negative numbers (initially, this script didn't support negative numbers).
+ *
+ * Employs "folding", as described at
+ * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from
+ * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
+ *
+ * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
+ * usable on account of (1) its not using reasonable radix points as discussed in
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
+ * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that
+ * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
+ * comments for details.
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $n
+ * @param Array $m
+ * @return Array
+ */
+ function _barrett($n, $m)
+ {
+ static $cache = array(
+ MATH_BIGINTEGER_VARIABLE => array(),
+ MATH_BIGINTEGER_DATA => array()
+ );
+
+ $m_length = count($m);
+
+ // if ($this->_compare($n, $this->_square($m)) >= 0) {
+ if (count($n) > 2 * $m_length) {
+ $lhs = new Math_BigInteger();
+ $rhs = new Math_BigInteger();
+ $lhs->value = $n;
+ $rhs->value = $m;
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ }
+
+ // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
+ if ($m_length < 5) {
+ return $this->_regularBarrett($n, $m);
+ }
+
+ // n = 2 * m.length
+
+ if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
+ $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
+ $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
+
+ $lhs = new Math_BigInteger();
+ $lhs_value = &$lhs->value;
+ $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1));
+ $lhs_value[] = 1;
+ $rhs = new Math_BigInteger();
+ $rhs->value = $m;
+
+ list($u, $m1) = $lhs->divide($rhs);
+ $u = $u->value;
+ $m1 = $m1->value;
+
+ $cache[MATH_BIGINTEGER_DATA][] = array(
+ 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
+ 'm1'=> $m1 // m.length
+ );
+ } else {
+ extract($cache[MATH_BIGINTEGER_DATA][$key]);
+ }
+
+ $cutoff = $m_length + ($m_length >> 1);
+ $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1)
+ $msd = array_slice($n, $cutoff); // m.length >> 1
+ $lsd = $this->_trim($lsd);
+ $temp = $this->_multiply($msd, false, $m1, false);
+ $n = $this->_add($lsd, false, $temp[MATH_BIGINTEGER_VALUE], false); // m.length + (m.length >> 1) + 1
+
+ if ($m_length & 1) {
+ return $this->_regularBarrett($n[MATH_BIGINTEGER_VALUE], $m);
+ }
+
+ // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
+ $temp = array_slice($n[MATH_BIGINTEGER_VALUE], $m_length - 1);
+ // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
+ // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
+ $temp = $this->_multiply($temp, false, $u, false);
+ // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
+ // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
+ $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], ($m_length >> 1) + 1);
+ // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
+ // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1)
+ $temp = $this->_multiply($temp, false, $m, false);
+
+ // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
+ // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop
+ // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
+
+ $result = $this->_subtract($n[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
+
+ while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false) >= 0) {
+ $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false);
+ }
+
+ return $result[MATH_BIGINTEGER_VALUE];
+ }
+
+ /**
+ * (Regular) Barrett Modular Reduction
+ *
+ * For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this
+ * is that this function does not fold the denominator into a smaller form.
+ *
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $n
+ * @return Array
+ */
+ function _regularBarrett($x, $n)
+ {
+ static $cache = array(
+ MATH_BIGINTEGER_VARIABLE => array(),
+ MATH_BIGINTEGER_DATA => array()
+ );
+
+ $n_length = count($n);
+
+ if (count($x) > 2 * $n_length) {
+ $lhs = new Math_BigInteger();
+ $rhs = new Math_BigInteger();
+ $lhs->value = $x;
+ $rhs->value = $n;
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ }
+
+ if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
+ $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
+ $cache[MATH_BIGINTEGER_VARIABLE][] = $n;
+ $lhs = new Math_BigInteger();
+ $lhs_value = &$lhs->value;
+ $lhs_value = $this->_array_repeat(0, 2 * $n_length);
+ $lhs_value[] = 1;
+ $rhs = new Math_BigInteger();
+ $rhs->value = $n;
+ list($temp, ) = $lhs->divide($rhs); // m.length
+ $cache[MATH_BIGINTEGER_DATA][] = $temp->value;
+ }
+
+ // 2 * m.length - (m.length - 1) = m.length + 1
+ $temp = array_slice($x, $n_length - 1);
+ // (m.length + 1) + m.length = 2 * m.length + 1
+ $temp = $this->_multiply($temp, false, $cache[MATH_BIGINTEGER_DATA][$key], false);
+ // (2 * m.length + 1) - (m.length - 1) = m.length + 2
+ $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], $n_length + 1);
+
+ // m.length + 1
+ $result = array_slice($x, 0, $n_length + 1);
+ // m.length + 1
+ $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1);
+ // $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1)
+
+ if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
+ $corrector_value = $this->_array_repeat(0, $n_length + 1);
+ $corrector_value[] = 1;
+ $result = $this->_add($result, false, $corrector_value, false);
+ $result = $result[MATH_BIGINTEGER_VALUE];
+ }
+
+ // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
+ $result = $this->_subtract($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]);
+ while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false) > 0) {
+ $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false);
+ }
+
+ return $result[MATH_BIGINTEGER_VALUE];
+ }
+
+ /**
+ * Performs long multiplication up to $stop digits
+ *
+ * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
+ *
+ * @see _regularBarrett()
+ * @param Array $x_value
+ * @param Boolean $x_negative
+ * @param Array $y_value
+ * @param Boolean $y_negative
+ * @param Integer $stop
+ * @return Array
+ * @access private
+ */
+ function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
+ {
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+
+ if ( !$x_length || !$y_length ) { // a 0 is being multiplied
+ return array(
+ MATH_BIGINTEGER_VALUE => array(),
+ MATH_BIGINTEGER_SIGN => false
+ );
+ }
+
+ if ( $x_length < $y_length ) {
+ $temp = $x_value;
+ $x_value = $y_value;
+ $y_value = $temp;
+
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+ }
+
+ $product_value = $this->_array_repeat(0, $x_length + $y_length);
+
+ // the following for loop could be removed if the for loop following it
+ // (the one with nested for loops) initially set $i to 0, but
+ // doing so would also make the result in one set of unnecessary adds,
+ // since on the outermost loops first pass, $product->value[$k] is going
+ // to always be 0
+
+ $carry = 0;
+
+ for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
+ $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
+ }
+
+ if ($j < $stop) {
+ $product_value[$j] = $carry;
+ }
+
+ // the above for loop is what the previous comment was talking about. the
+ // following for loop is the "one with nested for loops"
+
+ for ($i = 1; $i < $y_length; ++$i) {
+ $carry = 0;
+
+ for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
+ $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
+ }
+
+ if ($k < $stop) {
+ $product_value[$k] = $carry;
+ }
+ }
+
+ return array(
+ MATH_BIGINTEGER_VALUE => $this->_trim($product_value),
+ MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
+ );
+ }
+
+ /**
+ * Montgomery Modular Reduction
+ *
+ * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n.
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
+ * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
+ * to work correctly.
+ *
+ * @see _prepMontgomery()
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $n
+ * @return Array
+ */
+ function _montgomery($x, $n)
+ {
+ static $cache = array(
+ MATH_BIGINTEGER_VARIABLE => array(),
+ MATH_BIGINTEGER_DATA => array()
+ );
+
+ if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
+ $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
+ $cache[MATH_BIGINTEGER_VARIABLE][] = $x;
+ $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n);
+ }
+
+ $k = count($n);
+
+ $result = array(MATH_BIGINTEGER_VALUE => $x);
+
+ for ($i = 0; $i < $k; ++$i) {
+ $temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key];
+ $temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
+ $temp = $this->_regularMultiply(array($temp), $n);
+ $temp = array_merge($this->_array_repeat(0, $i), $temp);
+ $result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false);
+ }
+
+ $result[MATH_BIGINTEGER_VALUE] = array_slice($result[MATH_BIGINTEGER_VALUE], $k);
+
+ if ($this->_compare($result, false, $n, false) >= 0) {
+ $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], false, $n, false);
+ }
+
+ return $result[MATH_BIGINTEGER_VALUE];
+ }
+
+ /**
+ * Montgomery Multiply
+ *
+ * Interleaves the montgomery reduction and long multiplication algorithms together as described in
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
+ *
+ * @see _prepMontgomery()
+ * @see _montgomery()
+ * @access private
+ * @param Array $x
+ * @param Array $y
+ * @param Array $m
+ * @return Array
+ */
+ function _montgomeryMultiply($x, $y, $m)
+ {
+ $temp = $this->_multiply($x, false, $y, false);
+ return $this->_montgomery($temp[MATH_BIGINTEGER_VALUE], $m);
+
+ static $cache = array(
+ MATH_BIGINTEGER_VARIABLE => array(),
+ MATH_BIGINTEGER_DATA => array()
+ );
+
+ if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
+ $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
+ $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
+ $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m);
+ }
+
+ $n = max(count($x), count($y), count($m));
+ $x = array_pad($x, $n, 0);
+ $y = array_pad($y, $n, 0);
+ $m = array_pad($m, $n, 0);
+ $a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1));
+ for ($i = 0; $i < $n; ++$i) {
+ $temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0];
+ $temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
+ $temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key];
+ $temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
+ $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
+ $a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
+ $a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1);
+ }
+ if ($this->_compare($a[MATH_BIGINTEGER_VALUE], false, $m, false) >= 0) {
+ $a = $this->_subtract($a[MATH_BIGINTEGER_VALUE], false, $m, false);
+ }
+ return $a[MATH_BIGINTEGER_VALUE];
+ }
+
+ /**
+ * Prepare a number for use in Montgomery Modular Reductions
+ *
+ * @see _montgomery()
+ * @see _slidingWindow()
+ * @access private
+ * @param Array $x
+ * @param Array $n
+ * @return Array
+ */
+ function _prepMontgomery($x, $n)
+ {
+ $lhs = new Math_BigInteger();
+ $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x);
+ $rhs = new Math_BigInteger();
+ $rhs->value = $n;
+
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ }
+
+ /**
+ * Modular Inverse of a number mod 2**26 (eg. 67108864)
+ *
+ * Based off of the bnpInvDigit function implemented and justified in the following URL:
+ *
+ * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
+ *
+ * The following URL provides more info:
+ *
+ * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
+ *
+ * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For
+ * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
+ * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
+ * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that
+ * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the
+ * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to
+ * 40 bits, which only 64-bit floating points will support.
+ *
+ * Thanks to Pedro Gimeno Fortea for input!
+ *
+ * @see _montgomery()
+ * @access private
+ * @param Array $x
+ * @return Integer
+ */
+ function _modInverse67108864($x) // 2**26 == 67,108,864
+ {
+ $x = -$x[0];
+ $result = $x & 0x3; // x**-1 mod 2**2
+ $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
+ $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
+ $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
+ $result = fmod($result * (2 - fmod($x * $result, MATH_BIGINTEGER_BASE_FULL)), MATH_BIGINTEGER_BASE_FULL); // x**-1 mod 2**26
+ return $result & MATH_BIGINTEGER_MAX_DIGIT;
+ }
+
+ /**
+ * Calculates modular inverses.
+ *
+ * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger(30);
+ * $b = new Math_BigInteger(17);
+ *
+ * $c = $a->modInverse($b);
+ * echo $c->toString(); // outputs 4
+ *
+ * echo "\r\n";
+ *
+ * $d = $a->multiply($c);
+ * list(, $d) = $d->divide($b);
+ * echo $d; // outputs 1 (as per the definition of modular inverse)
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $n
+ * @return mixed false, if no modular inverse exists, Math_BigInteger, otherwise.
+ * @access public
+ * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
+ */
+ function modInverse($n)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_invert($this->value, $n->value);
+
+ return ( $temp->value === false ) ? false : $this->_normalize($temp);
+ }
+
+ static $zero, $one;
+ if (!isset($zero)) {
+ $zero = new Math_BigInteger();
+ $one = new Math_BigInteger(1);
+ }
+
+ // $x mod -$n == $x mod $n.
+ $n = $n->abs();
+
+ if ($this->compare($zero) < 0) {
+ $temp = $this->abs();
+ $temp = $temp->modInverse($n);
+ return $this->_normalize($n->subtract($temp));
+ }
+
+ extract($this->extendedGCD($n));
+
+ if (!$gcd->equals($one)) {
+ return false;
+ }
+
+ $x = $x->compare($zero) < 0 ? $x->add($n) : $x;
+
+ return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x);
+ }
+
+ /**
+ * Calculates the greatest common divisor and Bezout's identity.
+ *
+ * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
+ * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
+ * combination is returned is dependant upon which mode is in use. See
+ * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger(693);
+ * $b = new Math_BigInteger(609);
+ *
+ * extract($a->extendedGCD($b));
+ *
+ * echo $gcd->toString() . "\r\n"; // outputs 21
+ * echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $n
+ * @return Math_BigInteger
+ * @access public
+ * @internal Calculates the GCD using the binary xGCD algorithim described in
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes,
+ * the more traditional algorithim requires "relatively costly multiple-precision divisions".
+ */
+ function extendedGCD($n)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ extract(gmp_gcdext($this->value, $n->value));
+
+ return array(
+ 'gcd' => $this->_normalize(new Math_BigInteger($g)),
+ 'x' => $this->_normalize(new Math_BigInteger($s)),
+ 'y' => $this->_normalize(new Math_BigInteger($t))
+ );
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
+ // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is,
+ // the basic extended euclidean algorithim is what we're using.
+
+ $u = $this->value;
+ $v = $n->value;
+
+ $a = '1';
+ $b = '0';
+ $c = '0';
+ $d = '1';
+
+ while (bccomp($v, '0', 0) != 0) {
+ $q = bcdiv($u, $v, 0);
+
+ $temp = $u;
+ $u = $v;
+ $v = bcsub($temp, bcmul($v, $q, 0), 0);
+
+ $temp = $a;
+ $a = $c;
+ $c = bcsub($temp, bcmul($a, $q, 0), 0);
+
+ $temp = $b;
+ $b = $d;
+ $d = bcsub($temp, bcmul($b, $q, 0), 0);
+ }
+
+ return array(
+ 'gcd' => $this->_normalize(new Math_BigInteger($u)),
+ 'x' => $this->_normalize(new Math_BigInteger($a)),
+ 'y' => $this->_normalize(new Math_BigInteger($b))
+ );
+ }
+
+ $y = $n->copy();
+ $x = $this->copy();
+ $g = new Math_BigInteger();
+ $g->value = array(1);
+
+ while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) {
+ $x->_rshift(1);
+ $y->_rshift(1);
+ $g->_lshift(1);
+ }
+
+ $u = $x->copy();
+ $v = $y->copy();
+
+ $a = new Math_BigInteger();
+ $b = new Math_BigInteger();
+ $c = new Math_BigInteger();
+ $d = new Math_BigInteger();
+
+ $a->value = $d->value = $g->value = array(1);
+ $b->value = $c->value = array();
+
+ while ( !empty($u->value) ) {
+ while ( !($u->value[0] & 1) ) {
+ $u->_rshift(1);
+ if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) {
+ $a = $a->add($y);
+ $b = $b->subtract($x);
+ }
+ $a->_rshift(1);
+ $b->_rshift(1);
+ }
+
+ while ( !($v->value[0] & 1) ) {
+ $v->_rshift(1);
+ if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) {
+ $c = $c->add($y);
+ $d = $d->subtract($x);
+ }
+ $c->_rshift(1);
+ $d->_rshift(1);
+ }
+
+ if ($u->compare($v) >= 0) {
+ $u = $u->subtract($v);
+ $a = $a->subtract($c);
+ $b = $b->subtract($d);
+ } else {
+ $v = $v->subtract($u);
+ $c = $c->subtract($a);
+ $d = $d->subtract($b);
+ }
+ }
+
+ return array(
+ 'gcd' => $this->_normalize($g->multiply($v)),
+ 'x' => $this->_normalize($c),
+ 'y' => $this->_normalize($d)
+ );
+ }
+
+ /**
+ * Calculates the greatest common divisor
+ *
+ * Say you have 693 and 609. The GCD is 21.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * include('Math/BigInteger.php');
+ *
+ * $a = new Math_BigInteger(693);
+ * $b = new Math_BigInteger(609);
+ *
+ * $gcd = a->extendedGCD($b);
+ *
+ * echo $gcd->toString() . "\r\n"; // outputs 21
+ * ?>
+ * </code>
+ *
+ * @param Math_BigInteger $n
+ * @return Math_BigInteger
+ * @access public
+ */
+ function gcd($n)
+ {
+ extract($this->extendedGCD($n));
+ return $gcd;
+ }
+
+ /**
+ * Absolute value.
+ *
+ * @return Math_BigInteger
+ * @access public
+ */
+ function abs()
+ {
+ $temp = new Math_BigInteger();
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp->value = gmp_abs($this->value);
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value;
+ break;
+ default:
+ $temp->value = $this->value;
+ }
+
+ return $temp;
+ }
+
+ /**
+ * Compares two numbers.
+ *
+ * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is
+ * demonstrated thusly:
+ *
+ * $x > $y: $x->compare($y) > 0
+ * $x < $y: $x->compare($y) < 0
+ * $x == $y: $x->compare($y) == 0
+ *
+ * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
+ *
+ * @param Math_BigInteger $y
+ * @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
+ * @access public
+ * @see equals()
+ * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
+ */
+ function compare($y)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ return gmp_cmp($this->value, $y->value);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ return bccomp($this->value, $y->value, 0);
+ }
+
+ return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative);
+ }
+
+ /**
+ * Compares two numbers.
+ *
+ * @param Array $x_value
+ * @param Boolean $x_negative
+ * @param Array $y_value
+ * @param Boolean $y_negative
+ * @return Integer
+ * @see compare()
+ * @access private
+ */
+ function _compare($x_value, $x_negative, $y_value, $y_negative)
+ {
+ if ( $x_negative != $y_negative ) {
+ return ( !$x_negative && $y_negative ) ? 1 : -1;
+ }
+
+ $result = $x_negative ? -1 : 1;
+
+ if ( count($x_value) != count($y_value) ) {
+ return ( count($x_value) > count($y_value) ) ? $result : -$result;
+ }
+ $size = max(count($x_value), count($y_value));
+
+ $x_value = array_pad($x_value, $size, 0);
+ $y_value = array_pad($y_value, $size, 0);
+
+ for ($i = count($x_value) - 1; $i >= 0; --$i) {
+ if ($x_value[$i] != $y_value[$i]) {
+ return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Tests the equality of two numbers.
+ *
+ * If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare()
+ *
+ * @param Math_BigInteger $x
+ * @return Boolean
+ * @access public
+ * @see compare()
+ */
+ function equals($x)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ return gmp_cmp($this->value, $x->value) == 0;
+ default:
+ return $this->value === $x->value && $this->is_negative == $x->is_negative;
+ }
+ }
+
+ /**
+ * Set Precision
+ *
+ * Some bitwise operations give different results depending on the precision being used. Examples include left
+ * shift, not, and rotates.
+ *
+ * @param Integer $bits
+ * @access public
+ */
+ function setPrecision($bits)
+ {
+ $this->precision = $bits;
+ if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) {
+ $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
+ } else {
+ $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0));
+ }
+
+ $temp = $this->_normalize($this);
+ $this->value = $temp->value;
+ }
+
+ /**
+ * Logical And
+ *
+ * @param Math_BigInteger $x
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return Math_BigInteger
+ */
+ function bitwise_and($x)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_and($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $left = $this->toBytes();
+ $right = $x->toBytes();
+
+ $length = max(strlen($left), strlen($right));
+
+ $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new Math_BigInteger($left & $right, 256));
+ }
+
+ $result = $this->copy();
+
+ $length = min(count($x->value), count($this->value));
+
+ $result->value = array_slice($result->value, 0, $length);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $result->value[$i]&= $x->value[$i];
+ }
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Or
+ *
+ * @param Math_BigInteger $x
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return Math_BigInteger
+ */
+ function bitwise_or($x)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_or($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $left = $this->toBytes();
+ $right = $x->toBytes();
+
+ $length = max(strlen($left), strlen($right));
+
+ $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new Math_BigInteger($left | $right, 256));
+ }
+
+ $length = max(count($this->value), count($x->value));
+ $result = $this->copy();
+ $result->value = array_pad($result->value, $length, 0);
+ $x->value = array_pad($x->value, $length, 0);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $result->value[$i]|= $x->value[$i];
+ }
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Exclusive-Or
+ *
+ * @param Math_BigInteger $x
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return Math_BigInteger
+ */
+ function bitwise_xor($x)
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ $temp = new Math_BigInteger();
+ $temp->value = gmp_xor($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $left = $this->toBytes();
+ $right = $x->toBytes();
+
+ $length = max(strlen($left), strlen($right));
+
+ $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new Math_BigInteger($left ^ $right, 256));
+ }
+
+ $length = max(count($this->value), count($x->value));
+ $result = $this->copy();
+ $result->value = array_pad($result->value, $length, 0);
+ $x->value = array_pad($x->value, $length, 0);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $result->value[$i]^= $x->value[$i];
+ }
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Not
+ *
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return Math_BigInteger
+ */
+ function bitwise_not()
+ {
+ // calculuate "not" without regard to $this->precision
+ // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
+ $temp = $this->toBytes();
+ $pre_msb = decbin(ord($temp[0]));
+ $temp = ~$temp;
+ $msb = decbin(ord($temp[0]));
+ if (strlen($msb) == 8) {
+ $msb = substr($msb, strpos($msb, '0'));
+ }
+ $temp[0] = chr(bindec($msb));
+
+ // see if we need to add extra leading 1's
+ $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
+ $new_bits = $this->precision - $current_bits;
+ if ($new_bits <= 0) {
+ return $this->_normalize(new Math_BigInteger($temp, 256));
+ }
+
+ // generate as many leading 1's as we need to.
+ $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);
+ $this->_base256_lshift($leading_ones, $current_bits);
+
+ $temp = str_pad($temp, ceil($this->bits / 8), chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256));
+ }
+
+ /**
+ * Logical Right Shift
+ *
+ * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
+ *
+ * @param Integer $shift
+ * @return Math_BigInteger
+ * @access public
+ * @internal The only version that yields any speed increases is the internal version.
+ */
+ function bitwise_rightShift($shift)
+ {
+ $temp = new Math_BigInteger();
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ static $two;
+
+ if (!isset($two)) {
+ $two = gmp_init('2');
+ }
+
+ $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
+
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0);
+
+ break;
+ default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten
+ // and I don't want to do that...
+ $temp->value = $this->value;
+ $temp->_rshift($shift);
+ }
+
+ return $this->_normalize($temp);
+ }
+
+ /**
+ * Logical Left Shift
+ *
+ * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
+ *
+ * @param Integer $shift
+ * @return Math_BigInteger
+ * @access public
+ * @internal The only version that yields any speed increases is the internal version.
+ */
+ function bitwise_leftShift($shift)
+ {
+ $temp = new Math_BigInteger();
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ static $two;
+
+ if (!isset($two)) {
+ $two = gmp_init('2');
+ }
+
+ $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
+
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0);
+
+ break;
+ default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
+ // and I don't want to do that...
+ $temp->value = $this->value;
+ $temp->_lshift($shift);
+ }
+
+ return $this->_normalize($temp);
+ }
+
+ /**
+ * Logical Left Rotate
+ *
+ * Instead of the top x bits being dropped they're appended to the shifted bit string.
+ *
+ * @param Integer $shift
+ * @return Math_BigInteger
+ * @access public
+ */
+ function bitwise_leftRotate($shift)
+ {
+ $bits = $this->toBytes();
+
+ if ($this->precision > 0) {
+ $precision = $this->precision;
+ if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
+ $mask = $this->bitmask->subtract(new Math_BigInteger(1));
+ $mask = $mask->toBytes();
+ } else {
+ $mask = $this->bitmask->toBytes();
+ }
+ } else {
+ $temp = ord($bits[0]);
+ for ($i = 0; $temp >> $i; ++$i);
+ $precision = 8 * strlen($bits) - 8 + $i;
+ $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);
+ }
+
+ if ($shift < 0) {
+ $shift+= $precision;
+ }
+ $shift%= $precision;
+
+ if (!$shift) {
+ return $this->copy();
+ }
+
+ $left = $this->bitwise_leftShift($shift);
+ $left = $left->bitwise_and(new Math_BigInteger($mask, 256));
+ $right = $this->bitwise_rightShift($precision - $shift);
+ $result = MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Right Rotate
+ *
+ * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
+ *
+ * @param Integer $shift
+ * @return Math_BigInteger
+ * @access public
+ */
+ function bitwise_rightRotate($shift)
+ {
+ return $this->bitwise_leftRotate(-$shift);
+ }
+
+ /**
+ * Set random number generator function
+ *
+ * This function is deprecated.
+ *
+ * @param String $generator
+ * @access public
+ */
+ function setRandomGenerator($generator)
+ {
+ }
+
+ /**
+ * Generate a random number
+ *
+ * @param optional Integer $min
+ * @param optional Integer $max
+ * @return Math_BigInteger
+ * @access public
+ */
+ function random($min = false, $max = false)
+ {
+ if ($min === false) {
+ $min = new Math_BigInteger(0);
+ }
+
+ if ($max === false) {
+ $max = new Math_BigInteger(0x7FFFFFFF);
+ }
+
+ $compare = $max->compare($min);
+
+ if (!$compare) {
+ return $this->_normalize($min);
+ } else if ($compare < 0) {
+ // if $min is bigger then $max, swap $min and $max
+ $temp = $max;
+ $max = $min;
+ $min = $temp;
+ }
+
+ $max = $max->subtract($min);
+ $max = ltrim($max->toBytes(), chr(0));
+ $size = strlen($max) - 1;
+
+ $crypt_random = function_exists('crypt_random_string') || (!class_exists('Crypt_Random') && function_exists('crypt_random_string'));
+ if ($crypt_random) {
+ $random = crypt_random_string($size);
+ } else {
+ $random = '';
+
+ if ($size & 1) {
+ $random.= chr(mt_rand(0, 255));
+ }
+
+ $blocks = $size >> 1;
+ for ($i = 0; $i < $blocks; ++$i) {
+ // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
+ $random.= pack('n', mt_rand(0, 0xFFFF));
+ }
+ }
+
+ $fragment = new Math_BigInteger($random, 256);
+ $leading = $fragment->compare(new Math_BigInteger(substr($max, 1), 256)) > 0 ?
+ ord($max[0]) - 1 : ord($max[0]);
+
+ if (!$crypt_random) {
+ $msb = chr(mt_rand(0, $leading));
+ } else {
+ $cutoff = floor(0xFF / $leading) * $leading;
+ while (true) {
+ $msb = ord(crypt_random_string(1));
+ if ($msb <= $cutoff) {
+ $msb%= $leading;
+ break;
+ }
+ }
+ $msb = chr($msb);
+ }
+
+ $random = new Math_BigInteger($msb . $random, 256);
+
+ return $this->_normalize($random->add($min));
+ }
+
+ /**
+ * Generate a random prime number.
+ *
+ * If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed,
+ * give up and return false.
+ *
+ * @param optional Integer $min
+ * @param optional Integer $max
+ * @param optional Integer $timeout
+ * @return Math_BigInteger
+ * @access public
+ * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
+ */
+ function randomPrime($min = false, $max = false, $timeout = false)
+ {
+ if ($min === false) {
+ $min = new Math_BigInteger(0);
+ }
+
+ if ($max === false) {
+ $max = new Math_BigInteger(0x7FFFFFFF);
+ }
+
+ $compare = $max->compare($min);
+
+ if (!$compare) {
+ return $min->isPrime() ? $min : false;
+ } else if ($compare < 0) {
+ // if $min is bigger then $max, swap $min and $max
+ $temp = $max;
+ $max = $min;
+ $min = $temp;
+ }
+
+ static $one, $two;
+ if (!isset($one)) {
+ $one = new Math_BigInteger(1);
+ $two = new Math_BigInteger(2);
+ }
+
+ $start = time();
+
+ $x = $this->random($min, $max);
+
+ // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
+ if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
+ $p = new Math_BigInteger();
+ $p->value = gmp_nextprime($x->value);
+
+ if ($p->compare($max) <= 0) {
+ return $p;
+ }
+
+ if (!$min->equals($x)) {
+ $x = $x->subtract($one);
+ }
+
+ return $x->randomPrime($min, $x);
+ }
+
+ if ($x->equals($two)) {
+ return $x;
+ }
+
+ $x->_make_odd();
+ if ($x->compare($max) > 0) {
+ // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
+ if ($min->equals($max)) {
+ return false;
+ }
+ $x = $min->copy();
+ $x->_make_odd();
+ }
+
+ $initial_x = $x->copy();
+
+ while (true) {
+ if ($timeout !== false && time() - $start > $timeout) {
+ return false;
+ }
+
+ if ($x->isPrime()) {
+ return $x;
+ }
+
+ $x = $x->add($two);
+
+ if ($x->compare($max) > 0) {
+ $x = $min->copy();
+ if ($x->equals($two)) {
+ return $x;
+ }
+ $x->_make_odd();
+ }
+
+ if ($x->equals($initial_x)) {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Make the current number odd
+ *
+ * If the current number is odd it'll be unchanged. If it's even, one will be added to it.
+ *
+ * @see randomPrime()
+ * @access private
+ */
+ function _make_odd()
+ {
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ gmp_setbit($this->value, 0);
+ break;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ if ($this->value[strlen($this->value) - 1] % 2 == 0) {
+ $this->value = bcadd($this->value, '1');
+ }
+ break;
+ default:
+ $this->value[0] |= 1;
+ }
+ }
+
+ /**
+ * Checks a numer to see if it's prime
+ *
+ * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the
+ * $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed accross multiple pageloads
+ * on a website instead of just one.
+ *
+ * @param optional Integer $t
+ * @return Boolean
+ * @access public
+ * @internal Uses the
+ * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}.
+ */
+ function isPrime($t = false)
+ {
+ $length = strlen($this->toBytes());
+
+ if (!$t) {
+ // see HAC 4.49 "Note (controlling the error probability)"
+ if ($length >= 163) { $t = 2; } // floor(1300 / 8)
+ else if ($length >= 106) { $t = 3; } // floor( 850 / 8)
+ else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8)
+ else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8)
+ else if ($length >= 56 ) { $t = 6; } // floor( 450 / 8)
+ else if ($length >= 50 ) { $t = 7; } // floor( 400 / 8)
+ else if ($length >= 43 ) { $t = 8; } // floor( 350 / 8)
+ else if ($length >= 37 ) { $t = 9; } // floor( 300 / 8)
+ else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8)
+ else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8)
+ else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8)
+ else { $t = 27; }
+ }
+
+ // ie. gmp_testbit($this, 0)
+ // ie. isEven() or !isOdd()
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ return gmp_prob_prime($this->value, $t) != 0;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ if ($this->value === '2') {
+ return true;
+ }
+ if ($this->value[strlen($this->value) - 1] % 2 == 0) {
+ return false;
+ }
+ break;
+ default:
+ if ($this->value == array(2)) {
+ return true;
+ }
+ if (~$this->value[0] & 1) {
+ return false;
+ }
+ }
+
+ static $primes, $zero, $one, $two;
+
+ if (!isset($primes)) {
+ $primes = array(
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997
+ );
+
+ if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) {
+ for ($i = 0; $i < count($primes); ++$i) {
+ $primes[$i] = new Math_BigInteger($primes[$i]);
+ }
+ }
+
+ $zero = new Math_BigInteger();
+ $one = new Math_BigInteger(1);
+ $two = new Math_BigInteger(2);
+ }
+
+ if ($this->equals($one)) {
+ return false;
+ }
+
+ // see HAC 4.4.1 "Random search for probable primes"
+ if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) {
+ foreach ($primes as $prime) {
+ list(, $r) = $this->divide($prime);
+ if ($r->equals($zero)) {
+ return $this->equals($prime);
+ }
+ }
+ } else {
+ $value = $this->value;
+ foreach ($primes as $prime) {
+ list(, $r) = $this->_divide_digit($value, $prime);
+ if (!$r) {
+ return count($value) == 1 && $value[0] == $prime;
+ }
+ }
+ }
+
+ $n = $this->copy();
+ $n_1 = $n->subtract($one);
+ $n_2 = $n->subtract($two);
+
+ $r = $n_1->copy();
+ $r_value = $r->value;
+ // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
+ if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
+ $s = 0;
+ // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
+ while ($r->value[strlen($r->value) - 1] % 2 == 0) {
+ $r->value = bcdiv($r->value, '2', 0);
+ ++$s;
+ }
+ } else {
+ for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
+ $temp = ~$r_value[$i] & 0xFFFFFF;
+ for ($j = 1; ($temp >> $j) & 1; ++$j);
+ if ($j != 25) {
+ break;
+ }
+ }
+ $s = 26 * $i + $j - 1;
+ $r->_rshift($s);
+ }
+
+ for ($i = 0; $i < $t; ++$i) {
+ $a = $this->random($two, $n_2);
+ $y = $a->modPow($r, $n);
+
+ if (!$y->equals($one) && !$y->equals($n_1)) {
+ for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) {
+ $y = $y->modPow($two, $n);
+ if ($y->equals($one)) {
+ return false;
+ }
+ }
+
+ if (!$y->equals($n_1)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Logical Left Shift
+ *
+ * Shifts BigInteger's by $shift bits.
+ *
+ * @param Integer $shift
+ * @access private
+ */
+ function _lshift($shift)
+ {
+ if ( $shift == 0 ) {
+ return;
+ }
+
+ $num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
+ $shift %= MATH_BIGINTEGER_BASE;
+ $shift = 1 << $shift;
+
+ $carry = 0;
+
+ for ($i = 0; $i < count($this->value); ++$i) {
+ $temp = $this->value[$i] * $shift + $carry;
+ $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
+ $this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
+ }
+
+ if ( $carry ) {
+ $this->value[] = $carry;
+ }
+
+ while ($num_digits--) {
+ array_unshift($this->value, 0);
+ }
+ }
+
+ /**
+ * Logical Right Shift
+ *
+ * Shifts BigInteger's by $shift bits.
+ *
+ * @param Integer $shift
+ * @access private
+ */
+ function _rshift($shift)
+ {
+ if ($shift == 0) {
+ return;
+ }
+
+ $num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
+ $shift %= MATH_BIGINTEGER_BASE;
+ $carry_shift = MATH_BIGINTEGER_BASE - $shift;
+ $carry_mask = (1 << $shift) - 1;
+
+ if ( $num_digits ) {
+ $this->value = array_slice($this->value, $num_digits);
+ }
+
+ $carry = 0;
+
+ for ($i = count($this->value) - 1; $i >= 0; --$i) {
+ $temp = $this->value[$i] >> $shift | $carry;
+ $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
+ $this->value[$i] = $temp;
+ }
+
+ $this->value = $this->_trim($this->value);
+ }
+
+ /**
+ * Normalize
+ *
+ * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
+ *
+ * @param Math_BigInteger
+ * @return Math_BigInteger
+ * @see _trim()
+ * @access private
+ */
+ function _normalize($result)
+ {
+ $result->precision = $this->precision;
+ $result->bitmask = $this->bitmask;
+
+ switch ( MATH_BIGINTEGER_MODE ) {
+ case MATH_BIGINTEGER_MODE_GMP:
+ if (!empty($result->bitmask->value)) {
+ $result->value = gmp_and($result->value, $result->bitmask->value);
+ }
+
+ return $result;
+ case MATH_BIGINTEGER_MODE_BCMATH:
+ if (!empty($result->bitmask->value)) {
+ $result->value = bcmod($result->value, $result->bitmask->value);
+ }
+
+ return $result;
+ }
+
+ $value = &$result->value;
+
+ if ( !count($value) ) {
+ return $result;
+ }
+
+ $value = $this->_trim($value);
+
+ if (!empty($result->bitmask->value)) {
+ $length = min(count($value), count($this->bitmask->value));
+ $value = array_slice($value, 0, $length);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $value[$i] = $value[$i] & $this->bitmask->value[$i];
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Trim
+ *
+ * Removes leading zeros
+ *
+ * @param Array $value
+ * @return Math_BigInteger
+ * @access private
+ */
+ function _trim($value)
+ {
+ for ($i = count($value) - 1; $i >= 0; --$i) {
+ if ( $value[$i] ) {
+ break;
+ }
+ unset($value[$i]);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Array Repeat
+ *
+ * @param $input Array
+ * @param $multiplier mixed
+ * @return Array
+ * @access private
+ */
+ function _array_repeat($input, $multiplier)
+ {
+ return ($multiplier) ? array_fill(0, $multiplier, $input) : array();
+ }
+
+ /**
+ * Logical Left Shift
+ *
+ * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
+ *
+ * @param $x String
+ * @param $shift Integer
+ * @return String
+ * @access private
+ */
+ function _base256_lshift(&$x, $shift)
+ {
+ if ($shift == 0) {
+ return;
+ }
+
+ $num_bytes = $shift >> 3; // eg. floor($shift/8)
+ $shift &= 7; // eg. $shift % 8
+
+ $carry = 0;
+ for ($i = strlen($x) - 1; $i >= 0; --$i) {
+ $temp = ord($x[$i]) << $shift | $carry;
+ $x[$i] = chr($temp);
+ $carry = $temp >> 8;
+ }
+ $carry = ($carry != 0) ? chr($carry) : '';
+ $x = $carry . $x . str_repeat(chr(0), $num_bytes);
+ }
+
+ /**
+ * Logical Right Shift
+ *
+ * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
+ *
+ * @param $x String
+ * @param $shift Integer
+ * @return String
+ * @access private
+ */
+ function _base256_rshift(&$x, $shift)
+ {
+ if ($shift == 0) {
+ $x = ltrim($x, chr(0));
+ return '';
+ }
+
+ $num_bytes = $shift >> 3; // eg. floor($shift/8)
+ $shift &= 7; // eg. $shift % 8
+
+ $remainder = '';
+ if ($num_bytes) {
+ $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes;
+ $remainder = substr($x, $start);
+ $x = substr($x, 0, -$num_bytes);
+ }
+
+ $carry = 0;
+ $carry_shift = 8 - $shift;
+ for ($i = 0; $i < strlen($x); ++$i) {
+ $temp = (ord($x[$i]) >> $shift) | $carry;
+ $carry = (ord($x[$i]) << $carry_shift) & 0xFF;
+ $x[$i] = chr($temp);
+ }
+ $x = ltrim($x, chr(0));
+
+ $remainder = chr($carry >> $carry_shift) . $remainder;
+
+ return ltrim($remainder, chr(0));
+ }
+
+ // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long
+ // at 32-bits, while java's longs are 64-bits.
+
+ /**
+ * Converts 32-bit integers to bytes.
+ *
+ * @param Integer $x
+ * @return String
+ * @access private
+ */
+ function _int2bytes($x)
+ {
+ return ltrim(pack('N', $x), chr(0));
+ }
+
+ /**
+ * Converts bytes to 32-bit integers
+ *
+ * @param String $x
+ * @return Integer
+ * @access private
+ */
+ function _bytes2int($x)
+ {
+ $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
+ return $temp['int'];
+ }
+
+ /**
+ * DER-encode an integer
+ *
+ * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
+ *
+ * @see modPow()
+ * @access private
+ * @param Integer $length
+ * @return String
+ */
+ function _encodeASN1Length($length)
+ {
+ if ($length <= 0x7F) {
+ return chr($length);
+ }
+
+ $temp = ltrim(pack('N', $length), chr(0));
+ return pack('Ca*', 0x80 | strlen($temp), $temp);
+ }
+}
diff --git a/inc/phpseclib/update.sh b/inc/phpseclib/update.sh
new file mode 100755
index 000000000..ff3747a14
--- /dev/null
+++ b/inc/phpseclib/update.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+wget -nv https://raw.github.com/phpseclib/phpseclib/master/LICENSE -O LICENSE
+wget -nv https://raw.github.com/phpseclib/phpseclib/master/phpseclib/Math/BigInteger.php -O Math_BigInteger.php
+wget -nv https://raw.github.com/phpseclib/phpseclib/master/phpseclib/Crypt/AES.php -O Crypt_AES.php
+wget -nv https://raw.github.com/phpseclib/phpseclib/master/phpseclib/Crypt/Rijndael.php -O Crypt_Rijndael.php
+wget -nv https://raw.github.com/phpseclib/phpseclib/master/phpseclib/Crypt/Base.php -O Crypt_Base.php
+wget -nv https://raw.github.com/phpseclib/phpseclib/master/phpseclib/Crypt/Hash.php -O Crypt_Hash.php
diff --git a/inc/plugin.php b/inc/plugin.php
index 4d3d45f62..422b82534 100644
--- a/inc/plugin.php
+++ b/inc/plugin.php
@@ -199,11 +199,7 @@ class DokuWiki_Plugin {
* @return object helper plugin object
*/
function loadHelper($name, $msg = true){
- if (!plugin_isdisabled($name)){
- $obj = plugin_load('helper',$name);
- }else{
- $obj = null;
- }
+ $obj = plugin_load('helper',$name);
if (is_null($obj) && $msg) msg("Helper plugin $name is not available or invalid.",-1);
return $obj;
}
diff --git a/inc/search.php b/inc/search.php
index 6927fff5f..884aa7b23 100644
--- a/inc/search.php
+++ b/inc/search.php
@@ -273,45 +273,6 @@ function search_allpages(&$data,$base,$file,$type,$lvl,$opts){
return true;
}
-/**
- * Reference search
- * This fuction searches for existing references to a given media file
- * and returns an array with the found pages. It doesn't pay any
- * attention to ACL permissions to find every reference. The caller
- * must check if the user has the appropriate rights to see the found
- * page and eventually have to prevent the result from displaying.
- *
- * @param array $data Reference to the result data structure
- * @param string $base Base usually $conf['datadir']
- * @param string $file current file or directory relative to $base
- * @param char $type Type either 'd' for directory or 'f' for file
- * @param int $lvl Current recursion depht
- * @param mixed $opts option array as given to search()
- *
- * $opts['query'] is the demanded media file name
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
-function search_reference(&$data,$base,$file,$type,$lvl,$opts){
- global $conf;
-
- //we do nothing with directories
- if($type == 'd') return true;
-
- //only search txt files
- if(substr($file,-4) != '.txt') return true;
-
- //we finish after 'cnt' references found. The return value
- //'false' will skip subdirectories to speed search up.
- $cnt = $conf['refshow'] > 0 ? $conf['refshow'] : 1;
- if(count($data) >= $cnt) return false;
-
- $reg = '\{\{ *\:?'.$opts['query'].' *(\|.*)?\}\}';
- search_regex($data,$base,$file,$reg,array($opts['query']));
- return true;
-}
-
/* ------------- helper functions below -------------- */
/**
diff --git a/inc/template.php b/inc/template.php
index a87650b84..ca1c8d9d5 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -291,12 +291,10 @@ function tpl_metaheaders($alt = true) {
$head = array();
// prepare seed for js and css
- $tseed = 0;
+ $tseed = $updateVersion;
$depends = getConfigFiles('main');
- foreach($depends as $f) {
- $time = @filemtime($f);
- if($time > $tseed) $tseed = $time;
- }
+ foreach($depends as $f) $tseed .= @filemtime($f);
+ $tseed = md5($tseed);
// the usual stuff
$head['meta'][] = array('name'=> 'generator', 'content'=> 'DokuWiki');
@@ -470,7 +468,7 @@ function tpl_link($url, $name, $more = '', $return = false) {
* @author Andreas Gohr <andi@splitbrain.org>
*/
function tpl_pagelink($id, $name = null) {
- print html_wikilink($id, $name);
+ print '<bdi>'.html_wikilink($id, $name).'</bdi>';
return true;
}
@@ -543,6 +541,7 @@ function tpl_actionlink($type, $pre = '', $suf = '', $inner = '', $return = fals
* @var string $accesskey
* @var string $id
* @var string $method
+ * @var bool $nofollow
* @var array $params
*/
extract($data);
@@ -557,10 +556,11 @@ function tpl_actionlink($type, $pre = '', $suf = '', $inner = '', $return = fals
$akey = 'accesskey="'.$accesskey.'" ';
$addTitle = ' ['.strtoupper($accesskey).']';
}
+ $rel = $nofollow ? 'rel="nofollow" ' : '';
$out = tpl_link(
$linktarget, $pre.(($inner) ? $inner : $caption).$suf,
'class="action '.$type.'" '.
- $akey.'rel="nofollow" '.
+ $akey.$rel.
'title="'.hsc($caption).$addTitle.'"', 1
);
}
@@ -597,6 +597,7 @@ function tpl_get_action($type) {
global $INFO;
global $REV;
global $ACT;
+ global $conf;
// check disabled actions and fix the badly named ones
if($type == 'history') $type = 'revisions';
@@ -606,6 +607,7 @@ function tpl_get_action($type) {
$id = $ID;
$method = 'get';
$params = array('do' => $type);
+ $nofollow = true;
switch($type) {
case 'edit':
// most complicated type - we need to decide on current action
@@ -643,6 +645,10 @@ function tpl_get_action($type) {
break;
case 'index':
$accesskey = 'x';
+ // allow searchbots to get to the sitemap from the homepage (when dokuwiki isn't providing a sitemap.xml)
+ if ($conf['start'] == $ID && !$conf['sitemap']) {
+ $nofollow = false;
+ }
break;
case 'top':
$accesskey = 't';
@@ -713,7 +719,7 @@ function tpl_get_action($type) {
return '[unknown %s type]';
break;
}
- return compact('accesskey', 'type', 'id', 'method', 'params');
+ return compact('accesskey', 'type', 'id', 'method', 'params', 'nofollow');
}
/**
@@ -766,7 +772,7 @@ function tpl_searchform($ajax = true, $autocomplete = true) {
// don't print the search form if search action has been disabled
if(!actionOK('search')) return false;
- print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search" method="get"><div class="no">';
+ print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search" method="get" role="search"><div class="no">';
print '<input type="hidden" name="do" value="search" />';
print '<input type="text" ';
if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" ';
@@ -794,13 +800,7 @@ function tpl_breadcrumbs($sep = '•') {
$crumbs = breadcrumbs(); //setup crumb trace
- //reverse crumborder in right-to-left mode, add RLM character to fix heb/eng display mixups
- if($lang['direction'] == 'rtl') {
- $crumbs = array_reverse($crumbs, true);
- $crumbs_sep = ' &#8207;<span class="bcsep">'.$sep.'</span>&#8207; ';
- } else {
- $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
- }
+ $crumbs_sep = ' <span class="bcsep">'.$sep.'</span> ';
//render crumbs, highlight the last one
print '<span class="bchead">'.$lang['breadcrumb'].':</span>';
@@ -810,7 +810,9 @@ function tpl_breadcrumbs($sep = '•') {
$i++;
echo $crumbs_sep;
if($i == $last) print '<span class="curid">';
+ print '<bdi>';
tpl_link(wl($id), hsc($name), 'class="breadcrumbs" title="'.$id.'"');
+ print '</bdi>';
if($i == $last) print '</span>';
}
return true;
@@ -883,7 +885,7 @@ function tpl_userinfo() {
global $lang;
global $INFO;
if(isset($_SERVER['REMOTE_USER'])) {
- print $lang['loggedinas'].': '.hsc($INFO['userinfo']['name']).' ('.hsc($_SERVER['REMOTE_USER']).')';
+ print $lang['loggedinas'].': <bdi>'.hsc($INFO['userinfo']['name']).'</bdi> (<bdi>'.hsc($_SERVER['REMOTE_USER']).'</bdi>)';
return true;
}
return false;
@@ -922,14 +924,14 @@ function tpl_pageinfo($ret = false) {
// print it
if($INFO['exists']) {
$out = '';
- $out .= $fn;
+ $out .= '<bdi>'.$fn.'</bdi>';
$out .= ' · ';
$out .= $lang['lastmod'];
$out .= ': ';
$out .= $date;
if($INFO['editor']) {
$out .= ' '.$lang['by'].' ';
- $out .= editorinfo($INFO['editor']);
+ $out .= '<bdi>'.editorinfo($INFO['editor']).'</bdi>';
} else {
$out .= ' ('.$lang['external_edit'].')';
}
@@ -937,7 +939,7 @@ function tpl_pageinfo($ret = false) {
$out .= ' · ';
$out .= $lang['lockedby'];
$out .= ': ';
- $out .= editorinfo($INFO['locked']);
+ $out .= '<bdi>'.editorinfo($INFO['locked']).'</bdi>';
}
if($ret) {
return $out;
@@ -1187,6 +1189,34 @@ function tpl_getLang($id) {
}
/**
+ * Retrieve a language dependent file and pass to xhtml renderer for display
+ * template equivalent of p_locale_xhtml()
+ *
+ * @param string $id id of language dependent wiki page
+ * @return string parsed contents of the wiki page in xhtml format
+ */
+function tpl_locale_xhtml($id) {
+ return p_cached_output(tpl_localeFN($id));
+}
+
+/**
+ * Prepends appropriate path for a language dependent filename
+ */
+function tpl_localeFN($id) {
+ $path = tpl_incdir().'lang/';
+ global $conf;
+ $file = DOKU_CONF.'/template_lang/'.$conf['template'].'/'.$conf['lang'].'/'.$id.'.txt';
+ if (!@file_exists($file)){
+ $file = $path.$conf['lang'].'/'.$id.'.txt';
+ if(!@file_exists($file)){
+ //fall back to english
+ $file = $path.'en/'.$id.'.txt';
+ }
+ }
+ return $file;
+}
+
+/**
* prints the "main content" in the mediamanger popup
*
* Depending on the user's actions this may be a list of
@@ -1463,8 +1493,8 @@ function tpl_license($img = 'badge', $imgonly = false, $return = false, $wrap =
}
if(!$imgonly) {
$out .= $lang['license'].' ';
- $out .= '<a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
- $out .= '>'.$lic['name'].'</a>';
+ $out .= '<bdi><a href="'.$lic['url'].'" rel="license" class="urlextern"'.$target;
+ $out .= '>'.$lic['name'].'</a></bdi>';
}
if($wrap) $out .= '</div>';
@@ -1748,5 +1778,23 @@ function tpl_media() {
echo '</div>'.NL;
}
+/**
+ * Return useful layout classes
+ *
+ * @author Anika Henke <anika@selfthinker.org>
+ */
+function tpl_classes() {
+ global $ACT, $conf, $ID, $INFO;
+ $classes = array(
+ 'dokuwiki',
+ 'mode_'.$ACT,
+ 'tpl_'.$conf['template'],
+ $_SERVER['REMOTE_USER'] ? 'loggedIn' : '',
+ $INFO['exists'] ? '' : 'notFound',
+ ($ID == $conf['start']) ? 'home' : '',
+ );
+ return join(' ', $classes);
+}
+
//Setup VIM: ex: et ts=4 :
diff --git a/install.php b/install.php
index ab0fad121..9f1ad0dc1 100644
--- a/install.php
+++ b/install.php
@@ -148,8 +148,8 @@ header('Content-Type: text/html; charset=utf-8');
<div style="clear: both">
- <a href="http://dokuwiki.org/"><img src="lib/tpl/default/images/button-dw.png" alt="driven by DokuWiki" /></a>
- <a href="http://www.php.net"><img src="lib/tpl/default/images/button-php.gif" alt="powered by PHP" /></a>
+ <a href="http://dokuwiki.org/"><img src="lib/tpl/dokuwiki/images/button-dw.png" alt="driven by DokuWiki" /></a>
+ <a href="http://www.php.net"><img src="lib/tpl/dokuwiki/images/button-php.gif" alt="powered by PHP" /></a>
</div>
</body>
</html>
diff --git a/lib/exe/css.php b/lib/exe/css.php
index 1e662c64a..83972d407 100644
--- a/lib/exe/css.php
+++ b/lib/exe/css.php
@@ -131,6 +131,8 @@ function css_out(){
// load files
$css_content = '';
foreach($files[$mediatype] as $file => $location){
+ $display = str_replace(fullpath(DOKU_INC), '', fullpath($file));
+ $css_content .= "\n/* XXXXXXXXX $display XXXXXXXXX */\n";
$css_content .= css_loadfile($file, $location);
}
switch ($mediatype) {
@@ -154,7 +156,10 @@ function css_out(){
// apply style replacements
$css = css_applystyle($css,$tplinc);
- // place all @import statements at the top of the file
+ // parse less
+ $css = css_parseless($css);
+
+ // place all remaining @import statements at the top of the file
$css = css_moveimports($css);
// compress whitespace and comments
@@ -172,16 +177,87 @@ function css_out(){
}
/**
+ * Uses phpless to parse LESS in our CSS
+ *
+ * most of this function is error handling to show a nice useful error when
+ * LESS compilation fails
+ *
+ * @param $css
+ * @return string
+ */
+function css_parseless($css) {
+ $less = new lessc();
+ try {
+ return $less->compile($css);
+ } catch(Exception $e) {
+ // get exception message
+ $msg = str_replace(array("\n", "\r", "'"), array(), $e->getMessage());
+
+ // try to use line number to find affected file
+ if(preg_match('/line: (\d+)$/', $msg, $m)){
+ $msg = substr($msg, 0, -1* strlen($m[0])); //remove useless linenumber
+ $lno = $m[1];
+
+ // walk upwards to last include
+ $lines = explode("\n", $css);
+ $count = count($lines);
+ for($i=$lno-1; $i>=0; $i--){
+ if(preg_match('/\/(\* XXXXXXXXX )(.*?)( XXXXXXXXX \*)\//', $lines[$i], $m)){
+ // we found it, add info to message
+ $msg .= ' in '.$m[2].' at line '.($lno-$i);
+ break;
+ }
+ }
+ }
+
+ // something went wrong
+ $error = 'A fatal error occured during compilation of the CSS files. '.
+ 'If you recently installed a new plugin or template it '.
+ 'might be broken and you should try disabling it again. ['.$msg.']';
+
+ echo ".dokuwiki:before {
+ content: '$error';
+ background-color: red;
+ display: block;
+ background-color: #fcc;
+ border-color: #ebb;
+ color: #000;
+ padding: 0.5em;
+ }";
+
+ exit;
+ }
+}
+
+/**
* Does placeholder replacements in the style according to
* the ones defined in a templates style.ini file
*
+ * This also adds the ini defined placeholders as less variables
+ * (sans the surrounding __ and with a ini_ prefix)
+ *
* @author Andreas Gohr <andi@splitbrain.org>
*/
function css_applystyle($css,$tplinc){
$styleini = css_styleini($tplinc);
if($styleini){
- $css = strtr($css,$styleini['replacements']);
+ // we convert ini replacements to LESS variable names
+ // and build a list of variable: value; pairs
+ $less = '';
+ foreach($styleini['replacements'] as $key => $value){
+ $lkey = trim($key, '_');
+ $lkey = '@ini_'.$lkey;
+ $less .= "$lkey: $value;\n";
+
+ $styleini['replacements'][$key] = $lkey;
+ }
+
+ // we now replace all old ini replacements with LESS variables
+ $css = strtr($css, $styleini['replacements']);
+
+ // now prepend the list of LESS variables as the very first thing
+ $css = $less.$css;
}
return $css;
}
@@ -314,7 +390,7 @@ function css_datauri($match){
$data = base64_encode(file_get_contents($local));
}
if($data){
- $url = 'data:image/'.$ext.';base64,'.$data;
+ $url = '\'data:image/'.$ext.';base64,'.$data.'\'';
}else{
$url = $base.$url;
}
@@ -333,9 +409,11 @@ function css_pluginstyles($mediatype='screen'){
$plugins = plugin_list();
foreach ($plugins as $p){
$list[DOKU_PLUGIN."$p/$mediatype.css"] = DOKU_BASE."lib/plugins/$p/";
+ $list[DOKU_PLUGIN."$p/$mediatype.less"] = DOKU_BASE."lib/plugins/$p/";
// alternative for screen.css
if ($mediatype=='screen') {
$list[DOKU_PLUGIN."$p/style.css"] = DOKU_BASE."lib/plugins/$p/";
+ $list[DOKU_PLUGIN."$p/style.less"] = DOKU_BASE."lib/plugins/$p/";
}
// @deprecated 2012-04-09: rtl will cease to be a mode of its own,
// please use "[dir=rtl]" in any css file in all, screen or print mode instead
diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php
index 7a2250373..5967494bf 100644
--- a/lib/exe/fetch.php
+++ b/lib/exe/fetch.php
@@ -60,6 +60,7 @@ if (defined('SIMPLE_TEST')) {
if($evt->advise_before()) {
// redirects
if($data['status'] > 300 && $data['status'] <= 304) {
+ if (defined('SIMPLE_TEST')) return; //TestResponse doesn't recognize redirects
send_redirect($data['statusmessage']);
}
// send any non 200 status
diff --git a/lib/exe/js.php b/lib/exe/js.php
index 4ff48133e..4b4b598de 100644
--- a/lib/exe/js.php
+++ b/lib/exe/js.php
@@ -96,6 +96,10 @@ function js_out(){
// load JS specific translations
$json = new JSON();
$lang['js']['plugins'] = js_pluginstrings();
+ $templatestrings = js_templatestrings();
+ if(!empty($templatestrings)) {
+ $lang['js']['template'] = $templatestrings;
+ }
echo 'LANG = '.$json->encode($lang['js']).";\n";
// load toolbar
@@ -104,10 +108,13 @@ function js_out(){
// load files
foreach($files as $file){
$ismin = (substr($file,-7) == '.min.js');
+ $debugjs = ($conf['allowdebug'] && strpos($file, DOKU_INC.'lib/scripts/') !== 0);
echo "\n\n/* XXXXXXXXXX begin of ".str_replace(DOKU_INC, '', $file) ." XXXXXXXXXX */\n\n";
if($ismin) echo "\n/* BEGIN NOCOMPRESS */\n";
+ if ($debugjs) echo "\ntry {\n";
js_load($file);
+ if ($debugjs) echo "\n} catch (e) {\n logError(e, '".str_replace(DOKU_INC, '', $file)."');\n}\n";
if($ismin) echo "\n/* END NOCOMPRESS */\n";
echo "\n\n/* XXXXXXXXXX end of " . str_replace(DOKU_INC, '', $file) . " XXXXXXXXXX */\n\n";
}
@@ -207,6 +214,21 @@ function js_pluginstrings()
return $pluginstrings;
}
+function js_templatestrings() {
+ global $conf;
+ $templatestrings = array();
+ if (@file_exists(tpl_incdir()."lang/en/lang.php")) {
+ include tpl_incdir()."lang/en/lang.php";
+ }
+ if (isset($conf['lang']) && $conf['lang']!='en' && @file_exists(tpl_incdir()."lang/".$conf['lang']."/lang.php")) {
+ include tpl_incdir()."lang/".$conf['lang']."/lang.php";
+ }
+ if (isset($lang['js'])) {
+ $templatestrings[$conf['template']] = $lang['js'];
+ }
+ return $templatestrings;
+}
+
/**
* Escapes a String to be embedded in a JavaScript call, keeps \n
* as newline
diff --git a/lib/exe/opensearch.php b/lib/exe/opensearch.php
index 73939c347..98f5f52d5 100644
--- a/lib/exe/opensearch.php
+++ b/lib/exe/opensearch.php
@@ -21,7 +21,7 @@ if(file_exists(DOKU_INC.'favicon.ico')){
}elseif(file_exists(tpl_incdir().'favicon.ico')){
$ico = DOKU_URL.'lib/tpl/'.$conf['template'].'/favicon.ico';
}else{
- $ico = DOKU_URL.'lib/tpl/default/images/favicon.ico';
+ $ico = DOKU_URL.'lib/tpl/dokuwiki/images/favicon.ico';
}
// output
diff --git a/lib/plugins/acl/lang/de-informal/lang.php b/lib/plugins/acl/lang/de-informal/lang.php
index 8b1416137..3487f4257 100644
--- a/lib/plugins/acl/lang/de-informal/lang.php
+++ b/lib/plugins/acl/lang/de-informal/lang.php
@@ -9,6 +9,7 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['admin_acl'] = 'Zugangsverwaltung';
$lang['acl_group'] = 'Gruppe';
@@ -21,8 +22,8 @@ $lang['p_user_id'] = 'Benutzer <b class="acluser">%s</b> hat im Mome
$lang['p_user_ns'] = 'Benutzer <b class="acluser">%s</b> hat momentan die folgenden Rechte im Namensraum <b class="aclns">%s</b>: <i>%s</i>.';
$lang['p_group_id'] = 'Die Gruppenmitglieder <b class="aclgroup">%s</b> haben momentan die folgenden Rechte auf der Seite <b class="aclpage">%s</b>: <i>%s</i>.';
$lang['p_group_ns'] = 'Die Mitglieder der Gruppe <b class="aclgroup">%s</b> haben gerade Zugriff in folgenden Namensräumen <b class="aclns">%s</b>: <i>%s</i>.';
-$lang['p_choose_id'] = 'Bitte <b>gib einen Nutzer oder eine Gruppe</b> in das Formular ein, um die Berechtigungen der Seite <b class="aclpage">%s</b> anzusehen oder zu bearbeiten.';
-$lang['p_choose_ns'] = 'Bitte <b>gib einen Nutzer oder eine Gruppe</b> in das Formular ein, um die Berechtigungen des Namenraumes <b class="aclpage">%s</b> anzusehen oder zu bearbeiten.';
+$lang['p_choose_id'] = 'Bitte <b>gib einen Benutzer oder eine Gruppe</b> in das Formular ein, um die Berechtigungen der Seite <b class="aclpage">%s</b> anzusehen oder zu bearbeiten.';
+$lang['p_choose_ns'] = 'Bitte <b>gib einen Benutzer oder eine Gruppe</b> in das Formular ein, um die Berechtigungen des Namenraumes <b class="aclpage">%s</b> anzusehen oder zu bearbeiten.';
$lang['p_inherited'] = 'Hinweis: Diese Rechte wurden nicht explizit gesetzt, sondern von anderen Gruppen oder übergeordneten Namensräumen geerbt.';
$lang['p_isadmin'] = 'Hinweis: Die gewählte Gruppe oder der Benutzer haben immer die vollen Rechte, weil sie als Superuser konfiguriert sind.';
$lang['p_include'] = 'Höhere Rechte schließen kleinere mit ein. Hochlade- und Löschrechte sind nur für Namensräume, nicht für Seiten.';
diff --git a/lib/plugins/acl/lang/de/help.txt b/lib/plugins/acl/lang/de/help.txt
index 783ae22e7..2a3efe5f0 100644
--- a/lib/plugins/acl/lang/de/help.txt
+++ b/lib/plugins/acl/lang/de/help.txt
@@ -4,7 +4,7 @@ Auf dieser Seite können sie Zugriffsberechtigungen für Seiten und Namensräume
Die Liste links zeigt alle verfügbaren Namensräume und Seiten.
-Das Formular oben erlaubt Anzeige, Ändern und Hinzufügen von Zugriffsregeln für einen ausgewählten Nutzer oder eine Gruppe.
+Das Formular oben erlaubt Anzeige, Ändern und Hinzufügen von Zugriffsregeln für einen ausgewählten Benutzer oder eine Gruppe.
In der Tabelle unten werden alle bestehenden Regeln aufgeführt und können dort modifiziert oder gelöscht werden.
diff --git a/lib/plugins/acl/lang/de/lang.php b/lib/plugins/acl/lang/de/lang.php
index eb23636c4..5f3e51a32 100644
--- a/lib/plugins/acl/lang/de/lang.php
+++ b/lib/plugins/acl/lang/de/lang.php
@@ -33,10 +33,10 @@ $lang['p_user_id'] = 'Nutzer <b class="acluser">%s</b> hat momentan
$lang['p_user_ns'] = 'Nutzer <b class="acluser">%s</b> hat momentan folgende Berechtigungen im Namensraum <b class="aclns">%s</b>: <i>%s</i>.';
$lang['p_group_id'] = 'Mitglieder der Gruppe <b class="aclgroup">%s</b> haben momentan folgende Berechtigungen für die Seite <b class="aclpage">%s</b>: <i>%s</i>.';
$lang['p_group_ns'] = 'Mitglieder der Gruppe <b class="aclgroup">%s</b> haben momentan folgende Berechtigungen für den Namensraum <b class="aclns">%s</b>: <i>%s</i>.';
-$lang['p_choose_id'] = 'Bitte geben Sie in obigem Formular eine <b>einen Nutzer oder eine Gruppe</b> an, um die Berechtigungen für die Seite <b class="aclpage">%s</b> zu sehen oder zu ändern.';
-$lang['p_choose_ns'] = 'Bitte geben Sie in obigem Formular eine <b>einen Nutzer oder eine Gruppe</b> an, um die Berechtigungen für den Namensraum <b class="aclns">%s</b> zu sehen oder zu ändern.';
+$lang['p_choose_id'] = 'Bitte geben Sie in obigem Formular eine <b>einen Benutzer oder eine Gruppe</b> an, um die Berechtigungen für die Seite <b class="aclpage">%s</b> zu sehen oder zu ändern.';
+$lang['p_choose_ns'] = 'Bitte geben Sie in obigem Formular eine <b>einen Benutzer oder eine Gruppe</b> an, um die Berechtigungen für den Namensraum <b class="aclns">%s</b> zu sehen oder zu ändern.';
$lang['p_inherited'] = 'Hinweis: Diese Berechtigungen wurden nicht explizit gesetzt, sondern von anderen Gruppen oder höher liegenden Namensräumen geerbt.';
-$lang['p_isadmin'] = 'Hinweis: Die ausgewählte Gruppe oder Nutzer haben immer alle Berechtigungen das sie als Superuser konfiguriert wurden.';
+$lang['p_isadmin'] = 'Hinweis: Die ausgewählte Gruppe oder Benutzer haben immer alle Berechtigungen das sie als Superuser konfiguriert wurden.';
$lang['p_include'] = 'Höhere Berechtigungen schließen niedrigere mit ein. Anlegen, Hochladen und Entfernen gilt nur für Namensräume, nicht für einzelne Seiten';
$lang['current'] = 'Momentane Zugriffsregeln';
$lang['where'] = 'Seite/Namensraum';
diff --git a/lib/plugins/acl/lang/hu/lang.php b/lib/plugins/acl/lang/hu/lang.php
index 255d838b6..9565eddc3 100644
--- a/lib/plugins/acl/lang/hu/lang.php
+++ b/lib/plugins/acl/lang/hu/lang.php
@@ -8,25 +8,26 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
$lang['admin_acl'] = 'Hozzáférési lista (ACL) kezelő';
$lang['acl_group'] = 'Csoport:';
$lang['acl_user'] = 'Felhasználó:';
$lang['acl_perms'] = 'Jogosultság ehhez:';
-$lang['page'] = 'oldal';
-$lang['namespace'] = 'névtér';
+$lang['page'] = 'Oldal';
+$lang['namespace'] = 'Névtér';
$lang['btn_select'] = 'Kiválaszt';
$lang['p_user_id'] = 'A(z) <b class="acluser">%s</b> felhasználónak jelenleg a következő jogosultsága van ezen az oldalon: <b class="aclpage">%s</b>: <i>%s</i>.';
$lang['p_user_ns'] = 'A(z) <b class="acluser">%s</b> felhasználónak jelenleg a következő jogosultsága van ebben a névtérben: <b class="aclns">%s</b>: <i>%s</i>.';
$lang['p_group_id'] = 'A(z) <b class="aclgroup">%s</b> csoport tagjainak jelenleg a következő jogosultsága van ezen az oldalon: <b class="aclpage">%s</b>: <i>%s</i>.';
$lang['p_group_ns'] = 'A(z) <b class="aclgroup">%s</b> csoport tagjainak jelenleg a következő jogosultsága van ebben a névtérben: <b class="aclns">%s</b>: <i>%s</i>.';
-$lang['p_choose_id'] = 'A felső formon <b>adjon meg egy felhasználót vagy csoportot</b>, akinek a(z) <b class="aclpage">%s</b> oldalhoz beállított jogosultságait megtekinteni vagy változtatni szeretné.';
-$lang['p_choose_ns'] = 'A felső formon <b>adjon meg egy felhasználót vagy csoportot</b>, akinek a(z) <b class="aclns">%s</b> névtérhez beállított jogosultságait megtekinteni vagy változtatni szeretné.';
+$lang['p_choose_id'] = 'A felső űrlapon <b>adjon meg egy felhasználót vagy csoportot</b>, akinek a(z) <b class="aclpage">%s</b> oldalhoz beállított jogosultságait megtekinteni vagy változtatni szeretné.';
+$lang['p_choose_ns'] = 'A felső űrlapon <b>adj meg egy felhasználót vagy csoportot</b>, akinek a(z) <b class="aclns">%s</b> névtérhez beállított jogosultságait megtekinteni vagy változtatni szeretnéd.';
$lang['p_inherited'] = 'Megjegyzés: ezek a jogok nem itt lettek explicit beállítva, hanem öröklődtek egyéb csoportokból vagy felsőbb névterekből.';
-$lang['p_isadmin'] = 'Megjegyzés: a kiválasztott csoportnak vagy felhasználónak mindig teljes jogosultsága lesz, mert Wiki-gazdának van beállítva.';
-$lang['p_include'] = 'A magasabb jogok tartalmazzák az alacsonyabbakat. A Létrehozás, Feltöltés és Törlés jogosultságok csak névterekre alkalmazhatók, az egyes oldalakra nem.';
+$lang['p_isadmin'] = 'Megjegyzés: a kiválasztott csoportnak vagy felhasználónak mindig teljes jogosultsága lesz, mert Adminisztrátornak van beállítva.';
+$lang['p_include'] = 'A magasabb szintű jogok tartalmazzák az alacsonyabbakat. A Létrehozás, Feltöltés és Törlés jogosultságok csak névterekre alkalmazhatók, az egyes oldalakra nem.';
$lang['current'] = 'Jelenlegi hozzáférési szabályok';
-$lang['where'] = 'Oldal/névtér';
+$lang['where'] = 'Oldal/Névtér';
$lang['who'] = 'Felhasználó/Csoport';
$lang['perm'] = 'Jogosultságok';
$lang['acl_perm0'] = 'Semmi';
diff --git a/lib/plugins/acl/lang/ko/help.txt b/lib/plugins/acl/lang/ko/help.txt
index 0386b5990..ba3dd6d9f 100644
--- a/lib/plugins/acl/lang/ko/help.txt
+++ b/lib/plugins/acl/lang/ko/help.txt
@@ -5,4 +5,4 @@
* 위쪽 입력 양식에서 선택된 사용자와 그룹의 접근 권한을 보거나 바꿀 수 있습니다.
* 아래 테이블에서 현재 설정된 모든 접근 제어 규칙을 볼 수 있으며, 즉시 여러 규칙을 삭제하거나 바꿀 수 있습니다.
-DokuWiki에서 접근 제어가 어떻게 동작되는지 알아보려면 [[doku>acl|ACL 공식 문서]]를 읽어보시기 바랍니다. \ No newline at end of file
+DokuWiki에서 접근 제어가 어떻게 동작되는지 알아보려면 [[doku>ko:acl|ACL 공식 문서]]를 읽어보시기 바랍니다. \ No newline at end of file
diff --git a/lib/plugins/acl/lang/sv/lang.php b/lib/plugins/acl/lang/sv/lang.php
index 388672fc0..f226542e6 100644
--- a/lib/plugins/acl/lang/sv/lang.php
+++ b/lib/plugins/acl/lang/sv/lang.php
@@ -1,11 +1,11 @@
<?php
+
/**
- * swedish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -14,7 +14,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/acl/remote.php b/lib/plugins/acl/remote.php
new file mode 100644
index 000000000..8f6dfbcd9
--- /dev/null
+++ b/lib/plugins/acl/remote.php
@@ -0,0 +1,30 @@
+<?php
+
+class remote_plugin_acl extends DokuWiki_Remote_Plugin {
+ function _getMethods() {
+ return array(
+ 'addAcl' => array(
+ 'args' => array('string','string','int'),
+ 'return' => 'int',
+ 'name' => 'addAcl',
+ 'doc' => 'Adds a new ACL rule.'
+ ), 'delAcl' => array(
+ 'args' => array('string','string'),
+ 'return' => 'int',
+ 'name' => 'delAcl',
+ 'doc' => 'Delete an existing ACL rule.'
+ ),
+ );
+ }
+
+ function addAcl($scope, $user, $level){
+ $apa = plugin_load('admin', 'acl');
+ return $apa->_acl_add($scope, $user, $level);
+ }
+
+ function delAcl($scope, $user){
+ $apa = plugin_load('admin', 'acl');
+ return $apa->_acl_del($scope, $user);
+ }
+}
+
diff --git a/lib/plugins/acl/script.js b/lib/plugins/acl/script.js
index c3763dc8d..0abb80d67 100644
--- a/lib/plugins/acl/script.js
+++ b/lib/plugins/acl/script.js
@@ -61,6 +61,7 @@ var dw_acl = {
*/
loadinfo: function () {
jQuery('#acl__info')
+ .attr('role', 'alert')
.html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="..." />')
.load(
DOKU_BASE + 'lib/plugins/acl/ajax.php',
diff --git a/lib/plugins/authad/lang/de-informal/settings.php b/lib/plugins/authad/lang/de-informal/settings.php
index 4d0b93e5d..a458617b8 100644
--- a/lib/plugins/authad/lang/de-informal/settings.php
+++ b/lib/plugins/authad/lang/de-informal/settings.php
@@ -4,6 +4,7 @@
*
* @author Frank Loizzi <contact@software.bacal.de>
* @author Matthias Schulte <dokuwiki@lupo49.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['account_suffix'] = 'Dein Account-Suffix. Z.B. <code>@my.domain.org</code>';
$lang['base_dn'] = 'Dein Base-DN. Z.B. <code>DC=my,DC=domain,DC=org</code>';
diff --git a/lib/plugins/authad/lang/hu/settings.php b/lib/plugins/authad/lang/hu/settings.php
new file mode 100644
index 000000000..c2cab410f
--- /dev/null
+++ b/lib/plugins/authad/lang/hu/settings.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Hungarian language file
+ *
+ * @author Marton Sebok <sebokmarton@gmail.com>
+ */
+$lang['account_suffix'] = 'Felhasználói azonosító végződése, pl. <code>@my.domain.org</code>.';
+$lang['base_dn'] = 'Bázis DN, pl. <code>DC=my,DC=domain,DC=org</code>.';
+$lang['domain_controllers'] = 'Tartománykezelők listája vesszővel elválasztva, pl. <code>srv1.domain.org,srv2.domain.org</code>.';
+$lang['admin_username'] = 'Privilegizált AD felhasználó, aki az összes feéhasználó adatait elérheti. Elhagyható, de bizonyos funkciókhoz, például a feliratkozási e-mailek kiküldéséhez szükséges.';
+$lang['admin_password'] = 'Ehhez tartozó jelszó.';
+$lang['sso'] = 'Single-Sign-On Kerberos-szal vagy NTML használata?';
+$lang['real_primarygroup'] = 'A valódi elsődleges csoport feloldása a "Tartományfelhasználók" csoport használata helyett? (lassabb)';
+$lang['use_ssl'] = 'SSL használata? Ha használjuk, tiltsuk le a TLS-t!';
+$lang['use_tls'] = 'TLS használata? Ha használjuk, tiltsuk le az SSL-t!';
+$lang['debug'] = 'Debug-üzenetek megjelenítése?';
+$lang['expirywarn'] = 'Felhasználók értesítése ennyi nappal a jelszavuk lejárata előtt. 0 a funkció kikapcsolásához.';
+$lang['additional'] = 'Vesszővel elválasztott lista a további AD attribútumok lekéréshez. Néhány plugin használhatja.';
diff --git a/lib/plugins/authad/lang/pl/settings.php b/lib/plugins/authad/lang/pl/settings.php
new file mode 100644
index 000000000..9113c0e51
--- /dev/null
+++ b/lib/plugins/authad/lang/pl/settings.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Polish language file
+ *
+ */
+$lang['account_suffix'] = 'Przyrostek twojej nazwy konta np. <code>@my.domain.org</code>';
+$lang['admin_password'] = 'Hasło dla powyższego użytkownika.';
+$lang['use_ssl'] = 'Użyć połączenie SSL? Jeśli tak to nie aktywuj TLS poniżej.';
+$lang['use_tls'] = 'Użyć połączenie TLS? Jeśli tak to nie aktywuj SSL powyżej.';
+$lang['expirywarn'] = 'Dni poprzedzających powiadomienie użytkownika o wygasającym haśle. 0 aby wyłączyć.';
diff --git a/lib/plugins/authad/lang/pt-br/settings.php b/lib/plugins/authad/lang/pt-br/settings.php
index 29f8db4ad..56f37b75f 100644
--- a/lib/plugins/authad/lang/pt-br/settings.php
+++ b/lib/plugins/authad/lang/pt-br/settings.php
@@ -3,12 +3,15 @@
* Brazilian Portuguese language file
*
* @author Victor Westmann <victor.westmann@gmail.com>
+ * @author Frederico Guimarães <frederico@teia.bio.br>
*/
$lang['account_suffix'] = 'Sufixo de sua conta. Eg. <code>@meu.domínio.org</code>';
$lang['base_dn'] = 'Sua base DN. Eg. <code>DC=meu,DC=domínio,DC=org</code>';
$lang['domain_controllers'] = 'Uma lista de controles de domínios separada por vírgulas. Eg. <code>srv1.domínio.org,srv2.domínio.org</code>';
+$lang['admin_username'] = 'Um usuário do Active Directory com privilégios para acessar os dados de todos os outros usuários. Opcional, mas necessário para realizar certas ações, tais como enviar mensagens de assinatura.';
$lang['admin_password'] = 'A senha do usuário acima.';
$lang['sso'] = 'Usar Single-Sign-On através do Kerberos ou NTLM?';
+$lang['real_primarygroup'] = 'O grupo primário real deve ser resolvido ao invés de assumirmos como "Usuários do Domínio" (mais lento)';
$lang['use_ssl'] = 'Usar conexão SSL? Se usar, não habilitar TLS abaixo.';
$lang['use_tls'] = 'Usar conexão TLS? se usar, não habilitar SSL acima.';
$lang['debug'] = 'Mostrar saída adicional de depuração em mensagens de erros?';
diff --git a/lib/plugins/authad/lang/sv/settings.php b/lib/plugins/authad/lang/sv/settings.php
index b1eb1cb96..17eb523a8 100644
--- a/lib/plugins/authad/lang/sv/settings.php
+++ b/lib/plugins/authad/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['account_suffix'] = 'Ditt konto suffix. T.ex. <code>min.domän.org</code>';
diff --git a/lib/plugins/authldap/lang/de-informal/settings.php b/lib/plugins/authldap/lang/de-informal/settings.php
index fa0fc1521..15e4d8129 100644
--- a/lib/plugins/authldap/lang/de-informal/settings.php
+++ b/lib/plugins/authldap/lang/de-informal/settings.php
@@ -4,6 +4,7 @@
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Matthias Schulte <dokuwiki@lupo49.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['server'] = 'Adresse zum LDAP-Server. Entweder als Hostname (<code>localhost</code>) oder als FQDN (<code>ldap://server.tld:389</code>).';
$lang['port'] = 'Port des LDAP-Servers, falls kein Port angegeben wurde.';
@@ -14,9 +15,14 @@ $lang['groupfilter'] = 'LDAP-Filter, um die Benutzergruppen zu suchen.
$lang['version'] = 'Zu verwendende Protokollversion von LDAP.';
$lang['starttls'] = 'Verbindung über TLS aufbauen?';
$lang['referrals'] = 'Weiterverfolgen von LDAP-Referrals (Verweise)?';
+$lang['deref'] = 'Wie sollen Aliasse derefernziert werden?';
$lang['binddn'] = 'DN eines optionalen Benutzers, wenn der anonyme Zugriff nicht ausreichend ist. Zum Beispiel: <code>cn=admin, dc=my, dc=home</code>.';
$lang['bindpw'] = 'Passwort des angegebenen Benutzers.';
$lang['userscope'] = 'Die Suchweite nach Benutzeraccounts.';
$lang['groupscope'] = 'Die Suchweite nach Benutzergruppen.';
$lang['groupkey'] = 'Gruppieren der Benutzeraccounts anhand eines beliebigen Benutzerattributes z. B. Telefonnummer oder Abteilung, anstelle der Standard-Gruppen).';
$lang['debug'] = 'Debug-Informationen beim Auftreten von Fehlern anzeigen?';
+$lang['deref_o_0'] = 'LDAP_DEREF_NIEMALS';
+$lang['deref_o_1'] = 'LDAP_DEREF_SUCHEN';
+$lang['deref_o_2'] = 'LDAP_DEREF_FINDEN';
+$lang['deref_o_3'] = 'LDAP_DEREF_IMMER';
diff --git a/lib/plugins/authldap/lang/en/settings.php b/lib/plugins/authldap/lang/en/settings.php
index e3f385f99..b73166ab2 100644
--- a/lib/plugins/authldap/lang/en/settings.php
+++ b/lib/plugins/authldap/lang/en/settings.php
@@ -20,4 +20,4 @@ $lang['debug'] = 'Display additional debug information on errors';
$lang['deref_o_0'] = 'LDAP_DEREF_NEVER';
$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING';
$lang['deref_o_2'] = 'LDAP_DEREF_FINDING';
-$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS'; \ No newline at end of file
+$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS';
diff --git a/lib/plugins/authldap/lang/hu/settings.php b/lib/plugins/authldap/lang/hu/settings.php
new file mode 100644
index 000000000..b4b28d0a0
--- /dev/null
+++ b/lib/plugins/authldap/lang/hu/settings.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Hungarian language file
+ *
+ * @author Marton Sebok <sebokmarton@gmail.com>
+ */
+$lang['server'] = 'LDAP-szerver. Hosztnév (<code>localhost</code>) vagy abszolút URL portszámmal (<code>ldap://server.tld:389</code>)';
+$lang['port'] = 'LDAP-szerver port, ha nem URL lett megadva';
+$lang['usertree'] = 'Hol találom a felhasználókat? Pl. <code>ou=People, dc=server, dc=tld</code>';
+$lang['grouptree'] = 'Hol találom a csoportokat? Pl. <code>ou=Group, dc=server, dc=tld</code>';
+$lang['userfilter'] = 'LDAP szűrő a felhasználók kereséséhez, pl. <code>(&amp;(uid=%{user})(objectClass=posixAccount))</code>';
+$lang['groupfilter'] = 'LDAP szűrő a csoportok kereséséhez, pl. <code>(&amp;(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))</code>';
+$lang['version'] = 'A használt protokollverzió. Valószínűleg a <code>3</code> megfelelő';
+$lang['starttls'] = 'TLS használata?';
+$lang['referrals'] = 'Hivatkozások követése?';
+$lang['deref'] = 'Hogyan fejtsük vissza az aliasokat?';
+$lang['binddn'] = 'Egy hozzáféréshez használt felhasználó DN-je, ha nincs névtelen hozzáférés. Pl. <code>cn=admin, dc=my, dc=home</code>';
+$lang['bindpw'] = 'Ehhez tartozó jelszó.';
+$lang['userscope'] = 'A keresési tartomány korlátozása erre a felhasználókra való keresésnél';
+$lang['groupscope'] = 'A keresési tartomány korlátozása erre a csoportokra való keresésnél';
+$lang['groupkey'] = 'Csoport meghatározása a következő attribútumból (az alapértelmezett AD csoporttagság helyett), pl. a szervezeti egység vagy a telefonszám';
+$lang['debug'] = 'Debug-üzenetek megjelenítése?';
+$lang['deref_o_0'] = 'LDAP_DEREF_NEVER';
+$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING';
+$lang['deref_o_2'] = 'LDAP_DEREF_FINDING';
+$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS';
diff --git a/lib/plugins/authldap/lang/ko/settings.php b/lib/plugins/authldap/lang/ko/settings.php
index 7f7efe8d0..6200a03b9 100644
--- a/lib/plugins/authldap/lang/ko/settings.php
+++ b/lib/plugins/authldap/lang/ko/settings.php
@@ -13,9 +13,14 @@ $lang['groupfilter'] = '그룹을 찾을 LDAP 필터. 예를 들어 <c
$lang['version'] = '사용할 프로토콜 버전. <code>3</code>으로 설정해야 할 수도 있습니다';
$lang['starttls'] = 'TLS 연결을 사용하겠습니까?';
$lang['referrals'] = '참고(referrals)를 허용하겠습니까? ';
+$lang['deref'] = '어떻게 별명을 간접 참고하겠습니까?';
$lang['binddn'] = '익명 바인드가 충분하지 않으면 선택적인 바인드 사용자의 DN. 예를 들어 <code>cn=admin, dc=my, dc=home</code>';
$lang['bindpw'] = '위 사용자의 비밀번호';
$lang['userscope'] = '사용자 찾기에 대한 찾기 범위 제한';
$lang['groupscope'] = '그룹 찾기에 대한 찾기 범위 제한';
$lang['groupkey'] = '(표준 AD 그룹 대신) 사용자 속성에서 그룹 구성원. 예를 들어 부서나 전화에서 그룹';
$lang['debug'] = '오류에 대한 추가적인 디버그 정보를 보이기';
+$lang['deref_o_0'] = 'LDAP_DEREF_NEVER (없음)';
+$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING (검색)';
+$lang['deref_o_2'] = 'LDAP_DEREF_FINDING (발견)';
+$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS (항상)';
diff --git a/lib/plugins/authldap/lang/pl/settings.php b/lib/plugins/authldap/lang/pl/settings.php
new file mode 100644
index 000000000..44641f514
--- /dev/null
+++ b/lib/plugins/authldap/lang/pl/settings.php
@@ -0,0 +1,7 @@
+<?php
+/**
+ * Polish language file
+ *
+ */
+$lang['starttls'] = 'Użyć połączeń TLS?';
+$lang['bindpw'] = 'Hasło powyższego użytkownika';
diff --git a/lib/plugins/authldap/lang/pt-br/settings.php b/lib/plugins/authldap/lang/pt-br/settings.php
index daf9efd00..d12a9cf36 100644
--- a/lib/plugins/authldap/lang/pt-br/settings.php
+++ b/lib/plugins/authldap/lang/pt-br/settings.php
@@ -3,17 +3,25 @@
* Brazilian Portuguese language file
*
* @author Victor Westmann <victor.westmann@gmail.com>
+ * @author Frederico Guimarães <frederico@teia.bio.br>
*/
$lang['server'] = 'Seu servidor LDAP. Ou hostname (<code>localhost</code>) ou uma URL completa (<code>ldap://server.tld:389</code>)';
$lang['port'] = 'Porta LDAP do servidor se nenhuma URL completa tiver sido fornecida acima';
$lang['usertree'] = 'Onde encontrar as contas de usuários. Eg. <code>ou=Pessoas, dc=servidor, dc=tld</code>';
$lang['grouptree'] = 'Onde encontrar os grupos de usuários. Eg. <code>ou=Pessoas, dc=servidor, dc=tld</code>';
+$lang['userfilter'] = 'Filtro LDAP para pesquisar por contas de usuários. Ex. <code>(&amp;(uid=%{user})(objectClass=posixAccount))</code>';
+$lang['groupfilter'] = 'Filtro LDAP para pesquisar por grupos. Ex. <code>(&amp;(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))</code>';
$lang['version'] = 'A versão do protocolo para usar. Você talvez deva definir isto para <code>3</code>';
$lang['starttls'] = 'Usar conexões TLS?';
-$lang['referrals'] = 'Permitir referências serem seguidas?';
+$lang['referrals'] = 'Permitir que as referências sejam seguidas?';
+$lang['deref'] = 'Como dereferenciar os aliases?';
$lang['binddn'] = 'DN de um vínculo opcional de usuário se vínculo anônimo não for suficiente. Eg. <code>cn=admin, dc=my, dc=home</code>';
$lang['bindpw'] = 'Senha do usuário acima';
$lang['userscope'] = 'Limitar escopo da busca para busca de usuário';
$lang['groupscope'] = 'Limitar escopo da busca para busca de grupo';
$lang['groupkey'] = 'Membro de grupo vem de qualquer atributo do usuário (ao invés de grupos padrões AD) e.g. departamento de grupo ou número de telefone';
$lang['debug'] = 'Mostrar informações adicionais de depuração em erros';
+$lang['deref_o_0'] = 'LDAP_DEREF_NEVER';
+$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING';
+$lang['deref_o_2'] = 'LDAP_DEREF_FINDING';
+$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS';
diff --git a/lib/plugins/authldap/lang/sv/settings.php b/lib/plugins/authldap/lang/sv/settings.php
index 0fdcad147..68dbccfd0 100644
--- a/lib/plugins/authldap/lang/sv/settings.php
+++ b/lib/plugins/authldap/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['server'] = 'Din LDAO server. Antingen värdnamn (<code>localhost</code>) eller giltig full URL (<code>ldap://server.tld:389</code>)';
diff --git a/lib/plugins/authmysql/lang/de-informal/settings.php b/lib/plugins/authmysql/lang/de-informal/settings.php
index 0c9bc85fe..540979cf4 100644
--- a/lib/plugins/authmysql/lang/de-informal/settings.php
+++ b/lib/plugins/authmysql/lang/de-informal/settings.php
@@ -4,6 +4,7 @@
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Matthias Schulte <dokuwiki@lupo49.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['server'] = 'MySQL-Server';
$lang['user'] = 'Benutzername für den Zugriff auf den MySQL-Server.';
diff --git a/lib/plugins/authmysql/lang/hu/settings.php b/lib/plugins/authmysql/lang/hu/settings.php
new file mode 100644
index 000000000..9489c73f9
--- /dev/null
+++ b/lib/plugins/authmysql/lang/hu/settings.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Hungarian language file
+ *
+ * @author Marton Sebok <sebokmarton@gmail.com>
+ */
+$lang['server'] = 'MySQL-szerver';
+$lang['user'] = 'MySQL felhasználónév';
+$lang['password'] = 'Ehhez a jelszó';
+$lang['database'] = 'Adatbázis';
+$lang['charset'] = 'Az adatbázisban használt karakterkészlet';
+$lang['debug'] = 'Debug-üzenetek megjelenítése?';
+$lang['forwardClearPass'] = 'A jelszó nyílt szövegben való átadása a következő SQL utasításokban a passcrypt opció használata helyett';
+$lang['TablesToLock'] = 'Az íráskor zárolandó táblák vesszővel elválasztott listája';
+$lang['checkPass'] = 'SQL utasítás a jelszavak ellenőrzéséhez';
+$lang['getUserInfo'] = 'SQL utasítás a felhasználói információk lekérdezéséhez';
+$lang['getGroups'] = 'SQL utasítás egy felhasználó csoporttagságainak lekérdezéséhez';
+$lang['getUsers'] = 'SQL utasítás a felhasználók listázásához';
+$lang['FilterLogin'] = 'SQL kifejezés a felhasználók azonosító alapú szűréséhez';
+$lang['FilterName'] = 'SQL kifejezés a felhasználók név alapú szűréséhez';
+$lang['FilterEmail'] = 'SQL kifejezés a felhasználók e-mail cím alapú szűréséhez';
+$lang['FilterGroup'] = 'SQL kifejezés a felhasználók csoporttagság alapú szűréséhez';
+$lang['SortOrder'] = 'SQL kifejezés a felhasználók rendezéséhez';
+$lang['addUser'] = 'SQL utasítás új felhasználó hozzáadásához';
+$lang['addGroup'] = 'SQL utasítás új csoport hozzáadásához';
+$lang['addUserGroup'] = 'SQL utasítás egy felhasználó egy meglévő csoporthoz való hozzáadásához';
+$lang['delGroup'] = 'SQL utasítás egy csoport törléséhez';
+$lang['getUserID'] = 'SQL utasítás egy felhasználó elsődleges kulcsának lekérdezéséhez';
+$lang['delUser'] = 'SQL utasítás egy felhasználó törléséhez';
+$lang['delUserRefs'] = 'SQL utasítás egy felhasználó eltávolításához az összes csoportból';
+$lang['updateUser'] = 'SQL utasítás egy felhasználó profiljának frissítéséhez';
+$lang['UpdateLogin'] = 'SQL kifejezés a felhasználó azonosítójának frissítéséhez';
+$lang['UpdatePass'] = 'SQL kifejezés a felhasználó jelszavának frissítéséhez';
+$lang['UpdateEmail'] = 'SQL kifejezés a felhasználó e-mail címének frissítéséhez';
+$lang['UpdateName'] = 'SQL kifejezés a felhasználó nevének frissítéséhez';
+$lang['UpdateTarget'] = 'SQL kifejezés a felhasználó kiválasztásához az adatok frissítésekor';
+$lang['delUserGroup'] = 'SQL utasítás egy felhasználó eltávolításához egy adott csoportból';
+$lang['getGroupID'] = 'SQL utasítás egy csoport elsődleges kulcsának lekérdezéséhez';
+$lang['debug_o_0'] = 'nem';
+$lang['debug_o_1'] = 'csak hiba esetén';
+$lang['debug_o_2'] = 'minden SQL-lekérdezésnél';
diff --git a/lib/plugins/authmysql/lang/pl/settings.php b/lib/plugins/authmysql/lang/pl/settings.php
new file mode 100644
index 000000000..93528cf34
--- /dev/null
+++ b/lib/plugins/authmysql/lang/pl/settings.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Polish language file
+ *
+ */
+$lang['server'] = 'Twój server MySQL';
+$lang['user'] = 'Nazwa użytkownika MySQL';
+$lang['password'] = 'Hasło dla powyższego użytkownika';
+$lang['database'] = 'Używana baza danych';
+$lang['charset'] = 'Zestaw znaków uzyty w bazie danych';
diff --git a/lib/plugins/authmysql/lang/pt-br/settings.php b/lib/plugins/authmysql/lang/pt-br/settings.php
index 5febedd13..8ac775b54 100644
--- a/lib/plugins/authmysql/lang/pt-br/settings.php
+++ b/lib/plugins/authmysql/lang/pt-br/settings.php
@@ -3,6 +3,7 @@
* Brazilian Portuguese language file
*
* @author Victor Westmann <victor.westmann@gmail.com>
+ * @author Frederico Guimarães <frederico@teia.bio.br>
*/
$lang['server'] = 'Seu servidor MySQL';
$lang['user'] = 'usuário MySQL';
diff --git a/lib/plugins/authmysql/lang/sv/settings.php b/lib/plugins/authmysql/lang/sv/settings.php
index 027c64025..420e443f4 100644
--- a/lib/plugins/authmysql/lang/sv/settings.php
+++ b/lib/plugins/authmysql/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['server'] = 'Din MySQL server';
diff --git a/lib/plugins/authpgsql/lang/de-informal/settings.php b/lib/plugins/authpgsql/lang/de-informal/settings.php
index 4c80245d6..d864d14d4 100644
--- a/lib/plugins/authpgsql/lang/de-informal/settings.php
+++ b/lib/plugins/authpgsql/lang/de-informal/settings.php
@@ -4,6 +4,7 @@
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Matthias Schulte <dokuwiki@lupo49.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['server'] = 'PostgreSQL-Server';
$lang['port'] = 'Port des PostgreSQL-Servers.';
diff --git a/lib/plugins/authpgsql/lang/hu/settings.php b/lib/plugins/authpgsql/lang/hu/settings.php
new file mode 100644
index 000000000..7b9393256
--- /dev/null
+++ b/lib/plugins/authpgsql/lang/hu/settings.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Hungarian language file
+ *
+ * @author Marton Sebok <sebokmarton@gmail.com>
+ */
+$lang['server'] = 'PostgreSQL-szerver';
+$lang['port'] = 'PostgreSQL-port';
+$lang['user'] = 'PostgreSQL felhasználónév';
+$lang['password'] = 'Ehhez a jelszó';
+$lang['database'] = 'Adatbázis';
+$lang['debug'] = 'Debug-üzenetek megjelenítése?';
+$lang['forwardClearPass'] = 'A jelszó nyílt szövegben való átadása a következő SQL utasításokban a passcrypt opció használata helyett';
+$lang['checkPass'] = 'SQL utasítás a jelszavak ellenőrzéséhez';
+$lang['getUserInfo'] = 'SQL utasítás a felhasználói információk lekérdezéséhez';
+$lang['getGroups'] = 'SQL utasítás egy felhasználó csoporttagságainak lekérdezéséhez';
+$lang['getUsers'] = 'SQL utasítás a felhasználók listázásához';
+$lang['FilterLogin'] = 'SQL kifejezés a felhasználók azonosító alapú szűréséhez';
+$lang['FilterName'] = 'SQL kifejezés a felhasználók név alapú szűréséhez';
+$lang['FilterEmail'] = 'SQL kifejezés a felhasználók e-mail cím alapú szűréséhez';
+$lang['FilterGroup'] = 'SQL kifejezés a felhasználók csoporttagság alapú szűréséhez';
+$lang['SortOrder'] = 'SQL kifejezés a felhasználók rendezéséhez';
+$lang['addUser'] = 'SQL utasítás új felhasználó hozzáadásához';
+$lang['addGroup'] = 'SQL utasítás új csoport hozzáadásához';
+$lang['addUserGroup'] = 'SQL utasítás egy felhasználó egy meglévő csoporthoz való hozzáadásához';
+$lang['delGroup'] = 'SQL utasítás egy csoport törléséhez';
+$lang['getUserID'] = 'SQL utasítás egy felhasználó elsődleges kulcsának lekérdezéséhez';
+$lang['delUser'] = 'SQL utasítás egy felhasználó törléséhez';
+$lang['delUserRefs'] = 'SQL utasítás egy felhasználó eltávolításához az összes csoportból';
+$lang['updateUser'] = 'SQL utasítás egy felhasználó profiljának frissítéséhez';
+$lang['UpdateLogin'] = 'SQL kifejezés a felhasználó azonosítójának frissítéséhez';
+$lang['UpdatePass'] = 'SQL kifejezés a felhasználó jelszavának frissítéséhez';
+$lang['UpdateEmail'] = 'SQL kifejezés a felhasználó e-mail címének frissítéséhez';
+$lang['UpdateName'] = 'SQL kifejezés a felhasználó nevének frissítéséhez';
+$lang['UpdateTarget'] = 'SQL kifejezés a felhasználó kiválasztásához az adatok frissítésekor';
+$lang['delUserGroup'] = 'SQL utasítás egy felhasználó eltávolításához egy adott csoportból';
+$lang['getGroupID'] = 'SQL utasítás egy csoport elsődleges kulcsának lekérdezéséhez';
diff --git a/lib/plugins/authpgsql/lang/pl/settings.php b/lib/plugins/authpgsql/lang/pl/settings.php
new file mode 100644
index 000000000..37afb252d
--- /dev/null
+++ b/lib/plugins/authpgsql/lang/pl/settings.php
@@ -0,0 +1,5 @@
+<?php
+/**
+ * Polish language file
+ *
+ */
diff --git a/lib/plugins/authpgsql/lang/pt-br/settings.php b/lib/plugins/authpgsql/lang/pt-br/settings.php
index d91e9c8e5..5ffe13465 100644
--- a/lib/plugins/authpgsql/lang/pt-br/settings.php
+++ b/lib/plugins/authpgsql/lang/pt-br/settings.php
@@ -3,6 +3,7 @@
* Brazilian Portuguese language file
*
* @author Victor Westmann <victor.westmann@gmail.com>
+ * @author Frederico Guimarães <frederico@teia.bio.br>
*/
$lang['server'] = 'Seu servidor PostgreSQL';
$lang['port'] = 'Sua porta do servidor PostgreSQL';
diff --git a/lib/plugins/authpgsql/lang/sv/settings.php b/lib/plugins/authpgsql/lang/sv/settings.php
index 27cb2601d..7da2e82c8 100644
--- a/lib/plugins/authpgsql/lang/sv/settings.php
+++ b/lib/plugins/authpgsql/lang/sv/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Smorkster Andersson smorkster@gmail.com
*/
$lang['server'] = 'Din PostgreSQL server';
diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php
index cbe9d336a..29529760c 100644
--- a/lib/plugins/config/admin.php
+++ b/lib/plugins/config/admin.php
@@ -268,7 +268,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin {
// fill in the plugin name if missing (should exist for plugins with settings)
if (!isset($this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'])) {
$this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'] =
- ucwords(str_replace('_', ' ', $plugin)).' '.$this->getLang('_plugin_sufix');
+ ucwords(str_replace('_', ' ', $plugin));
}
}
closedir($dh);
@@ -289,7 +289,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin {
// fill in the template name if missing (should exist for templates with settings)
if (!isset($this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'])) {
$this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'] =
- ucwords(str_replace('_', ' ', $tpl)).' '.$this->getLang('_template_sufix');
+ ucwords(str_replace('_', ' ', $tpl));
}
return true;
diff --git a/lib/plugins/config/lang/ar/lang.php b/lib/plugins/config/lang/ar/lang.php
index 76c155812..66bb4240f 100644
--- a/lib/plugins/config/lang/ar/lang.php
+++ b/lib/plugins/config/lang/ar/lang.php
@@ -31,8 +31,6 @@ $lang['_media'] = 'اعدادات الوسائط';
$lang['_notifications'] = 'اعدادات التنبيه';
$lang['_advanced'] = 'اعدادات متقدمة';
$lang['_network'] = 'اعدادات الشبكة';
-$lang['_plugin_sufix'] = 'اعدادات الملحقات';
-$lang['_template_sufix'] = 'اعدادات القوالب';
$lang['_msg_setting_undefined'] = 'لا بيانات إعدادات.';
$lang['_msg_setting_no_class'] = 'لا صنف إعدادات.';
$lang['_msg_setting_no_default'] = 'لا قيمة افتراضية.';
@@ -104,7 +102,6 @@ $lang['target____media'] = 'النافذة الهدف لروابط الو
$lang['target____windows'] = 'النافذة الهدف لروابط النوافذ';
$lang['mediarevisions'] = 'تفعيل إصدارات الوسائط؟';
$lang['refcheck'] = 'التحقق من مرجع الوسائط';
-$lang['refshow'] = 'عدد مراجع الوسائط لتعرض';
$lang['gdlib'] = 'اصدار مكتبة GD';
$lang['im_convert'] = 'المسار إلى اداة تحويل ImageMagick';
$lang['jpg_quality'] = 'دقة ضغط JPG (0-100)';
diff --git a/lib/plugins/config/lang/bg/lang.php b/lib/plugins/config/lang/bg/lang.php
index 43c961bfc..d0df38cae 100644
--- a/lib/plugins/config/lang/bg/lang.php
+++ b/lib/plugins/config/lang/bg/lang.php
@@ -42,12 +42,6 @@ $lang['_notifications'] = 'Настройки за известяване';
$lang['_syndication'] = 'Настройки на RSS емисиите';
$lang['_advanced'] = 'Допълнителни настройки';
$lang['_network'] = 'Мрежови настройки';
-// The settings group name for plugins and templates can be set with
-// plugin_settings_name and template_settings_name respectively. If one
-// of these lang properties is not set, the group name will be generated
-// from the plugin or template name and the localized suffix.
-$lang['_plugin_sufix'] = ' (приставка)';
-$lang['_template_sufix'] = ' (шаблон)';
/* --- Undefined Setting Messages --- */
$lang['_msg_setting_undefined'] = 'Няма метаданни за настройките.';
@@ -136,7 +130,6 @@ $lang['target____windows'] = 'Прозорец за препратки към
/* Media Settings */
$lang['mediarevisions'] = 'Да се пазят ли стари версии на качените файлове (Mediarevisions)?';
$lang['refcheck'] = 'Проверка за препратка към медия, преди да бъде изтрита';
-$lang['refshow'] = 'Брой на показваните медийни препратки';
$lang['gdlib'] = 'Версия на GD Lib';
$lang['im_convert'] = 'Път до инструмента за трансформация на ImageMagick';
$lang['jpg_quality'] = 'Качество на JPG компресията (0-100)';
diff --git a/lib/plugins/config/lang/ca-valencia/lang.php b/lib/plugins/config/lang/ca-valencia/lang.php
index 4a8c10895..b6ceadd59 100644
--- a/lib/plugins/config/lang/ca-valencia/lang.php
+++ b/lib/plugins/config/lang/ca-valencia/lang.php
@@ -30,8 +30,6 @@ $lang['_links'] = 'Ajusts de vínculs';
$lang['_media'] = 'Ajusts de mijos';
$lang['_advanced'] = 'Ajusts alvançats';
$lang['_network'] = 'Ajusts de ret';
-$lang['_plugin_sufix'] = 'Ajusts de plúgins';
-$lang['_template_sufix'] = '(ajusts de la plantilla)';
$lang['_msg_setting_undefined'] = 'Ajust sense informació.';
$lang['_msg_setting_no_class'] = 'Ajust sense classe.';
$lang['_msg_setting_no_default'] = 'Sense valor predeterminat.';
@@ -62,7 +60,6 @@ $lang['camelcase'] = 'Utilisar CamelCase per als vínculs';
$lang['deaccent'] = 'Depurar els noms de pàgines';
$lang['useheading'] = 'Utilisar el primer titular per al nom de pàgina';
$lang['refcheck'] = 'Comprovar referències a mijos';
-$lang['refshow'] = 'Número de referències a mijos a mostrar';
$lang['allowdebug'] = 'Permetre depurar (<b>¡desactivar quan no es necessite!</b>)';
$lang['usewordblock'] = 'Bloquejar spam basant-se en una llista de paraules';
$lang['indexdelay'] = 'Retart abans d\'indexar (seg.)';
diff --git a/lib/plugins/config/lang/ca/lang.php b/lib/plugins/config/lang/ca/lang.php
index 205d7aa6b..a53a859a0 100644
--- a/lib/plugins/config/lang/ca/lang.php
+++ b/lib/plugins/config/lang/ca/lang.php
@@ -33,8 +33,6 @@ $lang['_notifications'] = 'Paràmetres de notificació';
$lang['_syndication'] = 'Paràmetres de sindicació';
$lang['_advanced'] = 'Paràmetres avançats';
$lang['_network'] = 'Paràmetres de xarxa';
-$lang['_plugin_sufix'] = 'Paràmetres de connectors';
-$lang['_template_sufix'] = 'Paràmetres de plantilla';
$lang['_msg_setting_undefined'] = 'Falten metadades de paràmetre.';
$lang['_msg_setting_no_class'] = 'Falta classe de paràmetre.';
$lang['_msg_setting_no_default'] = 'No hi ha valor per defecte.';
@@ -102,7 +100,6 @@ $lang['target____extern'] = 'Finestra de destinació en enllaços externs';
$lang['target____media'] = 'Finestra de destinació en enllaços de mitjans';
$lang['target____windows'] = 'Finestra de destinació en enllaços de Windows';
$lang['refcheck'] = 'Comprova la referència en els fitxers de mitjans';
-$lang['refshow'] = 'Nombre de referències de mitjans per mostrar';
$lang['gdlib'] = 'Versió GD Lib';
$lang['im_convert'] = 'Camí de la utilitat convert d\'ImageMagick';
$lang['jpg_quality'] = 'Qualitat de compressió JPEG (0-100)';
diff --git a/lib/plugins/config/lang/cs/lang.php b/lib/plugins/config/lang/cs/lang.php
index d35ebec9b..289c458e5 100644
--- a/lib/plugins/config/lang/cs/lang.php
+++ b/lib/plugins/config/lang/cs/lang.php
@@ -42,8 +42,6 @@ $lang['_notifications'] = 'Nastavení upozornění';
$lang['_syndication'] = 'Nastavení syndikace';
$lang['_advanced'] = 'Pokročilá nastavení';
$lang['_network'] = 'Nastavení sítě';
-$lang['_plugin_sufix'] = 'Nastavení pluginů ';
-$lang['_template_sufix'] = 'Nastavení šablon';
$lang['_msg_setting_undefined'] = 'Chybí metadata položky.';
$lang['_msg_setting_no_class'] = 'Chybí třída položky.';
$lang['_msg_setting_no_default'] = 'Chybí výchozí hodnota položky.';
@@ -119,7 +117,6 @@ $lang['target____media'] = 'Cílové okno pro odkazy na média';
$lang['target____windows'] = 'Cílové okno pro odkazy na windows sdílení';
$lang['mediarevisions'] = 'Aktivovat revize souborů';
$lang['refcheck'] = 'Kontrolovat odkazy na média (před vymazáním)';
-$lang['refshow'] = 'Počet zobrazených odkazů na média';
$lang['gdlib'] = 'Verze GD knihovny';
$lang['im_convert'] = 'Cesta k nástroji convert z balíku ImageMagick';
$lang['jpg_quality'] = 'Kvalita komprese JPEG (0-100)';
diff --git a/lib/plugins/config/lang/da/lang.php b/lib/plugins/config/lang/da/lang.php
index 239a4986f..59a602ee5 100644
--- a/lib/plugins/config/lang/da/lang.php
+++ b/lib/plugins/config/lang/da/lang.php
@@ -38,8 +38,6 @@ $lang['_media'] = 'Medieindstillinger';
$lang['_notifications'] = 'Notificeringsindstillinger';
$lang['_advanced'] = 'Avancerede indstillinger';
$lang['_network'] = 'Netværksindstillinger';
-$lang['_plugin_sufix'] = 'Udvidelsesindstillinger';
-$lang['_template_sufix'] = 'Skabelonindstillinger';
$lang['_msg_setting_undefined'] = 'Ingen indstillingsmetadata.';
$lang['_msg_setting_no_class'] = 'Ingen indstillingsklasse.';
$lang['_msg_setting_no_default'] = 'Ingen standardværdi.';
@@ -110,7 +108,6 @@ $lang['target____media'] = 'Målvindue for mediehenvisninger';
$lang['target____windows'] = 'Målvindue til Windows-henvisninger';
$lang['mediarevisions'] = 'Akvtivér media udgaver?';
$lang['refcheck'] = 'Mediehenvisningerkontrol';
-$lang['refshow'] = 'Antal viste mediehenvisninger';
$lang['gdlib'] = 'Udgave af GD Lib';
$lang['im_convert'] = 'Sti til ImageMagick\'s omdannerværktøj';
$lang['jpg_quality'] = 'JPG komprimeringskvalitet (0-100)';
diff --git a/lib/plugins/config/lang/de-informal/lang.php b/lib/plugins/config/lang/de-informal/lang.php
index ac61e4c85..598c1a72d 100644
--- a/lib/plugins/config/lang/de-informal/lang.php
+++ b/lib/plugins/config/lang/de-informal/lang.php
@@ -10,6 +10,8 @@
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
* @author Mateng Schimmerlos <mateng@firemail.de>
+ * @author Volker Bödker <volker@boedker.de>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
$lang['menu'] = 'Konfiguration';
$lang['error'] = 'Konfiguration wurde nicht aktualisiert auf Grund eines ungültigen Wertes. Bitte überprüfe deine Änderungen und versuche es erneut.<br />Die/der ungültige(n) Wert(e) werden durch eine rote Umrandung hervorgehoben.';
@@ -19,24 +21,22 @@ $lang['locked'] = 'Die Konfigurationsdatei kann nicht aktualisier
$lang['danger'] = '**Achtung**: Eine Änderung dieser Einstellung kann dein Wiki und das Einstellungsmenü unerreichbar machen.';
$lang['warning'] = 'Achtung: Eine Änderungen dieser Option kann zu unbeabsichtigtem Verhalten führen.';
$lang['security'] = 'Sicherheitswarnung: Eine Änderungen dieser Option können ein Sicherheitsrisiko bedeuten.';
-$lang['_configuration_manager'] = 'Konfiguration';
-$lang['_header_dokuwiki'] = 'DokuWiki-Konfiguration';
-$lang['_header_plugin'] = 'Plugin-Konfiguration';
-$lang['_header_template'] = 'Template-Konfiguration';
+$lang['_configuration_manager'] = 'Konfigurations-Manager';
+$lang['_header_dokuwiki'] = 'DokuWiki';
+$lang['_header_plugin'] = 'Plugin';
+$lang['_header_template'] = 'Template';
$lang['_header_undefined'] = 'Unbekannte Werte';
-$lang['_basic'] = 'Grund-Konfiguration';
-$lang['_display'] = 'Darstellungs-Konfiguration';
-$lang['_authentication'] = 'Authentifizierung-Konfiguration';
-$lang['_anti_spam'] = 'Anti-Spam-Konfiguration';
-$lang['_editing'] = 'Bearbeitungs-Konfiguration';
-$lang['_links'] = 'Links-Konfiguration';
-$lang['_media'] = 'Medien-Konfiguration';
-$lang['_notifications'] = 'Benachrichtigungs-Konfiguration';
-$lang['_syndication'] = 'Syndication-Konfiguration (RSS)';
-$lang['_advanced'] = 'Erweiterte Konfiguration';
-$lang['_network'] = 'Netzwerk-Konfiguration';
-$lang['_plugin_sufix'] = 'Plugin-Konfiguration';
-$lang['_template_sufix'] = 'Template-Konfiguration';
+$lang['_basic'] = 'Basis';
+$lang['_display'] = 'Darstellung';
+$lang['_authentication'] = 'Authentifizierung';
+$lang['_anti_spam'] = 'Anti-Spam';
+$lang['_editing'] = 'Bearbeitung';
+$lang['_links'] = 'Links';
+$lang['_media'] = 'Medien';
+$lang['_notifications'] = 'Benachrichtigung';
+$lang['_syndication'] = 'Syndication (RSS)';
+$lang['_advanced'] = 'Erweitert';
+$lang['_network'] = 'Netzwerk';
$lang['_msg_setting_undefined'] = 'Keine Konfigurationsmetadaten.';
$lang['_msg_setting_no_class'] = 'Keine Konfigurationsklasse.';
$lang['_msg_setting_no_default'] = 'Kein Standardwert.';
@@ -45,7 +45,7 @@ $lang['start'] = 'Name der Startseite';
$lang['lang'] = 'Sprache';
$lang['template'] = 'Vorlage';
$lang['tagline'] = 'Tag-Linie (nur, wenn vom Template unterstützt)';
-$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt)), ein leeres Feld deaktiviert die Sidebar';
+$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt), ein leeres Feld deaktiviert die Sidebar';
$lang['license'] = 'Unter welcher Lizenz sollte Ihr Inhalt veröffentlicht werden?';
$lang['savedir'] = 'Ordner zum Speichern von Daten';
$lang['basedir'] = 'Installationsverzeichnis';
@@ -65,7 +65,7 @@ $lang['signature'] = 'Signatur';
$lang['showuseras'] = 'Was angezeigt werden soll, wenn der Benutzer, der zuletzt eine Seite bearbeitet hat, angezeigt wird';
$lang['toptoclevel'] = 'Inhaltsverzeichnis bei dieser Überschriftengröße beginnen';
$lang['tocminheads'] = 'Mindestanzahl der Überschriften die entscheidet, ob ein Inhaltsverzeichnis erscheinen soll';
-$lang['maxtoclevel'] = 'Maximale Überschriftsgröße für Inhaltsverzeichnis';
+$lang['maxtoclevel'] = 'Maximale Überschriftengröße für Inhaltsverzeichnis';
$lang['maxseclevel'] = 'Abschnitte bis zu dieser Stufe einzeln editierbar machen';
$lang['camelcase'] = 'CamelCase-Verlinkungen verwenden';
$lang['deaccent'] = 'Seitennamen bereinigen';
@@ -77,14 +77,15 @@ $lang['autopasswd'] = 'Automatisch erzeugte Passwörter';
$lang['authtype'] = 'Authentifizierungsmethode';
$lang['passcrypt'] = 'Passwortverschlüsselungsmethode';
$lang['defaultgroup'] = 'Standardgruppe';
-$lang['superuser'] = 'Administrator - Eine Gruppe oder Nutzer mit vollem Zugriff auf alle Seiten und Administrationswerkzeuge.';
-$lang['manager'] = 'Manager - Eine Gruppe oder Nutzer mit Zugriff auf einige Administrationswerkzeuge.';
+$lang['superuser'] = 'Administrator - Eine Gruppe oder Benutzer mit vollem Zugriff auf alle Seiten und Administrationswerkzeuge.';
+$lang['manager'] = 'Manager - Eine Gruppe oder Benutzer mit Zugriff auf einige Administrationswerkzeuge.';
$lang['profileconfirm'] = 'Änderungen am Benutzerprofil mit Passwort bestätigen';
$lang['rememberme'] = 'Permanente Login-Cookies erlauben (Auf diesem Computer eingeloggt bleiben)';
$lang['disableactions'] = 'Deaktiviere DokuWiki\'s Zugriffe';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Bestellen/Abbestellen';
$lang['disableactions_wikicode'] = 'Zeige Quelle/Exportiere Rohdaten';
+$lang['disableactions_profile_delete'] = 'Eigenes Benutzerprofil löschen';
$lang['disableactions_other'] = 'Weitere Aktionen (durch Komma getrennt)';
$lang['auth_security_timeout'] = 'Zeitüberschreitung bei der Authentifizierung (Sekunden)';
$lang['securecookie'] = 'Sollen Cookies, die via HTTPS gesetzt wurden nur per HTTPS versendet werden? Deaktiviere diese Option, wenn nur der Login deines Wikis mit SSL gesichert ist, aber das Betrachten des Wikis ungesichert geschieht.';
@@ -190,7 +191,7 @@ $lang['xsendfile_o_1'] = 'Proprietärer lighttpd-Header (vor Release 1.5
$lang['xsendfile_o_2'] = 'Standard X-Sendfile-Header';
$lang['xsendfile_o_3'] = 'Proprietärer Nginx X-Accel-Redirect-Header';
$lang['showuseras_o_loginname'] = 'Login-Name';
-$lang['showuseras_o_username'] = 'Voller Name des Nutzers';
+$lang['showuseras_o_username'] = 'Voller Name des Benutzers';
$lang['showuseras_o_email'] = 'E-Mail-Adresse des Benutzers (je nach Mailguard-Einstellung verschleiert)';
$lang['showuseras_o_email_link'] = 'E-Mail-Adresse des Benutzers als mailto:-Link';
$lang['useheading_o_0'] = 'Niemals';
diff --git a/lib/plugins/config/lang/de/lang.php b/lib/plugins/config/lang/de/lang.php
index dd29f8038..07eb4a750 100644
--- a/lib/plugins/config/lang/de/lang.php
+++ b/lib/plugins/config/lang/de/lang.php
@@ -27,24 +27,22 @@ $lang['locked'] = 'Die Konfigurationsdatei kann nicht geändert w
$lang['danger'] = 'Vorsicht: Die Änderung dieser Option könnte Ihr Wiki und das Konfigurationsmenü unzugänglich machen.';
$lang['warning'] = 'Hinweis: Die Änderung dieser Option könnte unbeabsichtigtes Verhalten hervorrufen.';
$lang['security'] = 'Sicherheitswarnung: Die Änderung dieser Option könnte ein Sicherheitsrisiko darstellen.';
-$lang['_configuration_manager'] = 'Konfiguration';
-$lang['_header_dokuwiki'] = 'DokuWiki-Konfiguration';
-$lang['_header_plugin'] = 'Plugin-Konfiguration';
-$lang['_header_template'] = 'Template-Konfiguration';
+$lang['_configuration_manager'] = 'Konfigurations-Manager';
+$lang['_header_dokuwiki'] = 'DokuWiki';
+$lang['_header_plugin'] = 'Plugin';
+$lang['_header_template'] = 'Template';
$lang['_header_undefined'] = 'Unbekannte Werte';
-$lang['_basic'] = 'Grund-Konfiguration';
-$lang['_display'] = 'Darstellungs-Konfiguration';
-$lang['_authentication'] = 'Authentifizierungs-Konfiguration';
-$lang['_anti_spam'] = 'Anti-Spam-Konfiguration';
-$lang['_editing'] = 'Bearbeitungs-Konfiguration';
-$lang['_links'] = 'Links-Konfiguration';
-$lang['_media'] = 'Medien-Konfiguration';
-$lang['_notifications'] = 'Benachrichtigungs-Konfiguration';
-$lang['_syndication'] = 'Syndication-Konfiguration (RSS)';
-$lang['_advanced'] = 'Erweiterte Konfiguration';
-$lang['_network'] = 'Netzwerk-Konfiguration';
-$lang['_plugin_sufix'] = 'Plugin-Konfiguration';
-$lang['_template_sufix'] = 'Template-Konfiguration';
+$lang['_basic'] = 'Basis';
+$lang['_display'] = 'Darstellung';
+$lang['_authentication'] = 'Authentifizierung';
+$lang['_anti_spam'] = 'Anti-Spam';
+$lang['_editing'] = 'Bearbeitung';
+$lang['_links'] = 'Links';
+$lang['_media'] = 'Medien';
+$lang['_notifications'] = 'Benachrichtigung';
+$lang['_syndication'] = 'Syndication (RSS)';
+$lang['_advanced'] = 'Erweitertet';
+$lang['_network'] = 'Netzwerk';
$lang['_msg_setting_undefined'] = 'Keine Konfigurationsmetadaten.';
$lang['_msg_setting_no_class'] = 'Keine Konfigurationsklasse.';
$lang['_msg_setting_no_default'] = 'Kein Standardwert.';
@@ -59,7 +57,7 @@ $lang['start'] = 'Startseitenname';
$lang['title'] = 'Titel des Wikis';
$lang['template'] = 'Designvorlage (Template)';
$lang['tagline'] = 'Tag-Linie (nur, wenn vom Template unterstützt)';
-$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt)), ein leeres Feld deaktiviert die Sidebar';
+$lang['sidebar'] = 'Name der Sidebar-Seite (nur, wenn vom Template unterstützt), ein leeres Feld deaktiviert die Sidebar';
$lang['license'] = 'Unter welcher Lizenz sollen Ihre Inhalte veröffentlicht werden?';
$lang['fullpath'] = 'Den kompletten Dateipfad im Footer anzeigen';
$lang['recent'] = 'Anzahl der Einträge in der Änderungsliste';
@@ -72,13 +70,13 @@ $lang['dformat'] = 'Datumsformat (Siehe PHP <a href="http://www.ph
$lang['signature'] = 'Signatur';
$lang['toptoclevel'] = 'Inhaltsverzeichnis bei dieser Überschriftengröße beginnen';
$lang['tocminheads'] = 'Mindestanzahl der Überschriften die entscheidet, ob ein Inhaltsverzeichnis erscheinen soll';
-$lang['maxtoclevel'] = 'Maximale Überschriftsgröße für Inhaltsverzeichnis';
+$lang['maxtoclevel'] = 'Maximale Überschriftengröße für Inhaltsverzeichnis';
$lang['maxseclevel'] = 'Abschnitte bis zu dieser Stufe einzeln editierbar machen';
$lang['camelcase'] = 'CamelCase-Verlinkungen verwenden';
$lang['deaccent'] = 'Seitennamen bereinigen';
$lang['useheading'] = 'Erste Überschrift als Seitennamen verwenden';
$lang['refcheck'] = 'Auf Verwendung beim Löschen von Media-Dateien testen';
-$lang['refshow'] = 'Wiev iele Verwendungsorte der Media-Datei zeigen';
+$lang['refshow'] = 'Wie viele Verwendungsorte der Media-Datei zeigen';
$lang['allowdebug'] = 'Debug-Ausgaben erlauben <b>Abschalten wenn nicht benötigt!</b>';
$lang['mediarevisions'] = 'Media-Revisionen (ältere Versionen) aktivieren?';
$lang['usewordblock'] = 'Spam-Blocking benutzen';
@@ -92,18 +90,19 @@ $lang['autopasswd'] = 'Passwort automatisch generieren';
$lang['authtype'] = 'Authentifizierungsmechanismus';
$lang['passcrypt'] = 'Verschlüsselungsmechanismus';
$lang['defaultgroup'] = 'Standardgruppe';
-$lang['superuser'] = 'Administrator - Eine Gruppe oder Nutzer mit vollem Zugriff auf alle Seiten und Administrationswerkzeuge.';
-$lang['manager'] = 'Manager - Eine Gruppe oder Nutzer mit Zugriff auf einige Administrationswerkzeuge.';
+$lang['superuser'] = 'Administrator - Eine Gruppe oder Benutzer mit vollem Zugriff auf alle Seiten und Administrationswerkzeuge.';
+$lang['manager'] = 'Manager - Eine Gruppe oder Benutzer mit Zugriff auf einige Administrationswerkzeuge.';
$lang['profileconfirm'] = 'Profiländerung nur nach Passwortbestätigung';
$lang['disableactions'] = 'DokuWiki-Aktionen deaktivieren';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Seiten-Abonnements';
$lang['disableactions_wikicode'] = 'Quelltext betrachten/exportieren';
+$lang['disableactions_profile_delete'] = 'Eigenes Benutzerprofil löschen';
$lang['disableactions_other'] = 'Andere Aktionen (durch Komma getrennt)';
$lang['sneaky_index'] = 'Standardmäßig zeigt DokuWiki alle Namensräume in der Übersicht. Wenn diese Option aktiviert wird, werden alle Namensräume, für die der Benutzer keine Lese-Rechte hat, nicht angezeigt. Dies kann unter Umständen dazu führen, das lesbare Unter-Namensräume nicht angezeigt werden und macht die Übersicht evtl. unbrauchbar in Kombination mit bestimmten ACL Einstellungen.';
$lang['auth_security_timeout'] = 'Authentifikations-Timeout (Sekunden)';
$lang['securecookie'] = 'Sollen Cookies, die via HTTPS gesetzt wurden nur per HTTPS versendet werden? Deaktivieren Sie diese Option, wenn nur der Login Ihres Wikis mit SSL gesichert ist, aber das Betrachten des Wikis ungesichert geschieht.';
-$lang['remote'] = 'Aktiviert den externen API-Zugang. Diese Option erlaubt es externen Anwendungen von außen auf die XML-RPC-Schnittstelle oder anderweitigen Schnittstellen zuzugreifen.';
+$lang['remote'] = 'Aktiviert den externen API-Zugang. Diese Option erlaubt es externen Anwendungen von außen auf die XML-RPC-Schnittstelle oder anderweitigen Schnittstellen zu zugreifen.';
$lang['remoteuser'] = 'Zugriff auf die externen Schnittstellen durch kommaseparierte Angabe von Benutzern oder Gruppen einschränken. Ein leeres Feld erlaubt Zugriff für jeden.';
$lang['updatecheck'] = 'Automatisch auf Updates und Sicherheitswarnungen prüfen? DokuWiki muss sich dafür mit update.dokuwiki.org verbinden.';
$lang['userewrite'] = 'URL rewriting';
@@ -118,18 +117,18 @@ $lang['cachetime'] = 'Maximale Cachespeicherung (Sekunden)';
$lang['locktime'] = 'Maximales Alter für Seitensperren (Sekunden)';
$lang['fetchsize'] = 'Maximale Größe (in Bytes), die fetch.php von extern herunterladen darf';
$lang['notify'] = 'Änderungsmitteilungen an diese E-Mail-Adresse versenden';
-$lang['registernotify'] = 'Information über neu registrierte Nutzer an diese E-Mail-Adresse senden';
+$lang['registernotify'] = 'Information über neu registrierte Benutzer an diese E-Mail-Adresse senden';
$lang['mailfrom'] = 'Absender-E-Mail-Adresse für automatische Mails';
$lang['mailprefix'] = 'Präfix für E-Mail-Betreff beim automatischen Versand von Benachrichtigungen';
$lang['htmlmail'] = 'Versendet optisch angenehmere, aber größere E-Mails im HTML-Format (multipart). Deaktivieren, um Text-Mails zu versenden.';
$lang['gzip_output'] = 'Seiten mit gzip komprimiert ausliefern';
$lang['gdlib'] = 'GD Lib Version';
-$lang['im_convert'] = 'Pfad zu ImageMagicks-Konvertierwerkzeug';
+$lang['im_convert'] = 'Pfad zum ImageMagicks-Konvertierwerkzeug';
$lang['jpg_quality'] = 'JPEG Kompressionsqualität (0-100)';
$lang['subscribers'] = 'E-Mail-Abos zulassen';
$lang['subscribe_time'] = 'Zeit nach der Zusammenfassungs- und Änderungslisten-E-Mails verschickt werden; Dieser Wert sollte kleiner als die in recent_days konfigurierte Zeit sein.';
$lang['compress'] = 'JavaScript und Stylesheets komprimieren';
-$lang['cssdatauri'] = 'Größe in Bytes, bis zu der Bilder in css-Dateien referenziert werden können, um HTTP-Anfragen zu minimieren. Diese Technik funktioniert nicht im IE 7 und älter! Empfohlene Einstellung: <code>400</code> to <code>600</code> Bytes. Setzen Sie die Einstellung auf <code>0</code> um die Funktion zu deaktivieren.';
+$lang['cssdatauri'] = 'Größe in Bytes, bis zu der Bilder in CSS-Dateien referenziert werden können, um HTTP-Anfragen zu minimieren. Diese Technik funktioniert nicht im IE 7 und älter! Empfohlene Einstellung: <code>400</code> to <code>600</code> Bytes. Setzen Sie die Einstellung auf <code>0</code> um die Funktion zu deaktivieren.';
$lang['hidepages'] = 'Seiten verstecken (Regulärer Ausdruck)';
$lang['send404'] = 'Bei nicht vorhandenen Seiten mit 404 Fehlercode antworten';
$lang['sitemap'] = 'Google Sitemap erzeugen (Tage)';
@@ -143,7 +142,7 @@ $lang['rss_type'] = 'XML-Feed-Format';
$lang['rss_linkto'] = 'XML-Feed verlinken auf';
$lang['rss_content'] = 'Welche Inhalte sollen im XML-Feed dargestellt werden?';
$lang['rss_update'] = 'XML-Feed Aktualisierungsintervall (Sekunden)';
-$lang['recent_days'] = 'Wieviele letzte Änderungen sollen einsehbar bleiben? (Tage)';
+$lang['recent_days'] = 'Wie viele letzte Änderungen sollen einsehbar bleiben? (Tage)';
$lang['rss_show_summary'] = 'Bearbeitungs-Zusammenfassung im XML-Feed anzeigen';
$lang['rss_media'] = 'Welche Änderungen sollen im XML-Feed angezeigt werden?';
$lang['target____wiki'] = 'Zielfenster für interne Links (target Attribut)';
@@ -151,17 +150,17 @@ $lang['target____interwiki'] = 'Zielfenster für InterWiki-Links (target Attri
$lang['target____extern'] = 'Zielfenster für Externe Links (target Attribut)';
$lang['target____media'] = 'Zielfenster für (Bild-)Dateien (target Attribut)';
$lang['target____windows'] = 'Zielfenster für Windows Freigaben (target Attribut)';
-$lang['dnslookups'] = 'DokuWiki löst die IP-Adressen von Benutzern zu deren Hostnamen auf. Wenn du einen langsamen, unbrauchbaren DNS-Server verwendest oder die Funktion nicht benötigst, dann sollte diese Option deaktivert sein.';
+$lang['dnslookups'] = 'DokuWiki löst die IP-Adressen von Benutzern zu deren Hostnamen auf. Wenn du einen langsamen, unbrauchbaren DNS-Server verwendest oder die Funktion nicht benötigst, dann sollte diese Option deaktiviert sein.';
$lang['proxy____host'] = 'Proxy-Server';
$lang['proxy____port'] = 'Proxy-Port';
-$lang['proxy____user'] = 'Proxy Nutzername';
+$lang['proxy____user'] = 'Proxy Benutzername';
$lang['proxy____pass'] = 'Proxy Passwort';
$lang['proxy____ssl'] = 'SSL bei Verbindung zum Proxy verwenden';
$lang['proxy____except'] = 'Regulärer Ausdruck um Adressen zu beschreiben, für die kein Proxy verwendet werden soll';
$lang['safemodehack'] = 'Safemodehack verwenden';
$lang['ftp____host'] = 'FTP-Host für Safemodehack';
$lang['ftp____port'] = 'FTP-Port für Safemodehack';
-$lang['ftp____user'] = 'FTP Nutzername für Safemodehack';
+$lang['ftp____user'] = 'FTP Benutzername für Safemodehack';
$lang['ftp____pass'] = 'FTP Passwort für Safemodehack';
$lang['ftp____root'] = 'FTP Wurzelverzeichnis für Safemodehack';
$lang['license_o_'] = 'Keine gewählt';
diff --git a/lib/plugins/config/lang/el/lang.php b/lib/plugins/config/lang/el/lang.php
index d2801e507..4c24e067e 100644
--- a/lib/plugins/config/lang/el/lang.php
+++ b/lib/plugins/config/lang/el/lang.php
@@ -39,8 +39,6 @@ $lang['_notifications'] = 'Ρυθμίσεις ενημερώσεων';
$lang['_syndication'] = 'Ρυθμίσεις σύνδεσης';
$lang['_advanced'] = 'Ρυθμίσεις για Προχωρημένους';
$lang['_network'] = 'Ρυθμίσεις Δικτύου';
-$lang['_plugin_sufix'] = 'Ρυθμίσεις Επεκτάσεων';
-$lang['_template_sufix'] = 'Ρυθμίσεις Προτύπων παρουσίασης';
$lang['_msg_setting_undefined'] = 'Δεν έχουν οριστεί metadata.';
$lang['_msg_setting_no_class'] = 'Δεν έχει οριστεί κλάση.';
$lang['_msg_setting_no_default'] = 'Δεν υπάρχει τιμή εξ ορισμού.';
@@ -111,7 +109,6 @@ $lang['target____media'] = 'Παράθυρο-στόχος για συνδ
$lang['target____windows'] = 'Παράθυρο-στόχος για συνδέσμους σε Windows shares';
$lang['mediarevisions'] = 'Ενεργοποίηση Mediarevisions;';
$lang['refcheck'] = 'Πριν τη διαγραφή ενός αρχείου να ελέγχεται η ύπαρξη σελίδων που το χρησιμοποιούν';
-$lang['refshow'] = 'Εμφανιζόμενος αριθμός σελίδων που χρησιμοποιούν ένα αρχείο';
$lang['gdlib'] = 'Έκδοση βιβλιοθήκης GD';
$lang['im_convert'] = 'Διαδρομή προς το εργαλείο μετατροπής εικόνων του ImageMagick';
$lang['jpg_quality'] = 'Ποιότητα συμπίεσης JPG (0-100)';
diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php
index 83c843b3a..67d3ce51f 100644
--- a/lib/plugins/config/lang/en/lang.php
+++ b/lib/plugins/config/lang/en/lang.php
@@ -4,6 +4,7 @@
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Christopher Smith <chris@jalakai.co.uk>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
// for admin plugins, the menu prompt to be displayed in the admin menu
@@ -23,29 +24,23 @@ $lang['security'] = 'Security Warning: Changing this option could present a se
/* --- Config Setting Headers --- */
$lang['_configuration_manager'] = 'Configuration Manager'; //same as heading in intro.txt
-$lang['_header_dokuwiki'] = 'DokuWiki Settings';
-$lang['_header_plugin'] = 'Plugin Settings';
-$lang['_header_template'] = 'Template Settings';
+$lang['_header_dokuwiki'] = 'DokuWiki';
+$lang['_header_plugin'] = 'Plugin';
+$lang['_header_template'] = 'Template';
$lang['_header_undefined'] = 'Undefined Settings';
/* --- Config Setting Groups --- */
-$lang['_basic'] = 'Basic Settings';
-$lang['_display'] = 'Display Settings';
-$lang['_authentication'] = 'Authentication Settings';
-$lang['_anti_spam'] = 'Anti-Spam Settings';
-$lang['_editing'] = 'Editing Settings';
-$lang['_links'] = 'Link Settings';
-$lang['_media'] = 'Media Settings';
-$lang['_notifications'] = 'Notification Settings';
-$lang['_syndication'] = 'Syndication Settings';
-$lang['_advanced'] = 'Advanced Settings';
-$lang['_network'] = 'Network Settings';
-// The settings group name for plugins and templates can be set with
-// plugin_settings_name and template_settings_name respectively. If one
-// of these lang properties is not set, the group name will be generated
-// from the plugin or template name and the localized suffix.
-$lang['_plugin_sufix'] = 'Plugin Settings';
-$lang['_template_sufix'] = 'Template Settings';
+$lang['_basic'] = 'Basic';
+$lang['_display'] = 'Display';
+$lang['_authentication'] = 'Authentication';
+$lang['_anti_spam'] = 'Anti-Spam';
+$lang['_editing'] = 'Editing';
+$lang['_links'] = 'Links';
+$lang['_media'] = 'Media';
+$lang['_notifications'] = 'Notification';
+$lang['_syndication'] = 'Syndication (RSS)';
+$lang['_advanced'] = 'Advanced';
+$lang['_network'] = 'Network';
/* --- Undefined Setting Messages --- */
$lang['_msg_setting_undefined'] = 'No setting metadata.';
@@ -104,6 +99,7 @@ $lang['disableactions'] = 'Disable DokuWiki actions';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Subscribe/Unsubscribe';
$lang['disableactions_wikicode'] = 'View source/Export Raw';
+$lang['disableactions_profile_delete'] = 'Delete Own Account';
$lang['disableactions_other'] = 'Other actions (comma separated)';
$lang['auth_security_timeout'] = 'Authentication Security Timeout (seconds)';
$lang['securecookie'] = 'Should cookies set via HTTPS only be sent via HTTPS by the browser? Disable this option when only the login of your wiki is secured with SSL but browsing the wiki is done unsecured.';
@@ -134,7 +130,6 @@ $lang['target____windows'] = 'Target window for windows links';
/* Media Settings */
$lang['mediarevisions'] = 'Enable Mediarevisions?';
$lang['refcheck'] = 'Check if a media file is still in use before deleting it';
-$lang['refshow'] = 'Number of media references to show when the above setting is enabled';
$lang['gdlib'] = 'GD Lib version';
$lang['im_convert'] = 'Path to ImageMagick\'s convert tool';
$lang['jpg_quality'] = 'JPG compression quality (0-100)';
diff --git a/lib/plugins/config/lang/eo/lang.php b/lib/plugins/config/lang/eo/lang.php
index 36f865c28..440d771dc 100644
--- a/lib/plugins/config/lang/eo/lang.php
+++ b/lib/plugins/config/lang/eo/lang.php
@@ -36,8 +36,6 @@ $lang['_notifications'] = 'Sciigaj agordoj';
$lang['_syndication'] = 'Kunhavigaj agordoj';
$lang['_advanced'] = 'Fakaj difinoj';
$lang['_network'] = 'Difinoj por reto';
-$lang['_plugin_sufix'] = 'Difinoj por kromaĵoj';
-$lang['_template_sufix'] = 'Difinoj por ŝablonoj';
$lang['_msg_setting_undefined'] = 'Neniu difinanta metadatumaro.';
$lang['_msg_setting_no_class'] = 'Neniu difinanta klaso.';
$lang['_msg_setting_no_default'] = 'Neniu apriora valoro.';
@@ -108,7 +106,6 @@ $lang['target____media'] = 'Parametro "target" (celo) por aŭdvidaĵaj lig
$lang['target____windows'] = 'Parametro "target" (celo) por Vindozaj ligiloj';
$lang['mediarevisions'] = 'Ĉu ebligi reviziadon de aŭdvidaĵoj?';
$lang['refcheck'] = 'Kontrolo por referencoj al aŭdvidaĵoj';
-$lang['refshow'] = 'Nombro da referencoj al aŭdvidaĵoj por montri';
$lang['gdlib'] = 'Versio de GD-Lib';
$lang['im_convert'] = 'Pado al la konvertilo de ImageMagick';
$lang['jpg_quality'] = 'Kompaktiga kvalito de JPG (0-100)';
diff --git a/lib/plugins/config/lang/es/lang.php b/lib/plugins/config/lang/es/lang.php
index 5d03efb60..847b326a8 100644
--- a/lib/plugins/config/lang/es/lang.php
+++ b/lib/plugins/config/lang/es/lang.php
@@ -49,8 +49,6 @@ $lang['_notifications'] = 'Configuración de notificaciones';
$lang['_syndication'] = 'Configuración de sindicación';
$lang['_advanced'] = 'Parámetros Avanzados';
$lang['_network'] = 'Parámetros de Red';
-$lang['_plugin_sufix'] = 'Parámetros de Plugins';
-$lang['_template_sufix'] = 'Parámetros de Plantillas';
$lang['_msg_setting_undefined'] = 'Sin parámetros de metadata.';
$lang['_msg_setting_no_class'] = 'Sin clase establecida.';
$lang['_msg_setting_no_default'] = 'Sin valor por defecto.';
@@ -121,7 +119,6 @@ $lang['target____media'] = 'Ventana para enlaces a medios';
$lang['target____windows'] = 'Ventana para enlaces a ventanas';
$lang['mediarevisions'] = '¿Habilitar Mediarevisions?';
$lang['refcheck'] = 'Control de referencia a medios';
-$lang['refshow'] = 'Número de referencias a medios a mostrar';
$lang['gdlib'] = 'Versión de GD Lib';
$lang['im_convert'] = 'Ruta a la herramienta de conversión de ImageMagick';
$lang['jpg_quality'] = 'Calidad de compresión de JPG (0-100)';
diff --git a/lib/plugins/config/lang/et/lang.php b/lib/plugins/config/lang/et/lang.php
index 27f2e87ac..cce679f31 100644
--- a/lib/plugins/config/lang/et/lang.php
+++ b/lib/plugins/config/lang/et/lang.php
@@ -16,8 +16,6 @@ $lang['_links'] = 'Lingi seaded';
$lang['_media'] = 'Meedia seaded';
$lang['_advanced'] = 'Laiendatud seaded';
$lang['_network'] = 'Võrgu seaded';
-$lang['_plugin_sufix'] = 'Plugina seaded';
-$lang['_template_sufix'] = 'Kujunduse seaded';
$lang['title'] = 'Wiki pealkiri';
$lang['template'] = 'Kujundus';
$lang['recent'] = 'Viimased muudatused';
diff --git a/lib/plugins/config/lang/eu/lang.php b/lib/plugins/config/lang/eu/lang.php
index 4dd3ff351..2b67a49ed 100644
--- a/lib/plugins/config/lang/eu/lang.php
+++ b/lib/plugins/config/lang/eu/lang.php
@@ -30,8 +30,6 @@ $lang['_notifications'] = 'Abisuen ezarpenak';
$lang['_syndication'] = 'Sindikazio ezarpenak';
$lang['_advanced'] = 'Ezarpen Aurreratuak';
$lang['_network'] = 'Sare Ezarpenak';
-$lang['_plugin_sufix'] = 'Plugin Ezarpenak';
-$lang['_template_sufix'] = 'Txantiloi Ezarpenak';
$lang['_msg_setting_undefined'] = 'Ezarpen metadaturik ez.';
$lang['_msg_setting_no_class'] = 'Ezarpen klaserik ez.';
$lang['_msg_setting_no_default'] = 'Balio lehenetsirik ez.';
@@ -97,7 +95,6 @@ $lang['target____media'] = 'Multimedia estekentzat helburu leihoa';
$lang['target____windows'] = 'Leihoen estekentzat helburu leihoa';
$lang['mediarevisions'] = 'Media rebisioak gaitu?';
$lang['refcheck'] = 'Multimedia erreferentzia kontrolatu';
-$lang['refshow'] = 'Erakusteko multimedia erreferentzia kopurua';
$lang['gdlib'] = 'GD Lib bertsioa';
$lang['im_convert'] = 'ImageMagick-en aldaketa tresnara bidea';
$lang['jpg_quality'] = 'JPG konprimitze kalitatea (0-100)';
diff --git a/lib/plugins/config/lang/fa/lang.php b/lib/plugins/config/lang/fa/lang.php
index 34c76780c..dd97f716e 100644
--- a/lib/plugins/config/lang/fa/lang.php
+++ b/lib/plugins/config/lang/fa/lang.php
@@ -34,8 +34,6 @@ $lang['_notifications'] = 'تنظیمات آگاه سازی';
$lang['_syndication'] = 'تنظیمات پیوند';
$lang['_advanced'] = 'تنظیمات پیشرفته';
$lang['_network'] = 'تنظیمات شبکه';
-$lang['_plugin_sufix'] = 'تنظیمات افزونه';
-$lang['_template_sufix'] = 'تنظیمات قالب';
$lang['_msg_setting_undefined'] = 'داده‌نمایی برای تنظیمات وجود ندارد';
$lang['_msg_setting_no_class'] = 'هیچ دسته‌ای برای تنظیمات وجود ندارد.';
$lang['_msg_setting_no_default'] = 'بدون مقدار پیش‌فرض';
@@ -106,7 +104,6 @@ $lang['target____media'] = 'پنجره‌ی هدف در پیوند‌ها
$lang['target____windows'] = 'پنجره‌ی هدف در پیوند‌های پنجره‌ای';
$lang['mediarevisions'] = 'تجدید نظر رسانه ، فعال؟';
$lang['refcheck'] = 'بررسی کردن مرجع رسانه‌ها';
-$lang['refshow'] = 'تعداد مراجعی که برای یک رسانه نمایش داده شود';
$lang['gdlib'] = 'نگارش کتاب‌خانه‌ی GD';
$lang['im_convert'] = 'مسیر ابزار convert از برنامه‌ی ImageMagick';
$lang['jpg_quality'] = 'کیفیت فشرده سازی JPEG (از 0 تا 100)';
diff --git a/lib/plugins/config/lang/fi/lang.php b/lib/plugins/config/lang/fi/lang.php
index 990852f99..9fd3fba24 100644
--- a/lib/plugins/config/lang/fi/lang.php
+++ b/lib/plugins/config/lang/fi/lang.php
@@ -33,8 +33,6 @@ $lang['_notifications'] = 'Ilmoitus-asetukset';
$lang['_syndication'] = 'Syöteasetukset';
$lang['_advanced'] = 'Lisäasetukset';
$lang['_network'] = 'Verkkoasetukset';
-$lang['_plugin_sufix'] = 'liitännäisen asetukset';
-$lang['_template_sufix'] = 'Sivumallin asetukset';
$lang['_msg_setting_undefined'] = 'Ei asetusten metadataa.';
$lang['_msg_setting_no_class'] = 'Ei asetusluokkaa.';
$lang['_msg_setting_no_default'] = 'Ei oletusarvoa';
@@ -105,7 +103,6 @@ $lang['target____media'] = 'Kohdeikkuna media-linkeissä';
$lang['target____windows'] = 'Kohdeikkuna Windows-linkeissä';
$lang['mediarevisions'] = 'Otetaan käyttään Media-versiointi';
$lang['refcheck'] = 'Mediaviitteen tarkistus';
-$lang['refshow'] = 'Montako mediaviitettä näytetään';
$lang['gdlib'] = 'GD Lib versio';
$lang['im_convert'] = 'ImageMagick-muunnostyökalun polku';
$lang['jpg_quality'] = 'JPG pakkauslaatu (0-100)';
diff --git a/lib/plugins/config/lang/fr/lang.php b/lib/plugins/config/lang/fr/lang.php
index f9e89f603..e92144b22 100644
--- a/lib/plugins/config/lang/fr/lang.php
+++ b/lib/plugins/config/lang/fr/lang.php
@@ -46,8 +46,6 @@ $lang['_notifications'] = 'Paramètres de notification';
$lang['_syndication'] = 'Paramètres de syndication';
$lang['_advanced'] = 'Paramètres avancés';
$lang['_network'] = 'Paramètres réseaux';
-$lang['_plugin_sufix'] = 'Paramètres d\'extension';
-$lang['_template_sufix'] = 'Paramètres de modèle';
$lang['_msg_setting_undefined'] = 'Pas de définition de métadonnées';
$lang['_msg_setting_no_class'] = 'Pas de définition de paramètres.';
$lang['_msg_setting_no_default'] = 'Pas de valeur par défaut.';
@@ -118,7 +116,6 @@ $lang['target____media'] = 'Cible pour liens média';
$lang['target____windows'] = 'Cible pour liens vers partages Windows';
$lang['mediarevisions'] = 'Activer les révisions (gestion de versions) des médias';
$lang['refcheck'] = 'Vérifier si un média est toujours utilisé avant de le supprimer';
-$lang['refshow'] = 'Nombre de références de média à montrer lorsque le paramètre précédent est actif';
$lang['gdlib'] = 'Version de la librairie GD';
$lang['im_convert'] = 'Chemin vers l\'outil de conversion ImageMagick';
$lang['jpg_quality'] = 'Qualité de la compression JPEG (0-100)';
diff --git a/lib/plugins/config/lang/gl/lang.php b/lib/plugins/config/lang/gl/lang.php
index 21fe17452..44942cc7c 100644
--- a/lib/plugins/config/lang/gl/lang.php
+++ b/lib/plugins/config/lang/gl/lang.php
@@ -32,8 +32,6 @@ $lang['_notifications'] = 'Opcións de Notificación';
$lang['_syndication'] = 'Opcións de Sindicación';
$lang['_advanced'] = 'Configuración Avanzada';
$lang['_network'] = 'Configuración de Rede';
-$lang['_plugin_sufix'] = 'Configuración de Extensións';
-$lang['_template_sufix'] = 'Configuración de Sobreplanta';
$lang['_msg_setting_undefined'] = 'Non hai configuración de metadatos.';
$lang['_msg_setting_no_class'] = 'Non hai configuración de clase.';
$lang['_msg_setting_no_default'] = 'Non hai valor predeterminado.';
@@ -104,7 +102,6 @@ $lang['target____media'] = 'Fiestra de destino para as ligazóns de media'
$lang['target____windows'] = 'Fiestra de destino para as ligazóns de fiestras';
$lang['mediarevisions'] = 'Habilitar revisións dos arquivos-media?';
$lang['refcheck'] = 'Comprobar a referencia media';
-$lang['refshow'] = 'Número de referencias media a amosar';
$lang['gdlib'] = 'Versión da Libraría GD';
$lang['im_convert'] = 'Ruta deica a ferramenta de conversión ImageMagick';
$lang['jpg_quality'] = 'Calidade de compresión dos JPG (0-100)';
diff --git a/lib/plugins/config/lang/he/lang.php b/lib/plugins/config/lang/he/lang.php
index b200082c9..bddfd90af 100644
--- a/lib/plugins/config/lang/he/lang.php
+++ b/lib/plugins/config/lang/he/lang.php
@@ -30,8 +30,6 @@ $lang['_links'] = 'הגדרות קישורים';
$lang['_media'] = 'הגדרות מדיה';
$lang['_advanced'] = 'הגדרות מתקדמות';
$lang['_network'] = 'הגדרות רשת';
-$lang['_plugin_sufix'] = 'הגדרות תוסף';
-$lang['_template_sufix'] = 'הגדרות תבנית';
$lang['_msg_setting_undefined'] = 'אין מידע-על להגדרה.';
$lang['_msg_setting_no_class'] = 'אין קבוצה להגדרה.';
$lang['_msg_setting_no_default'] = 'אין ערך ברירת מחדל.';
@@ -60,7 +58,6 @@ $lang['camelcase'] = 'השתמש בראשיות גדולות לקי
$lang['deaccent'] = 'נקה שמות דפים';
$lang['useheading'] = 'השתמש בכותרת הראשונה לשם הדף';
$lang['refcheck'] = 'בדוק שיוך מדיה';
-$lang['refshow'] = 'מספר שיוכי המדיה שיוצגו';
$lang['allowdebug'] = 'אפשר דיבוג <b>יש לבטל אם אין צורך!</b>';
$lang['usewordblock'] = 'חסימת דואר זבל לפי רשימת מילים';
$lang['indexdelay'] = 'השהיה בטרם הכנסה לאינדקס (שניות)';
diff --git a/lib/plugins/config/lang/hu/lang.php b/lib/plugins/config/lang/hu/lang.php
index a1de94160..6f774bfac 100644
--- a/lib/plugins/config/lang/hu/lang.php
+++ b/lib/plugins/config/lang/hu/lang.php
@@ -8,8 +8,9 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
-$lang['menu'] = 'Beállító Központ';
+$lang['menu'] = 'Beállítóközpont';
$lang['error'] = 'Helytelen érték miatt a módosítások nem mentődtek. Nézd át a módosításokat, és ments újra.
<br />A helytelen érték(ek)et piros kerettel jelöljük.';
$lang['updated'] = 'A módosítások sikeresen beállítva.';
@@ -19,7 +20,7 @@ Nézd meg, hogy a fájl neve és jogosultságai helyesen vannak-e beállítva!';
$lang['danger'] = 'Figyelem: ezt a beállítást megváltoztatva a konfigurációs menü hozzáférhetetlenné válhat.';
$lang['warning'] = 'Figyelmeztetés: a beállítás megváltoztatása nem kívánt viselkedést okozhat.';
$lang['security'] = 'Biztonsági figyelmeztetés: a beállítás megváltoztatása biztonsági veszélyforrást okozhat.';
-$lang['_configuration_manager'] = 'Beállító Központ';
+$lang['_configuration_manager'] = 'Beállítóközpont';
$lang['_header_dokuwiki'] = 'DokuWiki beállítások';
$lang['_header_plugin'] = 'Bővítmények beállításai';
$lang['_header_template'] = 'Sablon beállítások';
@@ -30,33 +31,37 @@ $lang['_authentication'] = 'Azonosítás beállításai';
$lang['_anti_spam'] = 'Anti-Spam beállítások';
$lang['_editing'] = 'Szerkesztési beállítások';
$lang['_links'] = 'Link beállítások';
-$lang['_media'] = 'Media beállítások';
+$lang['_media'] = 'Média beállítások';
+$lang['_notifications'] = 'Értesítési beállítások';
+$lang['_syndication'] = 'Hírfolyam beállítások';
$lang['_advanced'] = 'Haladó beállítások';
$lang['_network'] = 'Hálózati beállítások';
-$lang['_plugin_sufix'] = 'Bővítmények beállításai';
-$lang['_template_sufix'] = 'Sablon beállítások';
-$lang['_msg_setting_undefined'] = 'Nincs beállított meta-adat.';
+$lang['_msg_setting_undefined'] = 'Nincs beállított metaadat.';
$lang['_msg_setting_no_class'] = 'Nincs beállított osztály.';
$lang['_msg_setting_no_default'] = 'Nincs alapértelmezett érték.';
-$lang['fmode'] = 'Fájl létrehozási maszk';
-$lang['dmode'] = 'Könyvtár létrehozási maszk';
-$lang['lang'] = 'Nyelv';
-$lang['basedir'] = 'Báziskönyvtár';
-$lang['baseurl'] = 'Alap URL';
-$lang['savedir'] = 'Könyvtár az adatok mentésére';
+$lang['title'] = 'Wiki neve';
$lang['start'] = 'Kezdőoldal neve';
-$lang['title'] = 'Wiki címe';
+$lang['lang'] = 'Nyelv';
$lang['template'] = 'Sablon';
+$lang['tagline'] = 'Lábléc (ha a sablon támogatja)';
+$lang['sidebar'] = 'Oldalsáv oldal neve (ha a sablon támogatja), az üres mező letiltja az oldalsáv megjelenítését';
$lang['license'] = 'Milyen licenc alatt érhető el a tartalom?';
-$lang['fullpath'] = 'Az oldalak teljes útvonalának mutatása a láblécben';
+$lang['savedir'] = 'Könyvtár az adatok mentésére';
+$lang['basedir'] = 'Báziskönyvtár (pl. <code>/dokuwiki/</code>). Hagyd üresen az automatikus beállításhoz!';
+$lang['baseurl'] = 'Báziscím (pl. <code>http://www.yourserver.com</code>). Hagyd üresen az automatikus beállításhoz!';
+$lang['cookiedir'] = 'Sütik címe. Hagy üresen a báziscím használatához!';
+$lang['dmode'] = 'Könyvtár létrehozási maszk';
+$lang['fmode'] = 'Fájl létrehozási maszk';
+$lang['allowdebug'] = 'Debug üzemmód <b>Kapcsold ki, hacsak biztos nem szükséges!</b>';
$lang['recent'] = 'Utolsó változatok száma';
+$lang['recent_days'] = 'Hány napig tartsuk meg a korábbi változatokat?';
$lang['breadcrumbs'] = 'Nyomvonal elemszám';
$lang['youarehere'] = 'Hierarchikus nyomvonal';
+$lang['fullpath'] = 'Az oldalak teljes útvonalának mutatása a láblécben';
$lang['typography'] = 'Legyen-e tipográfiai csere';
-$lang['htmlok'] = 'Beágyazott HTML engedélyezése';
-$lang['phpok'] = 'Beágyazott PHP engedélyezése';
$lang['dformat'] = 'Dátum formázás (lásd a PHP <a href="http://www.php.net/strftime">strftime</a> függvényt)';
$lang['signature'] = 'Aláírás';
+$lang['showuseras'] = 'A felhasználó melyik adatát mutassunk az utolsó változtatás adatainál?';
$lang['toptoclevel'] = 'A tartalomjegyzék felső szintje';
$lang['tocminheads'] = 'Legalább ennyi címsor hatására generálódjon tartalomjegyzék';
$lang['maxtoclevel'] = 'A tartalomjegyzék mélysége';
@@ -64,75 +69,80 @@ $lang['maxseclevel'] = 'A szakasz-szerkesztés maximális szintje';
$lang['camelcase'] = 'CamelCase használata hivatkozásként';
$lang['deaccent'] = 'Oldalnevek ékezettelenítése';
$lang['useheading'] = 'Az első fejléc legyen az oldalnév';
-$lang['refcheck'] = 'Médiafájlok hivatkozásainak ellenőrzése';
-$lang['refshow'] = 'Média-hivatkozások maximálisan mutatott szintje';
-$lang['allowdebug'] = 'Debug üzemmód <b>Kapcsold ki, hacsak biztos nem szükséges!</b>';
-$lang['usewordblock'] = 'Szólista alapú spam-szűrés';
-$lang['indexdelay'] = 'Várakozás indexelés előtt (másodperc)';
-$lang['relnofollow'] = 'rel="nofollow" beállítás használata külső hivatkozásokra';
-$lang['mailguard'] = 'Email címek olvashatatlanná tétele címgyűjtők számára';
-$lang['iexssprotect'] = 'Feltöltött fájlok ellenőrzése kártékony JavaScript vagy HTML kód elkerülésére';
-$lang['showuseras'] = 'A felhasználó melyik adatát mutassunk az utolsó változtatás adatainál?';
+$lang['sneaky_index'] = 'Alapértelmezetten minden névtér látszik a DokuWiki áttekintő (index) oldalán. Ezen opció bekapcsolása után azok nem jelennek meg, melyekhez a felhasználónak nincs olvasás joga. De ezzel eltakarhatunk egyébként elérhető al-névtereket is, így bizonyos ACL beállításoknál használhatatlan indexet eredményez ez a beállítás.';
+$lang['hidepages'] = 'Az itt megadott oldalak elrejtése (reguláris kifejezés)';
$lang['useacl'] = 'Hozzáférési listák (ACL) használata';
$lang['autopasswd'] = 'Jelszavak automatikus generálása';
$lang['authtype'] = 'Authentikációs háttérrendszer';
$lang['passcrypt'] = 'Jelszó titkosítási módszer';
$lang['defaultgroup'] = 'Alapértelmezett csoport';
-$lang['superuser'] = 'Szuper-felhasználó (Wiki-gazda) - csoport vagy felhasználó, aki teljes hozzáférési joggal rendelkezik az oldalakhoz és funkciókhoz, a hozzáférési jogosultságoktól függetlenül';
+$lang['superuser'] = 'Adminisztrátor - csoport vagy felhasználó, aki teljes hozzáférési joggal rendelkezik az oldalakhoz és funkciókhoz, a hozzáférési jogosultságoktól függetlenül';
$lang['manager'] = 'Menedzser - csoport vagy felhasználó, aki bizonyos menedzsment funkciókhoz hozzáfér';
$lang['profileconfirm'] = 'Beállítások változtatásának megerősítése jelszóval';
+$lang['rememberme'] = 'Állandó sütik engedélyezése (az "emlékezz rám" funkcióhoz)';
$lang['disableactions'] = 'Bizonyos DokuWiki tevékenységek (action) tiltása';
$lang['disableactions_check'] = 'Ellenőrzés';
$lang['disableactions_subscription'] = 'Feliratkozás/Leiratkozás';
$lang['disableactions_wikicode'] = 'Forrás megtekintése/Nyers adat exportja';
$lang['disableactions_other'] = 'Egyéb tevékenységek (vesszővel elválasztva)';
-$lang['sneaky_index'] = 'Alapértelmezetten minden névtér látszik a DokuWiki áttekintő (index) oldalán. Ezen opció bekapcsolása után azok nem jelennek meg, melyekhez a felhasználónak nincs olvasás joga. De ezzel eltakarhatunk egyébként elérhető al-névtereket is, így bizonyos ACL beállításoknál használhatatlan indexet eredményez ez a beállítás.';
$lang['auth_security_timeout'] = 'Authentikációs biztonsági időablak (másodperc)';
$lang['securecookie'] = 'A böngészők a HTTPS felett beállított sütijüket csak HTTPS felett küldhetik? Kapcsoljuk ki ezt az opciót, ha csak a bejelentkezést védjük SSL-lel, a wiki tartalmának böngészése nyílt forgalommal történik.';
+$lang['remote'] = 'Távoli API engedélyezése. Ezzel más alkalmazások XML-RPC-n keresztül hozzáférhetnek a wikihez.';
+$lang['remoteuser'] = 'A távoli API hozzáférés korlátozása a következő felhasználókra vagy csoportokra. Hagyd üresen, ha mindenki számára elérhető!';
+$lang['usewordblock'] = 'Szólista alapú spam-szűrés';
+$lang['relnofollow'] = 'rel="nofollow" beállítás használata külső hivatkozásokra';
+$lang['indexdelay'] = 'Várakozás indexelés előtt (másodperc)';
+$lang['mailguard'] = 'Email címek olvashatatlanná tétele címgyűjtők számára';
+$lang['iexssprotect'] = 'Feltöltött fájlok ellenőrzése kártékony JavaScript vagy HTML kód elkerülésére';
+$lang['usedraft'] = 'Piszkozat automatikus mentése szerkesztés alatt';
+$lang['htmlok'] = 'Beágyazott HTML engedélyezése';
+$lang['phpok'] = 'Beágyazott PHP engedélyezése';
+$lang['locktime'] = 'Oldal-zárolás maximális időtartama (másodperc)';
+$lang['cachetime'] = 'A gyorsítótár maximális élettartama (másodperc)';
+$lang['target____wiki'] = 'Cél-ablak belső hivatkozásokhoz';
+$lang['target____interwiki'] = 'Cél-ablak interwiki hivatkozásokhoz';
+$lang['target____extern'] = 'Cél-ablak külső hivatkozásokhoz';
+$lang['target____media'] = 'Cél-ablak média-fájl hivatkozásokhoz';
+$lang['target____windows'] = 'Cél-ablak Windows hivatkozásokhoz';
+$lang['mediarevisions'] = 'Médiafájlok verziókövetésének engedélyezése';
+$lang['refcheck'] = 'Médiafájlok hivatkozásainak ellenőrzése';
+$lang['gdlib'] = 'GD Lib verzió';
+$lang['im_convert'] = 'Útvonal az ImageMagick csomag convert parancsához';
+$lang['jpg_quality'] = 'JPG tömörítés minősége (0-100)';
+$lang['fetchsize'] = 'Maximális méret (bájtban), amit a fetch.php letölthet kívülről';
+$lang['subscribers'] = 'Oldalváltozás-listára feliratkozás engedélyezése';
+$lang['subscribe_time'] = 'Az értesítések kiküldésének késleltetése (másodperc); Érdemes kisebbet választani, mint a változások megőrzésének maximális ideje.';
+$lang['notify'] = 'Az oldal-változásokat erre az e-mail címre küldje';
+$lang['registernotify'] = 'Értesítés egy újonnan regisztrált felhasználóról erre az e-mail címre';
+$lang['mailfrom'] = 'Az automatikusan küldött levelekben használt e-mail cím';
+$lang['mailprefix'] = 'Előtag az automatikus e-mailek tárgyában';
+$lang['htmlmail'] = 'Szebb, de nagyobb méretű HTML multipart e-mailek küldése. Tiltsd le a nyers szöveges üzenetekhez!';
+$lang['sitemap'] = 'Hány naponként generáljunk Google sitemap-ot?';
+$lang['rss_type'] = 'XML hírfolyam típus';
+$lang['rss_linkto'] = 'XML hírfolyam hivatkozás';
+$lang['rss_content'] = 'Mit mutassunk az XML hírfolyam elemekben?';
+$lang['rss_update'] = 'Hány másodpercenként frissítsük az XML hírfolyamot?';
+$lang['rss_show_summary'] = 'A hírfolyam címébe összefoglaló helyezése';
+$lang['rss_media'] = 'Milyen változások legyenek felsorolva az XML hírfolyamban?';
$lang['updatecheck'] = 'Frissítések és biztonsági figyelmeztetések figyelése. Ehhez a DokuWikinek kapcsolatba kell lépnie a update.dokuwiki.org-gal.';
$lang['userewrite'] = 'Szép URL-ek használata';
$lang['useslash'] = 'Per-jel használata névtér-elválasztóként az URL-ekben';
-$lang['usedraft'] = 'Piszkozat automatikus mentése szerkesztés alatt';
$lang['sepchar'] = 'Szó elválasztó az oldalnevekben';
$lang['canonical'] = 'Teljesen kanonikus URL-ek használata';
$lang['fnencode'] = 'A nem ASCII fájlnevek dekódolási módja';
$lang['autoplural'] = 'Többes szám ellenőrzés a hivatkozásokban (angol)';
$lang['compression'] = 'Tömörítés használata a törölt lapokhoz';
-$lang['cachetime'] = 'A gyorsítótár maximális élettartama (másodperc)';
-$lang['locktime'] = 'Oldal-zárolás maximális időtartama (másodperc)';
-$lang['fetchsize'] = 'Maximális méret (bájtban), amit a fetch.php letölthet kívülről';
-$lang['notify'] = 'Az oldal-változásokat erre az e-mail címre küldje';
-$lang['registernotify'] = 'Értesítés egy újonnan regisztrált felhasználóról erre az e-mail címre';
-$lang['mailfrom'] = 'Az automatikusan küldött levelekben használt e-mail cím';
-$lang['mailprefix'] = 'Előtag az automatikus e-mailek tárgyában';
$lang['gzip_output'] = 'gzip tömörítés használata xhtml-hez (Content-Encoding)';
-$lang['gdlib'] = 'GD Lib verzió';
-$lang['im_convert'] = 'Útvonal az ImageMagick csomag convert parancsához';
-$lang['jpg_quality'] = 'JPG tömörítés minősége (0-100)';
-$lang['subscribers'] = 'Oldalváltozás-listára feliratkozás engedélyezése';
-$lang['subscribe_time'] = 'Az értesítések kiküldésének késleltetése (másodperc); Érdemes kisebbet választani, mint a változások megőrzésének maximális ideje.';
$lang['compress'] = 'CSS és JavaScript fájlok tömörítése';
-$lang['hidepages'] = 'Az itt megadott oldalak elrejtése (reguláris kifejezés)';
+$lang['cssdatauri'] = 'Mérethatár bájtokban, ami alatti CSS-ben hivatkozott fájlok közvetlenül beágyazódjanak a stíluslapba. Ez IE 7-ben és alatta nem fog működni! <code>400</code>-<code>600</code> bájt ideális érték. Állítsd <code>0</code>-ra a beágyazás kikapcsolásához!';
$lang['send404'] = '"HTTP 404/Page Not Found" küldése nemlétező oldalak esetén';
-$lang['sitemap'] = 'Hány naponként generáljunk Google sitemap-ot?';
$lang['broken_iua'] = 'Az ignore_user_abort függvény hibát dob a rendszereden? Ez nem működő keresési indexet eredményezhet. Az IIS+PHP/CGI összeállításról tudjuk, hogy hibát dob. Lásd a <a href="http://bugs.splitbrain.org/?do=details&amp;task_id=852">Bug 852</a> oldalt a további infóért.';
$lang['xsendfile'] = 'Használjuk az X-Sendfile fejlécet, hogy a webszerver statikus állományokat tudjon küldeni? A webszervernek is támogatnia kell ezt a funkciót.';
$lang['renderer_xhtml'] = 'Az elsődleges (xhtml) wiki kimenet generálója';
$lang['renderer__core'] = '%s (dokuwiki mag)';
$lang['renderer__plugin'] = '%s (bővítmény)';
-$lang['rememberme'] = 'Állandó sütik engedélyezése (az "emlékezz rám" funkcióhoz)';
-$lang['rss_type'] = 'XML hírfolyam típus';
-$lang['rss_linkto'] = 'XML hírfolyam hivatkozás';
-$lang['rss_content'] = 'Mit mutassunk az XML hírfolyam elemekben?';
-$lang['rss_update'] = 'Hány másodpercenként frissítsük az XML hírfolyamot?';
-$lang['recent_days'] = 'Hány napig tartsuk meg a korábbi változatokat?';
-$lang['rss_show_summary'] = 'A hírfolyam címébe összefoglaló helyezése';
-$lang['target____wiki'] = 'Cél-ablak belső hivatkozásokhoz';
-$lang['target____interwiki'] = 'Cél-ablak interwiki hivatkozásokhoz';
-$lang['target____extern'] = 'Cél-ablak külső hivatkozásokhoz';
-$lang['target____media'] = 'Cél-ablak média-fájl hivatkozásokhoz';
-$lang['target____windows'] = 'Cél-ablak Windows hivatkozásokhoz';
-$lang['proxy____host'] = 'Proxy szerver neve';
+$lang['dnslookups'] = 'A DokuWiki megpróbál hosztneveket keresni a távoli IP-címekhez. Amennyiben lassú, vagy nem működő DNS-szervered van vagy csak nem szeretnéd ezt a funkciót, tiltsd le ezt az opciót!';
+$lang['proxy____host'] = 'Proxy-szerver neve';
$lang['proxy____port'] = 'Proxy port';
$lang['proxy____user'] = 'Proxy felhasználó név';
$lang['proxy____pass'] = 'Proxy jelszó';
@@ -174,7 +184,7 @@ $lang['compression_o_0'] = 'nincs tömörítés';
$lang['compression_o_gz'] = 'gzip';
$lang['compression_o_bz2'] = 'bz2';
$lang['xsendfile_o_0'] = 'nincs használatban';
-$lang['xsendfile_o_1'] = 'lighttpd saját fejléc (1.5-ös verzió előtti)';
+$lang['xsendfile_o_1'] = 'Lighttpd saját fejléc (1.5-ös verzió előtti)';
$lang['xsendfile_o_2'] = 'Standard X-Sendfile fejléc';
$lang['xsendfile_o_3'] = 'Nginx saját X-Accel-Redirect fejléce';
$lang['showuseras_o_loginname'] = 'Azonosító';
diff --git a/lib/plugins/config/lang/ia/lang.php b/lib/plugins/config/lang/ia/lang.php
index fdb9d954e..c3430030c 100644
--- a/lib/plugins/config/lang/ia/lang.php
+++ b/lib/plugins/config/lang/ia/lang.php
@@ -27,8 +27,6 @@ $lang['_links'] = 'Configurationes de ligamines';
$lang['_media'] = 'Configurationes de multimedia';
$lang['_advanced'] = 'Configurationes avantiate';
$lang['_network'] = 'Configurationes de rete';
-$lang['_plugin_sufix'] = 'Configurationes de plug-ins';
-$lang['_template_sufix'] = 'Configurationes de patronos';
$lang['_msg_setting_undefined'] = 'Nulle metadatos de configuration.';
$lang['_msg_setting_no_class'] = 'Nulle classe de configuration.';
$lang['_msg_setting_no_default'] = 'Nulle valor predefinite.';
@@ -59,7 +57,6 @@ $lang['camelcase'] = 'Usar CamelCase pro ligamines';
$lang['deaccent'] = 'Nomines nette de paginas';
$lang['useheading'] = 'Usar le prime titulo como nomine de pagina';
$lang['refcheck'] = 'Verification de referentias multimedia';
-$lang['refshow'] = 'Numero de referentias multimedia a monstrar';
$lang['allowdebug'] = 'Permitter debugging <b>disactiva si non necessari!</b>';
$lang['usewordblock'] = 'Blocar spam a base de lista de parolas';
$lang['indexdelay'] = 'Retardo ante generation de indice (secundas)';
diff --git a/lib/plugins/config/lang/is/lang.php b/lib/plugins/config/lang/is/lang.php
index c4905d0f9..a99b39ca2 100644
--- a/lib/plugins/config/lang/is/lang.php
+++ b/lib/plugins/config/lang/is/lang.php
@@ -13,7 +13,6 @@ $lang['nochoice'] = '(engir aðrir valmöguleikar fyrir hendi)';
$lang['_display'] = 'Skjástillingar';
$lang['_anti_spam'] = 'Stillingar gegn ruslpósti';
$lang['_editing'] = 'Útgáfastillingar';
-$lang['_plugin_sufix'] = 'Viðbótstillingar';
$lang['lang'] = 'Tungumál';
$lang['title'] = 'Heiti wikis';
$lang['template'] = 'Mát';
diff --git a/lib/plugins/config/lang/it/lang.php b/lib/plugins/config/lang/it/lang.php
index 62dd00f0c..7a831c8de 100644
--- a/lib/plugins/config/lang/it/lang.php
+++ b/lib/plugins/config/lang/it/lang.php
@@ -42,8 +42,6 @@ $lang['_notifications'] = 'Impostazioni di notifica';
$lang['_syndication'] = 'Impostazioni di collaborazione';
$lang['_advanced'] = 'Impostazioni Avanzate';
$lang['_network'] = 'Impostazioni Rete';
-$lang['_plugin_sufix'] = 'Impostazioni Plugin';
-$lang['_template_sufix'] = 'Impostazioni Modello';
$lang['_msg_setting_undefined'] = 'Nessun metadato definito.';
$lang['_msg_setting_no_class'] = 'Nessuna classe definita.';
$lang['_msg_setting_no_default'] = 'Nessun valore predefinito.';
@@ -114,7 +112,6 @@ $lang['target____media'] = 'Finestra di destinazione per i collegamenti ai
$lang['target____windows'] = 'Finestra di destinazione per i collegamenti alle risorse condivise';
$lang['mediarevisions'] = 'Abilita Mediarevisions?';
$lang['refcheck'] = 'Controlla i riferimenti ai file';
-$lang['refshow'] = 'Numero di riferimenti da visualizzare';
$lang['gdlib'] = 'Versione GD Lib ';
$lang['im_convert'] = 'Percorso per il convertitore di ImageMagick';
$lang['jpg_quality'] = 'Qualità di compressione JPG (0-100)';
diff --git a/lib/plugins/config/lang/ja/lang.php b/lib/plugins/config/lang/ja/lang.php
index 807436cca..e8cf8227b 100644
--- a/lib/plugins/config/lang/ja/lang.php
+++ b/lib/plugins/config/lang/ja/lang.php
@@ -37,8 +37,6 @@ $lang['_notifications'] = '通知設定';
$lang['_syndication'] = 'RSS配信設定';
$lang['_advanced'] = '高度な設定';
$lang['_network'] = 'ネットワーク';
-$lang['_plugin_sufix'] = 'プラグイン設定';
-$lang['_template_sufix'] = 'テンプレート設定';
$lang['_msg_setting_undefined'] = '設定のためのメタデータがありません。';
$lang['_msg_setting_no_class'] = '設定クラスがありません。';
$lang['_msg_setting_no_default'] = '初期値が設定されていません。';
@@ -109,7 +107,6 @@ $lang['target____media'] = 'メディアリンクの表示先';
$lang['target____windows'] = 'Windowsリンクの表示先';
$lang['mediarevisions'] = 'メディアファイルの履歴を有効にしますか?';
$lang['refcheck'] = 'メディア参照元チェック';
-$lang['refshow'] = 'メディア参照元表示数';
$lang['gdlib'] = 'GDlibバージョン';
$lang['im_convert'] = 'ImageMagick変換ツールへのパス';
$lang['jpg_quality'] = 'JPG圧縮品質(0-100)';
diff --git a/lib/plugins/config/lang/ko/intro.txt b/lib/plugins/config/lang/ko/intro.txt
index b9eb763a4..c8b146930 100644
--- a/lib/plugins/config/lang/ko/intro.txt
+++ b/lib/plugins/config/lang/ko/intro.txt
@@ -1,7 +1,7 @@
-====== 환경 설정 관리 ======
+====== 환경 설정 관리자 ======
-DokuWiki 설치할 때 설정을 바꾸기 위해 사용하는 페이지입니다. 각 설정에 대한 자세한 도움말이 필요하다면 [[doku>ko:config|설정 문서 (한국어)]]와 [[doku>config|설정 문서 (영어)]]를 참고하세요.
+DokuWiki 설치할 때 설정을 바꾸기 위해 사용하는 페이지입니다. 각 설정에 대한 자세한 도움말이 필요하다면 [[doku>ko:config|설정]] 문서를 참고하세요. 플러그인에 대한 자세한 정보가 필요하다면 [[doku>ko:plugin:config|플러그인 설정]] 문서를 참고하세요.
-플러그인에 대한 자세한 정보가 필요하다면 [[doku>plugin:config|플러그인 설정]] 문서를 참고하세요. 빨간 배경색으로 보이는 설정은 이 플러그인에서 바꾸지 못하도록 되어있습니다. 파란 배경색으로 보이는 설정은 기본 설정값을 가지고 있습니다. 하얀 배경색으로 보이는 설정은 특별한 설치를 위해 설정되어 있습니다. 파란색과 하얀색 배경으로 된 설정은 바꿀 수 있습니다.
+빨간 배경색으로 보이는 설정은 이 플러그인에서 바꾸지 못하도록 되어있습니다. 파란 배경색으로 보이는 설정은 기본 설정값을 가지고 있습니다. 하얀 배경색으로 보이는 설정은 특별한 설치를 위해 설정되어 있습니다. 파란색과 하얀색 배경으로 된 설정은 바꿀 수 있습니다.
이 페이지를 떠나기 전에 **저장** 버튼을 누르지 않으면 바뀐 값은 적용되지 않습니다. \ No newline at end of file
diff --git a/lib/plugins/config/lang/ko/lang.php b/lib/plugins/config/lang/ko/lang.php
index da155bcef..1aab4731a 100644
--- a/lib/plugins/config/lang/ko/lang.php
+++ b/lib/plugins/config/lang/ko/lang.php
@@ -36,8 +36,6 @@ $lang['_notifications'] = '알림 설정';
$lang['_syndication'] = '신디케이션 설정';
$lang['_advanced'] = '고급 설정';
$lang['_network'] = '네트워크 설정';
-$lang['_plugin_sufix'] = '플러그인 설정';
-$lang['_template_sufix'] = '템플릿 설정';
$lang['_msg_setting_undefined'] = '설정된 메타데이터가 없습니다.';
$lang['_msg_setting_no_class'] = '설정된 클래스가 없습니다.';
$lang['_msg_setting_no_default'] = '기본값이 없습니다.';
@@ -62,7 +60,7 @@ $lang['youarehere'] = '계층형 위치 추적 (다음 위의 옵션
$lang['fullpath'] = '문서 하단에 전체 경로 보여주기';
$lang['typography'] = '기호 대체';
$lang['dformat'] = '날짜 형식 (PHP <a href="http://www.php.net/strftime">strftime</a> 기능 참고)';
-$lang['signature'] = '편집기에서 서명 버튼을 누를 때 삽입할 내용';
+$lang['signature'] = '편집기에서 서명 버튼을 누를 때 넣을 내용';
$lang['showuseras'] = '마지막에 문서를 편집한 사용자를 보여줄지 여부';
$lang['toptoclevel'] = '목차 최상위 항목';
$lang['tocminheads'] = '목차 표시 여부를 결정할 최소한의 문단 제목 항목의 수';
@@ -86,7 +84,7 @@ $lang['rememberme'] = '항상 로그인 정보 저장 허용 (기억
$lang['disableactions'] = 'DokuWiki 활동 비활성화';
$lang['disableactions_check'] = '검사';
$lang['disableactions_subscription'] = '구독 신청/구독 취소';
-$lang['disableactions_wikicode'] = '내용 보기/원본 내보내기';
+$lang['disableactions_wikicode'] = '원본 보기/원본 내보내기';
$lang['disableactions_other'] = '다른 활동 (쉼표로 구분)';
$lang['auth_security_timeout'] = '인증 보안 초과 시간 (초)';
$lang['securecookie'] = 'HTTPS로 보내진 쿠키는 HTTPS에만 적용 할까요? 위키의 로그인 페이지만 SSL로 암호화하고 위키 문서는 그렇지 않은 경우 비활성화 합니다.';
@@ -109,7 +107,6 @@ $lang['target____media'] = '미디어 링크에 대한 타겟 창';
$lang['target____windows'] = '창 링크에 대한 타겟 창';
$lang['mediarevisions'] = '미디어 판 관리를 사용하겠습니까?';
$lang['refcheck'] = '미디어 파일을 삭제하기 전에 사용하고 있는지 검사';
-$lang['refshow'] = '위의 설정이 활성화되었을 때 보여줄 미디어 참고 수';
$lang['gdlib'] = 'GD 라이브러리 버전';
$lang['im_convert'] = 'ImageMagick 변환 도구 위치';
$lang['jpg_quality'] = 'JPG 압축 품질 (0-100)';
diff --git a/lib/plugins/config/lang/la/lang.php b/lib/plugins/config/lang/la/lang.php
index 057e69974..100f06431 100644
--- a/lib/plugins/config/lang/la/lang.php
+++ b/lib/plugins/config/lang/la/lang.php
@@ -26,8 +26,6 @@ $lang['_links'] = 'Nexi Optiones';
$lang['_media'] = 'Visiuorum Optiones';
$lang['_advanced'] = 'Maiores Optiones';
$lang['_network'] = 'Interretis Optiones';
-$lang['_plugin_sufix'] = 'Addendorum Optiones';
-$lang['_template_sufix'] = 'Vicis Formae Optiones';
$lang['_msg_setting_undefined'] = 'Res codicum sine optionibus.';
$lang['_msg_setting_no_class'] = 'Classes sine optionibus';
$lang['_msg_setting_no_default'] = 'Nihil';
@@ -58,7 +56,6 @@ $lang['camelcase'] = 'SignaContinua nexis apta facere';
$lang['deaccent'] = 'Titulus paginarum abrogare';
$lang['useheading'] = 'Capite primo ut titulo paginae uti';
$lang['refcheck'] = 'Documenta uisiua inspicere';
-$lang['refshow'] = 'Numerus documentorum ostendorum';
$lang['allowdebug'] = '<b>ineptum facias si non necessarium!</b> aptum facere';
$lang['usewordblock'] = 'Malum interretiale ob uerba delere';
$lang['indexdelay'] = 'Tempus transitum in ordinando (sec)';
diff --git a/lib/plugins/config/lang/lv/lang.php b/lib/plugins/config/lang/lv/lang.php
index 3adfd1871..aa692c1e4 100644
--- a/lib/plugins/config/lang/lv/lang.php
+++ b/lib/plugins/config/lang/lv/lang.php
@@ -29,8 +29,6 @@ $lang['_media'] = 'Mēdiju iestatījumi';
$lang['_notifications'] = 'Brīdinājumu iestatījumi';
$lang['_advanced'] = 'Smalkāka iestatīšana';
$lang['_network'] = 'Tīkla iestatījumi';
-$lang['_plugin_sufix'] = 'moduļa iestatījumi';
-$lang['_template_sufix'] = 'šablona iestatījumi';
$lang['_msg_setting_undefined'] = 'Nav atrodami iestatījumu metadati';
$lang['_msg_setting_no_class'] = 'Nav iestatījumu klases';
$lang['_msg_setting_no_default'] = 'Nav noklusētās vērtības';
@@ -95,7 +93,6 @@ $lang['target____extern'] = 'Kur atvērt ārējās saites';
$lang['target____media'] = 'Kur atvērt mēdiju saites';
$lang['target____windows'] = 'Kur atvērt saites uz tīkla mapēm';
$lang['refcheck'] = 'Pārbaudīt saites uz mēdiju failiem';
-$lang['refshow'] = 'Cik saites uz mēdiju failiem rādīt';
$lang['gdlib'] = 'GD Lib versija';
$lang['im_convert'] = 'Ceļš uz ImageMagick convert rīku';
$lang['jpg_quality'] = 'JPG saspiešanas kvalitāte';
diff --git a/lib/plugins/config/lang/mr/lang.php b/lib/plugins/config/lang/mr/lang.php
index 4f33bfa7c..172c47e4f 100644
--- a/lib/plugins/config/lang/mr/lang.php
+++ b/lib/plugins/config/lang/mr/lang.php
@@ -30,8 +30,6 @@ $lang['_links'] = 'लिंक सेटिंग';
$lang['_media'] = 'दृक्श्राव्य माध्यम सेटिंग';
$lang['_advanced'] = 'सविस्तर सेटिंग';
$lang['_network'] = 'नेटवर्क सेटिंग';
-$lang['_plugin_sufix'] = 'प्लगिन सेटिंग';
-$lang['_template_sufix'] = 'टेम्पलेट ( नमुना ) सेटिंग';
$lang['_msg_setting_undefined'] = 'सेटिंगविषयी उप-डेटा उपलब्ध नाही.';
$lang['_msg_setting_no_class'] = 'सेटिंगचा क्लास उपलब्ध नाही';
$lang['_msg_setting_no_default'] = 'आपोआप किम्मत नाही';
@@ -62,7 +60,6 @@ $lang['camelcase'] = 'लिंकसाठी कॅमलकेस
$lang['deaccent'] = 'सरळ्सोट पृष्ठ नाम';
$lang['useheading'] = 'पहिलं शीर्षक पृष्ठ नाम म्हणुन वापरा';
$lang['refcheck'] = 'दृक्श्राव्य माध्यमाचा संदर्भ तपासा';
-$lang['refshow'] = 'दृक्श्राव्य माध्यामाचे संदर्भ दाखवण्याची संख्या';
$lang['allowdebug'] = 'डिबगची परवानगी <b> गरज नसल्यास बंद ठेवा !</b>';
$lang['usewordblock'] = 'भंकस मजकूर थोपवण्यासाठी शब्दसमुह वापरा';
$lang['indexdelay'] = 'सूचीकरणापूर्वीचा अवकाश ( सेकंदात )';
diff --git a/lib/plugins/config/lang/ne/lang.php b/lib/plugins/config/lang/ne/lang.php
index a8b426b9c..ffa7713fa 100644
--- a/lib/plugins/config/lang/ne/lang.php
+++ b/lib/plugins/config/lang/ne/lang.php
@@ -21,8 +21,6 @@ $lang['_links'] = 'लिङ्क सेटिंङ्ग';
$lang['_media'] = 'मिडिया सेटिंङ्ग';
$lang['_advanced'] = 'विशिष्ठ सेटिंङ्ग';
$lang['_network'] = 'सञ्जाल सेटिंङ्ग';
-$lang['_plugin_sufix'] = 'प्लगइन सेटिंङ्ग';
-$lang['_template_sufix'] = 'टेम्प्लेट सेटिंङ्ग';
$lang['_msg_setting_undefined'] = 'सेटिंङ्ग मेटाडाटा नभएको';
$lang['_msg_setting_no_class'] = 'सेटिंङ्ग वर्ग नभएको';
$lang['_msg_setting_no_default'] = 'कुनै पूर्व निर्धारित मान छैन ।';
diff --git a/lib/plugins/config/lang/nl/lang.php b/lib/plugins/config/lang/nl/lang.php
index 26ea3d8c1..14c8f9b1e 100644
--- a/lib/plugins/config/lang/nl/lang.php
+++ b/lib/plugins/config/lang/nl/lang.php
@@ -41,8 +41,6 @@ $lang['_notifications'] = 'Meldingsinstellingen';
$lang['_syndication'] = 'Syndication-instellingen';
$lang['_advanced'] = 'Geavanceerde instellingen';
$lang['_network'] = 'Netwerkinstellingen';
-$lang['_plugin_sufix'] = 'Plugin-instellingen';
-$lang['_template_sufix'] = 'Sjabloon-instellingen';
$lang['_msg_setting_undefined'] = 'Geen metadata voor deze instelling.';
$lang['_msg_setting_no_class'] = 'Geen class voor deze instelling.';
$lang['_msg_setting_no_default'] = 'Geen standaard waarde.';
@@ -113,7 +111,6 @@ $lang['target____media'] = 'Doelvenster voor medialinks';
$lang['target____windows'] = 'Doelvenster voor windows links';
$lang['mediarevisions'] = 'Mediarevisies activeren?';
$lang['refcheck'] = 'Controleer of er verwijzingen bestaan naar een mediabestand voor het wijderen';
-$lang['refshow'] = 'Aantal te tonen mediaverwijzingen';
$lang['gdlib'] = 'Versie GD Lib ';
$lang['im_convert'] = 'Path naar ImageMagick\'s convert tool';
$lang['jpg_quality'] = 'JPG compressiekwaliteit (0-100)';
diff --git a/lib/plugins/config/lang/no/lang.php b/lib/plugins/config/lang/no/lang.php
index b01637dd1..f048a0fe9 100644
--- a/lib/plugins/config/lang/no/lang.php
+++ b/lib/plugins/config/lang/no/lang.php
@@ -43,8 +43,6 @@ $lang['_links'] = 'Innstillinger for lenker';
$lang['_media'] = 'Innstillinger for mediafiler';
$lang['_advanced'] = 'Avanserte innstillinger';
$lang['_network'] = 'Nettverksinnstillinger';
-$lang['_plugin_sufix'] = '– innstillinger for tillegg';
-$lang['_template_sufix'] = '– innstillinger for mal';
$lang['_msg_setting_undefined'] = 'Ingen innstillingsmetadata';
$lang['_msg_setting_no_class'] = 'Ingen innstillingsklasse';
$lang['_msg_setting_no_default'] = 'Ingen standard verdi';
@@ -76,7 +74,6 @@ $lang['camelcase'] = 'Gjør KamelKasse til lenke automatisk';
$lang['deaccent'] = 'Rensk sidenavn';
$lang['useheading'] = 'Bruk første overskrift som tittel';
$lang['refcheck'] = 'Sjekk referanser før mediafiler slettes';
-$lang['refshow'] = 'Antall viste referanser til mediafiler';
$lang['allowdebug'] = 'Tillat feilsøking <b>skru av om det ikke behøves!</b>';
$lang['mediarevisions'] = 'Slå på mediaversjonering?';
$lang['usewordblock'] = 'Blokker søppel basert på ordliste';
diff --git a/lib/plugins/config/lang/pl/lang.php b/lib/plugins/config/lang/pl/lang.php
index 8441722cd..9a7cc49ba 100644
--- a/lib/plugins/config/lang/pl/lang.php
+++ b/lib/plugins/config/lang/pl/lang.php
@@ -40,8 +40,6 @@ $lang['_notifications'] = 'Ustawienia powiadomień';
$lang['_syndication'] = 'Ustawienia RSS';
$lang['_advanced'] = 'Zaawansowane';
$lang['_network'] = 'Sieć';
-$lang['_plugin_sufix'] = 'Wtyczki';
-$lang['_template_sufix'] = 'Motywy';
$lang['_msg_setting_undefined'] = 'Brak danych o ustawieniu.';
$lang['_msg_setting_no_class'] = 'Brak kategorii ustawień.';
$lang['_msg_setting_no_default'] = 'Brak wartości domyślnej.';
@@ -112,7 +110,6 @@ $lang['target____media'] = 'Okno docelowe odnośników do plików';
$lang['target____windows'] = 'Okno docelowe odnośników zasobów Windows';
$lang['mediarevisions'] = 'Włączyć wersjonowanie multimediów?';
$lang['refcheck'] = 'Sprawdzanie odwołań przed usunięciem pliku';
-$lang['refshow'] = 'Ilość pokazywanych odwołań do pliku';
$lang['gdlib'] = 'Wersja biblioteki GDLib';
$lang['im_convert'] = 'Ścieżka do programu imagemagick';
$lang['jpg_quality'] = 'Jakość kompresji JPG (0-100)';
diff --git a/lib/plugins/config/lang/pt-br/lang.php b/lib/plugins/config/lang/pt-br/lang.php
index 85218439a..ee1447b4e 100644
--- a/lib/plugins/config/lang/pt-br/lang.php
+++ b/lib/plugins/config/lang/pt-br/lang.php
@@ -44,8 +44,6 @@ $lang['_notifications'] = 'Configurações de notificação';
$lang['_syndication'] = 'Configurações de sindicância';
$lang['_advanced'] = 'Configurações avançadas';
$lang['_network'] = 'Configurações de rede';
-$lang['_plugin_sufix'] = 'Configurações de plug-ins';
-$lang['_template_sufix'] = 'Configurações do modelo';
$lang['_msg_setting_undefined'] = 'Nenhum metadado configurado.';
$lang['_msg_setting_no_class'] = 'Nenhuma classe definida.';
$lang['_msg_setting_no_default'] = 'Nenhum valor padrão.';
diff --git a/lib/plugins/config/lang/pt/lang.php b/lib/plugins/config/lang/pt/lang.php
index d0fe0ac0d..7a9111c62 100644
--- a/lib/plugins/config/lang/pt/lang.php
+++ b/lib/plugins/config/lang/pt/lang.php
@@ -31,8 +31,6 @@ $lang['_links'] = 'Configuração de Ligações';
$lang['_media'] = 'Configuração de Media';
$lang['_advanced'] = 'Configurações Avançadas';
$lang['_network'] = 'Configuração de Rede';
-$lang['_plugin_sufix'] = 'Configuração dos Plugins';
-$lang['_template_sufix'] = 'Configuração das Templates';
$lang['_msg_setting_undefined'] = 'Nenhum metadado configurado.';
$lang['_msg_setting_no_class'] = 'Nenhuma classe definida.';
$lang['_msg_setting_no_default'] = 'Sem valor por omissão.';
@@ -63,7 +61,6 @@ $lang['camelcase'] = 'Usar CamelCase';
$lang['deaccent'] = 'Nomes das páginas sem acentos';
$lang['useheading'] = 'Usar o primeiro cabeçalho para o nome da página';
$lang['refcheck'] = 'Verificação de referência da media';
-$lang['refshow'] = 'Número de referências de media a exibir';
$lang['allowdebug'] = 'Permitir depuração <b>desabilite se não for necessário!</b>';
$lang['usewordblock'] = 'Bloquear spam baseado em lista de palavras (wordlist)';
$lang['indexdelay'] = 'Tempo de espera antes da indexação (seg)';
diff --git a/lib/plugins/config/lang/ro/lang.php b/lib/plugins/config/lang/ro/lang.php
index 72b205b90..e95c551e7 100644
--- a/lib/plugins/config/lang/ro/lang.php
+++ b/lib/plugins/config/lang/ro/lang.php
@@ -34,8 +34,6 @@ $lang['_links'] = 'Setări Legături';
$lang['_media'] = 'Setări Media';
$lang['_advanced'] = 'Setări Avansate';
$lang['_network'] = 'Setări Reţea';
-$lang['_plugin_sufix'] = 'Setări Plugin-uri';
-$lang['_template_sufix'] = 'Setări Şabloane';
$lang['_msg_setting_undefined'] = 'Nesetat metadata';
$lang['_msg_setting_no_class'] = 'Nesetat class';
$lang['_msg_setting_no_default'] = 'Nici o valoare implicită';
@@ -69,7 +67,6 @@ $lang['camelcase'] = 'Foloseşte CamelCase pentru legături';
$lang['deaccent'] = 'numedepagină curate';
$lang['useheading'] = 'Foloseşte primul titlu pentru numele paginii';
$lang['refcheck'] = 'Verificare referinţă media';
-$lang['refshow'] = 'Numărul de referinţe media de arătat';
$lang['allowdebug'] = 'Permite depanarea <b>dezactivaţi dacă cu e necesar!</b>';
$lang['mediarevisions'] = 'Activare Revizii Media?';
$lang['usewordblock'] = 'Blochează spam-ul pe baza listei de cuvinte';
diff --git a/lib/plugins/config/lang/ru/lang.php b/lib/plugins/config/lang/ru/lang.php
index 42cbbd35a..596ad4ead 100644
--- a/lib/plugins/config/lang/ru/lang.php
+++ b/lib/plugins/config/lang/ru/lang.php
@@ -43,8 +43,6 @@ $lang['_notifications'] = 'Параметры уведомлений';
$lang['_syndication'] = 'Настройки синдикаций';
$lang['_advanced'] = 'Тонкая настройка';
$lang['_network'] = 'Параметры сети';
-$lang['_plugin_sufix'] = 'Параметры плагина';
-$lang['_template_sufix'] = 'Параметры шаблона';
$lang['_msg_setting_undefined'] = 'Не найдены метаданные настроек.';
$lang['_msg_setting_no_class'] = 'Не найден класс настроек.';
$lang['_msg_setting_no_default'] = 'Не задано значение по умолчанию.';
@@ -115,7 +113,6 @@ $lang['target____media'] = 'target для ссылок на медиафа
$lang['target____windows'] = 'target для ссылок на сетевые каталоги';
$lang['mediarevisions'] = 'Включение версий медиафайлов';
$lang['refcheck'] = 'Проверять ссылки на медиафайлы';
-$lang['refshow'] = 'Показывать ссылок на медиафайлы';
$lang['gdlib'] = 'Версия LibGD';
$lang['im_convert'] = 'Путь к ImageMagick';
$lang['jpg_quality'] = 'Качество сжатия JPG (0–100). Значение по умолчанию — 70.';
diff --git a/lib/plugins/config/lang/sk/lang.php b/lib/plugins/config/lang/sk/lang.php
index 9e18b3ed9..46e4081a9 100644
--- a/lib/plugins/config/lang/sk/lang.php
+++ b/lib/plugins/config/lang/sk/lang.php
@@ -31,8 +31,6 @@ $lang['_notifications'] = 'Nastavenie upozornení';
$lang['_syndication'] = 'Nastavenie poskytovania obsahu';
$lang['_advanced'] = 'Rozšírené nastavenia';
$lang['_network'] = 'Nastavenia siete';
-$lang['_plugin_sufix'] = 'Nastavenia plug-inu';
-$lang['_template_sufix'] = 'Nastavenia šablóny';
$lang['_msg_setting_undefined'] = 'Nenastavené metadata.';
$lang['_msg_setting_no_class'] = 'Nenastavená trieda.';
$lang['_msg_setting_no_default'] = 'Žiadna predvolená hodnota.';
@@ -103,7 +101,6 @@ $lang['target____media'] = 'Cieľové okno (target) pre media odkazy';
$lang['target____windows'] = 'Cieľové okno (target) pre windows odkazy';
$lang['mediarevisions'] = 'Povoliť verzie súborov?';
$lang['refcheck'] = 'Kontrolovať odkazy na médiá (pred vymazaním)';
-$lang['refshow'] = 'Počet zobrazených odkazov na médiá';
$lang['gdlib'] = 'Verzia GD Lib';
$lang['im_convert'] = 'Cesta k ImageMagick convert tool';
$lang['jpg_quality'] = 'Kvalita JPG kompresie (0-100)';
diff --git a/lib/plugins/config/lang/sl/lang.php b/lib/plugins/config/lang/sl/lang.php
index 364e0fd7f..fe334db55 100644
--- a/lib/plugins/config/lang/sl/lang.php
+++ b/lib/plugins/config/lang/sl/lang.php
@@ -29,8 +29,6 @@ $lang['_links'] = 'Nastavitve povezav';
$lang['_media'] = 'Predstavne nastavitve';
$lang['_advanced'] = 'Napredne nastavitve';
$lang['_network'] = 'Omrežne nastavitve';
-$lang['_plugin_sufix'] = 'nastavitve';
-$lang['_template_sufix'] = 'nastavitve';
$lang['_msg_setting_undefined'] = 'Ni nastavitvenih metapodatkov.';
$lang['_msg_setting_no_class'] = 'Ni nastavitvenega razreda.';
$lang['_msg_setting_no_default'] = 'Ni privzete vrednosti.';
@@ -64,7 +62,6 @@ $lang['camelcase'] = 'Uporabi EnoBesedni zapisa za povezave';
$lang['deaccent'] = 'Počisti imena strani';
$lang['useheading'] = 'Uporabi prvi naslov za ime strani';
$lang['refcheck'] = 'Preverjanje sklica predstavnih datotek';
-$lang['refshow'] = 'Število predstavih sklicev za prikaz';
$lang['allowdebug'] = 'Dovoli razhroščevanje (po potrebi!)';
$lang['mediarevisions'] = 'Ali naj se omogočijo objave predstavnih vsebin?';
$lang['usewordblock'] = 'Zaustavi neželeno besedilo glede na seznam besed';
diff --git a/lib/plugins/config/lang/sq/lang.php b/lib/plugins/config/lang/sq/lang.php
index 69e283b11..a6f30875b 100644
--- a/lib/plugins/config/lang/sq/lang.php
+++ b/lib/plugins/config/lang/sq/lang.php
@@ -27,8 +27,6 @@ $lang['_links'] = 'Kuadrot e Link-eve';
$lang['_media'] = 'Kuadrot e Medias';
$lang['_advanced'] = 'Kuadro të Avancuara';
$lang['_network'] = 'Kuadrot e Rrjetit';
-$lang['_plugin_sufix'] = 'Kuadrot e Plugin-eve';
-$lang['_template_sufix'] = 'Kuadrot e Template-eve';
$lang['_msg_setting_undefined'] = 'Metadata pa kuadro.';
$lang['_msg_setting_no_class'] = 'Klasë pa kuadro.';
$lang['_msg_setting_no_default'] = 'Asnjë vlerë default.';
@@ -59,7 +57,6 @@ $lang['camelcase'] = 'Përdor CamelCase (shkronja e parë e çdo fja
$lang['deaccent'] = 'Emra faqesh të pastër';
$lang['useheading'] = 'Përdor titra të nivelit të parë për faqet e emrave';
$lang['refcheck'] = 'Kontroll për referim mediash';
-$lang['refshow'] = 'Numri i referimeve të medias që duhet të tregohet';
$lang['allowdebug'] = 'Lejo debug <b>çaktivizoje nëse nuk nevojitet!</b>';
$lang['usewordblock'] = 'Blloko spam-in duke u bazuar mbi listë fjalësh';
$lang['indexdelay'] = 'Vonesa në kohë para index-imit (sekonda)';
diff --git a/lib/plugins/config/lang/sr/lang.php b/lib/plugins/config/lang/sr/lang.php
index c675b84e6..1c3250e86 100644
--- a/lib/plugins/config/lang/sr/lang.php
+++ b/lib/plugins/config/lang/sr/lang.php
@@ -28,8 +28,6 @@ $lang['_links'] = 'Подешавања линковања';
$lang['_media'] = 'Подешавања медија';
$lang['_advanced'] = 'Напредна подешавања';
$lang['_network'] = 'Подешавања мреже';
-$lang['_plugin_sufix'] = 'Подешавања за додатке';
-$lang['_template_sufix'] = 'Подешавања за шаблоне';
$lang['_msg_setting_undefined'] = 'Нема метаподатака подешавања';
$lang['_msg_setting_no_class'] = 'Нема класе подешавања';
$lang['_msg_setting_no_default'] = 'Нема подразумеване вредности';
@@ -60,7 +58,6 @@ $lang['camelcase'] = 'Користи CamelCase за линкове';
$lang['deaccent'] = 'Чисти имена страница';
$lang['useheading'] = 'Преузми наслов првог нивоа за назив странице';
$lang['refcheck'] = 'Провери референце медијских датотека';
-$lang['refshow'] = 'Број референци које се приказују за медијске датотеке';
$lang['allowdebug'] = 'Укључи дебаговање <b>искључи ако није потребно!</b>';
$lang['usewordblock'] = 'Блокирај спам на основу листе речи';
$lang['indexdelay'] = 'Одлагање индексирања (секунде)';
diff --git a/lib/plugins/config/lang/sv/lang.php b/lib/plugins/config/lang/sv/lang.php
index d59b4b17e..74f59502c 100644
--- a/lib/plugins/config/lang/sv/lang.php
+++ b/lib/plugins/config/lang/sv/lang.php
@@ -44,8 +44,6 @@ $lang['_notifications'] = 'Noterings inställningar';
$lang['_syndication'] = 'Syndikats inställningar';
$lang['_advanced'] = 'Avancerade inställningar';
$lang['_network'] = 'Nätverksinställningar';
-$lang['_plugin_sufix'] = '(inställningar för insticksmodul)';
-$lang['_template_sufix'] = '(inställningar för mall)';
$lang['_msg_setting_undefined'] = 'Ingen inställningsmetadata.';
$lang['_msg_setting_no_class'] = 'Ingen inställningsklass.';
$lang['_msg_setting_no_default'] = 'Inget standardvärde.';
@@ -111,7 +109,6 @@ $lang['target____extern'] = 'Målfönster för externa länkar';
$lang['target____media'] = 'Målfönster för medialänkar';
$lang['target____windows'] = 'Målfönster för windowslänkar';
$lang['refcheck'] = 'Kontrollera referenser till mediafiler';
-$lang['refshow'] = 'Antal mediareferenser som ska visas';
$lang['gdlib'] = 'Version av GD-biblioteket';
$lang['im_convert'] = 'Sökväg till ImageMagicks konverteringsverktyg';
$lang['jpg_quality'] = 'Kvalitet för JPG-komprimering (0-100)';
diff --git a/lib/plugins/config/lang/th/lang.php b/lib/plugins/config/lang/th/lang.php
index 140a287df..68ee8b8a2 100644
--- a/lib/plugins/config/lang/th/lang.php
+++ b/lib/plugins/config/lang/th/lang.php
@@ -23,7 +23,6 @@ $lang['_links'] = 'การตั้งค่าลิงก์'
$lang['_media'] = 'การตั้งค่าภาพ-เสียง';
$lang['_advanced'] = 'การตั้งค่าขั้นสูง';
$lang['_network'] = 'การตั้งค่าเครือข่าย';
-$lang['_plugin_sufix'] = 'การตั้งค่าโปรแกรมเสริม (plugin)';
$lang['lang'] = 'ภาษา';
$lang['basedir'] = 'ไดเรคทอรีพื้นฐาน';
$lang['baseurl'] = 'URL พื้นฐาน';
diff --git a/lib/plugins/config/lang/tr/lang.php b/lib/plugins/config/lang/tr/lang.php
index 5bc4f3fc1..cb610f4ff 100644
--- a/lib/plugins/config/lang/tr/lang.php
+++ b/lib/plugins/config/lang/tr/lang.php
@@ -32,8 +32,6 @@ $lang['_links'] = 'Bağlantı Ayarları';
$lang['_media'] = 'Medya Ayarları';
$lang['_advanced'] = 'Gelişmiş Ayarlar';
$lang['_network'] = 'Ağ Ayarları';
-$lang['_plugin_sufix'] = 'Eklenti Ayarları';
-$lang['_template_sufix'] = 'Şablon (Template) Ayarları';
$lang['_msg_setting_undefined'] = 'Ayar üstverisi yok.';
$lang['_msg_setting_no_class'] = 'Ayar sınıfı yok.';
$lang['_msg_setting_no_default'] = 'Varsayılan değer yok.';
@@ -79,7 +77,6 @@ $lang['iexssprotect'] = 'Yüklenmiş dosyaları muhtemel kötu niyetli
$lang['htmlok'] = 'Gömülü HTML koduna izin ver';
$lang['phpok'] = 'Gömülü PHP koduna izin ver';
$lang['refcheck'] = 'Araç kaynak denetimi';
-$lang['refshow'] = 'Gösterilecek araç kaynağı sayısı';
$lang['gdlib'] = 'GD Lib sürümü';
$lang['jpg_quality'] = 'JPG sıkıştırma kalitesi [0-100]';
$lang['mailfrom'] = 'Otomatik e-postalar için kullanılacak e-posta adresi';
diff --git a/lib/plugins/config/lang/uk/lang.php b/lib/plugins/config/lang/uk/lang.php
index 3d463fc72..dea9203e8 100644
--- a/lib/plugins/config/lang/uk/lang.php
+++ b/lib/plugins/config/lang/uk/lang.php
@@ -36,8 +36,6 @@ $lang['_media'] = 'Налаштування медіа';
$lang['_notifications'] = 'Налаштування сповіщень';
$lang['_advanced'] = 'Розширені налаштування';
$lang['_network'] = 'Налаштування мережі';
-$lang['_plugin_sufix'] = 'Налаштування (доданок)';
-$lang['_template_sufix'] = 'Налаштування (шаблон)';
$lang['_msg_setting_undefined'] = 'Немає метаданих параметру.';
$lang['_msg_setting_no_class'] = 'Немає класу параметру.';
$lang['_msg_setting_no_default'] = 'Немає значення за замовчуванням.';
@@ -102,7 +100,6 @@ $lang['target____extern'] = 'Target для зовнішніх посила
$lang['target____media'] = 'Target для медіа-посилань';
$lang['target____windows'] = 'Target для посилань на мережеві папки';
$lang['refcheck'] = 'Перевіряти посилання на медіа-файлі';
-$lang['refshow'] = 'Показувати кількість медіа-посилань';
$lang['gdlib'] = 'Версія GD Lib';
$lang['im_convert'] = 'Шлях до ImageMagick';
$lang['jpg_quality'] = 'Якість компресії JPG (0-100)';
diff --git a/lib/plugins/config/lang/zh-tw/lang.php b/lib/plugins/config/lang/zh-tw/lang.php
index cc6e0246e..cc2c28c31 100644
--- a/lib/plugins/config/lang/zh-tw/lang.php
+++ b/lib/plugins/config/lang/zh-tw/lang.php
@@ -37,8 +37,6 @@ $lang['_notifications'] = '提醒設定';
$lang['_syndication'] = '聚合設定';
$lang['_advanced'] = '進階設定';
$lang['_network'] = '網路設定';
-$lang['_plugin_sufix'] = '附加元件設定';
-$lang['_template_sufix'] = '樣板設定';
$lang['_msg_setting_undefined'] = '設定的後設數據不存在。';
$lang['_msg_setting_no_class'] = '設定的分類不存在。';
$lang['_msg_setting_no_default'] = '無預設值';
@@ -109,7 +107,6 @@ $lang['target____media'] = '媒體連結的目標視窗';
$lang['target____windows'] = 'Windows 連結的目標視窗';
$lang['mediarevisions'] = '啟用媒體修訂歷史嗎?';
$lang['refcheck'] = '媒體連結檢查';
-$lang['refshow'] = '媒體連結的顯示數量';
$lang['gdlib'] = 'GD Lib 版本';
$lang['im_convert'] = 'ImageMagick 的轉換工具路徑';
$lang['jpg_quality'] = 'JPG 壓縮品質(0-100)';
diff --git a/lib/plugins/config/lang/zh/lang.php b/lib/plugins/config/lang/zh/lang.php
index 832dfe749..364ad3fe6 100644
--- a/lib/plugins/config/lang/zh/lang.php
+++ b/lib/plugins/config/lang/zh/lang.php
@@ -42,8 +42,6 @@ $lang['_notifications'] = '通知设置';
$lang['_syndication'] = '聚合设置';
$lang['_advanced'] = '高级设置';
$lang['_network'] = '网络设置';
-$lang['_plugin_sufix'] = '插件设置';
-$lang['_template_sufix'] = '模板设置';
$lang['_msg_setting_undefined'] = '设置的元数据不存在。';
$lang['_msg_setting_no_class'] = '设置的分类不存在。';
$lang['_msg_setting_no_default'] = '设置的默认值不存在。';
@@ -114,7 +112,6 @@ $lang['target____media'] = '媒体文件链接的目标窗口';
$lang['target____windows'] = 'Windows 链接的目标窗口';
$lang['mediarevisions'] = '激活媒体修订历史?';
$lang['refcheck'] = '检查媒体与页面的挂钩情况';
-$lang['refshow'] = '显示媒体与页面挂钩情况的数量';
$lang['gdlib'] = 'GD 库版本';
$lang['im_convert'] = 'ImageMagick 转换工具的路径';
$lang['jpg_quality'] = 'JPG 压缩质量(0-100)';
diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php
index 8eb99284d..6d582ad30 100644
--- a/lib/plugins/config/settings/config.class.php
+++ b/lib/plugins/config/settings/config.class.php
@@ -366,12 +366,11 @@ if (!class_exists('setting')) {
var $_pattern = '';
var $_error = false; // only used by those classes which error check
var $_input = null; // only used by those classes which error check
+ var $_caution = null; // used by any setting to provide an alert along with the setting
+ // valid alerts, 'warning', 'danger', 'security'
+ // images matching the alerts are in the plugin's images directory
- var $_cautionList = array(
- 'basedir' => 'danger', 'baseurl' => 'danger', 'savedir' => 'danger', 'cookiedir' => 'danger', 'useacl' => 'danger', 'authtype' => 'danger', 'superuser' => 'danger', 'userewrite' => 'danger',
- 'start' => 'warning', 'camelcase' => 'warning', 'deaccent' => 'warning', 'sepchar' => 'warning', 'compression' => 'warning', 'xsendfile' => 'warning', 'renderer_xhtml' => 'warning', 'fnencode' => 'warning',
- 'allowdebug' => 'security', 'htmlok' => 'security', 'phpok' => 'security', 'iexssprotect' => 'security', 'remote' => 'security', 'fullpath' => 'security'
- );
+ static protected $_validCautions = array('warning','danger','security');
function setting($key, $params=null) {
$this->_key = $key;
@@ -473,8 +472,22 @@ if (!class_exists('setting')) {
function error() { return $this->_error; }
function caution() {
- if (!array_key_exists($this->_key, $this->_cautionList)) return false;
- return $this->_cautionList[$this->_key];
+ if (!empty($this->_caution)) {
+ if (!in_array($this->_caution, setting::$_validCautions)) {
+ trigger_error('Invalid caution string ('.$this->_caution.') in metadata for setting "'.$this->_key.'"', E_USER_WARNING);
+ return false;
+ }
+ return $this->_caution;
+ }
+ // compatibility with previous cautionList
+ // TODO: check if any plugins use; remove
+ if (!empty($this->_cautionList[$this->_key])) {
+ $this->_caution = $this->_cautionList[$this->_key];
+ unset($this->_cautionList);
+
+ return $this->caution();
+ }
+ return false;
}
function _out_key($pretty=false,$url=false) {
@@ -659,10 +672,8 @@ if (!class_exists('setting_password')) {
}
if (!class_exists('setting_email')) {
- if (!defined('SETTING_EMAIL_PATTERN')) define('SETTING_EMAIL_PATTERN','<^'.PREG_PATTERN_VALID_EMAIL.'$>');
class setting_email extends setting_string {
- var $_pattern = SETTING_EMAIL_PATTERN; // no longer required, retained for backward compatibility - FIXME, may not be necessary
var $_multiple = false;
var $_placeholders = false;
@@ -717,6 +728,29 @@ if (!class_exists('setting_email')) {
$this->_local = $input;
return true;
}
+ function html(&$plugin, $echo=false) {
+ $value = '';
+ $disable = '';
+
+ if ($this->is_protected()) {
+ $value = $this->_protected;
+ $disable = 'disabled="disabled"';
+ } else {
+ if ($echo && $this->_error) {
+ $value = $this->_input;
+ } else {
+ $value = is_null($this->_local) ? $this->_default : $this->_local;
+ }
+ }
+
+ $multiple = $this->_multiple ? 'multiple="multiple"' : '';
+ $key = htmlspecialchars($this->_key);
+ $value = htmlspecialchars($value);
+
+ $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>';
+ $input = '<input id="config___'.$key.'" name="config['.$key.']" type="email" class="edit" value="'.$value.'" '.$multiple.' '.$disable.'/>';
+ return array($label,$input);
+ }
}
}
@@ -1084,96 +1118,39 @@ if (!class_exists('setting_multicheckbox')) {
}
}
-/**
- * Provide php_strip_whitespace (php5 function) functionality
- *
- * @author Chris Smith <chris@jalakai.co.uk>
- */
-if (!function_exists('php_strip_whitespace')) {
-
- if (function_exists('token_get_all')) {
+if (!class_exists('setting_regex')){
+ class setting_regex extends setting_string {
- if (!defined('T_ML_COMMENT')) {
- define('T_ML_COMMENT', T_COMMENT);
- } else {
- define('T_DOC_COMMENT', T_ML_COMMENT);
- }
+ var $_delimiter = '/'; // regex delimiter to be used in testing input
+ var $_pregflags = 'ui'; // regex pattern modifiers to be used in testing input
- /**
- * modified from original
- * source Google Groups, php.general, by David Otton
- */
- function php_strip_whitespace($file) {
- if (!@is_readable($file)) return '';
-
- $in = join('',@file($file));
- $out = '';
+ /**
+ * update changed setting with user provided value $input
+ * - if changed value fails error check, save it to $this->_input (to allow echoing later)
+ * - if changed value passes error check, set $this->_local to the new value
+ *
+ * @param mixed $input the new value
+ * @return boolean true if changed, false otherwise (incl. on error)
+ */
+ function update($input) {
- $tokens = token_get_all($in);
+ // let parent do basic checks, value, not changed, etc.
+ $local = $this->_local;
+ if (!parent::update($input)) return false;
+ $this->_local = $local;
- foreach ($tokens as $token) {
- if (is_string ($token)) {
- $out .= $token;
- } else {
- list ($id, $text) = $token;
- switch ($id) {
- case T_COMMENT : // fall thru
- case T_ML_COMMENT : // fall thru
- case T_DOC_COMMENT : // fall thru
- case T_WHITESPACE :
- break;
- default : $out .= $text; break;
+ // see if the regex compiles and runs (we don't check for effectiveness)
+ $regex = $this->_delimiter . $input . $this->_delimiter . $this->_pregflags;
+ $lastError = error_get_last();
+ $ok = @preg_match($regex,'testdata');
+ if (preg_last_error() != PREG_NO_ERROR || error_get_last() != $lastError) {
+ $this->_input = $input;
+ $this->_error = true;
+ return false;
}
- }
- }
- return ($out);
- }
-
- } else {
-
- function is_whitespace($c) { return (strpos("\t\n\r ",$c) !== false); }
- function is_quote($c) { return (strpos("\"'",$c) !== false); }
- function is_escaped($s,$i) {
- $idx = $i-1;
- while(($idx>=0) && ($s{$idx} == '\\')) $idx--;
- return (($i - $idx + 1) % 2);
- }
-
- function is_commentopen($str, $i) {
- if ($str{$i} == '#') return "\n";
- if ($str{$i} == '/') {
- if ($str{$i+1} == '/') return "\n";
- if ($str{$i+1} == '*') return "*/";
- }
- return false;
- }
-
- function php_strip_whitespace($file) {
-
- if (!@is_readable($file)) return '';
-
- $contents = join('',@file($file));
- $out = '';
-
- $state = 0;
- for ($i=0; $i<strlen($contents); $i++) {
- if (!$state && is_whitespace($contents{$i})) continue;
-
- if (!$state && ($c_close = is_commentopen($contents, $i))) {
- $c_open_len = ($contents{$i} == '/') ? 2 : 1;
- $i = strpos($contents, $c_close, $i+$c_open_len)+strlen($c_close)-1;
- continue;
- }
-
- $out .= $contents{$i};
- if (is_quote($contents{$i})) {
- if (($state == $contents{$i}) && !is_escaped($contents, $i)) { $state = 0; continue; }
- if (!$state) {$state = $contents{$i}; continue; }
- }
+ $this->_local = $input;
+ return true;
}
-
- return $out;
}
- }
}
diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php
index 22e76a013..f4c2ed265 100644
--- a/lib/plugins/config/settings/config.metadata.php
+++ b/lib/plugins/config/settings/config.metadata.php
@@ -20,7 +20,8 @@
* 'numericopt' - like above, but accepts empty values
* 'onoff' - checkbox input, setting output 0|1
* 'multichoice' - select input (single choice), setting output with quotes, required _choices parameter
- * 'email' - text input, input must conform to email address format
+ * 'email' - text input, input must conform to email address format, supports optional '_multiple'
+ * parameter for multiple comma separated email addresses
* 'password' - password input, minimal input validation, setting output text in quotes, maybe encoded
* according to the _code parameter
* 'dirchoice' - as multichoice, selection choices based on folders found at location specified in _dir
@@ -33,6 +34,9 @@
* 'array' - a simple (one dimensional) array of string values, shown as comma separated list in the
* config manager but saved as PHP array(). Values may not contain commas themselves.
* _pattern matching on the array values supported.
+ * 'regex' - regular expression string, normally without delimiters; as for string, in addition tested
+ * to see if will compile & run as a regex. in addition to _pattern, also accepts _delimiter
+ * (default '/') and _pregflags (default 'ui')
*
* Single Setting (source: settings/extra.class.php)
* -------------------------------------------------
@@ -42,10 +46,13 @@
* 'im_convert' - as 'setting', input must exist and be an im_convert module
* 'disableactions' - as 'setting'
* 'compression' - no additional parameters. checks php installation supports possible compression alternatives
+ * 'licence' - as multichoice, selection constructed from licence strings in language files
+ * 'renderer' - as multichoice, selection constructed from enabled renderer plugins which canRender()
*
* Any setting commented or missing will use 'setting' class - text input, minimal validation, quoted output
*
* Defined parameters:
+ * '_caution' - no value (default) or 'warning', 'danger', 'security'. display an alert along with the setting
* '_pattern' - string, a preg pattern. input is tested against this pattern before being accepted
* optional all classes, except onoff & multichoice which ignore it
* '_choices' - array of choices. used to populate a selection box. choice will be replaced by a localised
@@ -58,6 +65,10 @@
* '_code' - encoding method to use, accepted values: 'base64','uuencode','plain'. defaults to plain.
* '_min' - minimum numeric value, optional for 'numeric' and 'numericopt', ignored by others
* '_max' - maximum numeric value, optional for 'numeric' and 'numericopt', ignored by others
+ * '_delimiter' - string, default '/', a single character used as a delimiter for testing regex input values
+ * '_pregflags' - string, default 'ui', valid preg pattern modifiers used when testing regex input values, for more
+ * information see http://uk1.php.net/manual/en/reference.pcre.pattern.modifiers.php
+ * '_multiple' - bool, allow multiple comma separated email values; optional for 'email', ignored by others
*
* @author Chris Smith <chris@jalakai.co.uk>
*/
@@ -81,26 +92,26 @@ $config['heading'] = 'Dokuwiki\'s Main Configuration File - Local Settings';
$meta['_basic'] = array('fieldset');
$meta['title'] = array('string');
-$meta['start'] = array('string','_pattern' => '!^[^:;/]+$!'); // don't accept namespaces
+$meta['start'] = array('string','_caution' => 'warning','_pattern' => '!^[^:;/]+$!'); // don't accept namespaces
$meta['lang'] = array('dirchoice','_dir' => DOKU_INC.'inc/lang/');
$meta['template'] = array('dirchoice','_dir' => DOKU_INC.'lib/tpl/','_pattern' => '/^[\w-]+$/');
$meta['tagline'] = array('string');
$meta['sidebar'] = array('string');
$meta['license'] = array('license');
-$meta['savedir'] = array('savedir');
-$meta['basedir'] = array('string');
-$meta['baseurl'] = array('string');
-$meta['cookiedir'] = array('string');
+$meta['savedir'] = array('savedir','_caution' => 'danger');
+$meta['basedir'] = array('string','_caution' => 'danger');
+$meta['baseurl'] = array('string','_caution' => 'danger');
+$meta['cookiedir'] = array('string','_caution' => 'danger');
$meta['dmode'] = array('numeric','_pattern' => '/0[0-7]{3,4}/'); // only accept octal representation
$meta['fmode'] = array('numeric','_pattern' => '/0[0-7]{3,4}/'); // only accept octal representation
-$meta['allowdebug'] = array('onoff');
+$meta['allowdebug'] = array('onoff','_caution' => 'security');
$meta['_display'] = array('fieldset');
$meta['recent'] = array('numeric');
$meta['recent_days'] = array('numeric');
$meta['breadcrumbs'] = array('numeric','_min' => 0);
$meta['youarehere'] = array('onoff');
-$meta['fullpath'] = array('onoff');
+$meta['fullpath'] = array('onoff','_caution' => 'security');
$meta['typography'] = array('multichoice','_choices' => array(0,1,2));
$meta['dformat'] = array('string');
$meta['signature'] = array('string');
@@ -109,28 +120,28 @@ $meta['toptoclevel'] = array('multichoice','_choices' => array(1,2,3,4,5)); //
$meta['tocminheads'] = array('multichoice','_choices' => array(0,1,2,3,4,5,10,15,20));
$meta['maxtoclevel'] = array('multichoice','_choices' => array(0,1,2,3,4,5));
$meta['maxseclevel'] = array('multichoice','_choices' => array(0,1,2,3,4,5)); // 0 for no sec edit buttons
-$meta['camelcase'] = array('onoff');
-$meta['deaccent'] = array('multichoice','_choices' => array(0,1,2));
+$meta['camelcase'] = array('onoff','_caution' => 'warning');
+$meta['deaccent'] = array('multichoice','_choices' => array(0,1,2),'_caution' => 'warning');
$meta['useheading'] = array('multichoice','_choices' => array(0,'navigation','content',1));
$meta['sneaky_index'] = array('onoff');
-$meta['hidepages'] = array('string');
+$meta['hidepages'] = array('regex');
$meta['_authentication'] = array('fieldset');
-$meta['useacl'] = array('onoff');
+$meta['useacl'] = array('onoff','_caution' => 'danger');
$meta['autopasswd'] = array('onoff');
-$meta['authtype'] = array('authtype');
+$meta['authtype'] = array('authtype','_caution' => 'danger');
$meta['passcrypt'] = array('multichoice','_choices' => array('smd5','md5','apr1','sha1','ssha','lsmd5','crypt','mysql','my411','kmd5','pmd5','hmd5','mediawiki','bcrypt','djangomd5','djangosha1','sha512'));
$meta['defaultgroup']= array('string');
-$meta['superuser'] = array('string');
+$meta['superuser'] = array('string','_caution' => 'danger');
$meta['manager'] = array('string');
$meta['profileconfirm'] = array('onoff');
$meta['rememberme'] = array('onoff');
$meta['disableactions'] = array('disableactions',
- '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','edit','wikicode','check'),
+ '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','profile_delete','edit','wikicode','check'),
'_combine' => array('subscription' => array('subscribe','unsubscribe'), 'wikicode' => array('source','export_raw')));
$meta['auth_security_timeout'] = array('numeric');
$meta['securecookie'] = array('onoff');
-$meta['remote'] = array('onoff');
+$meta['remote'] = array('onoff','_caution' => 'security');
$meta['remoteuser'] = array('string');
$meta['_anti_spam'] = array('fieldset');
@@ -138,12 +149,12 @@ $meta['usewordblock']= array('onoff');
$meta['relnofollow'] = array('onoff');
$meta['indexdelay'] = array('numeric');
$meta['mailguard'] = array('multichoice','_choices' => array('visible','hex','none'));
-$meta['iexssprotect']= array('onoff');
+$meta['iexssprotect']= array('onoff','_caution' => 'security');
$meta['_editing'] = array('fieldset');
$meta['usedraft'] = array('onoff');
-$meta['htmlok'] = array('onoff');
-$meta['phpok'] = array('onoff');
+$meta['htmlok'] = array('onoff','_caution' => 'security');
+$meta['phpok'] = array('onoff','_caution' => 'security');
$meta['locktime'] = array('numeric');
$meta['cachetime'] = array('numeric');
@@ -161,7 +172,6 @@ $meta['im_convert'] = array('im_convert');
$meta['jpg_quality'] = array('numeric','_pattern' => '/^100$|^[1-9]?[0-9]$/'); //(0-100)
$meta['fetchsize'] = array('numeric');
$meta['refcheck'] = array('onoff');
-$meta['refshow'] = array('numeric');
$meta['_notifications'] = array('fieldset');
$meta['subscribers'] = array('onoff');
@@ -183,20 +193,20 @@ $meta['rss_show_summary'] = array('onoff');
$meta['_advanced'] = array('fieldset');
$meta['updatecheck'] = array('onoff');
-$meta['userewrite'] = array('multichoice','_choices' => array(0,1,2));
+$meta['userewrite'] = array('multichoice','_choices' => array(0,1,2),'_caution' => 'danger');
$meta['useslash'] = array('onoff');
-$meta['sepchar'] = array('sepchar');
+$meta['sepchar'] = array('sepchar','_caution' => 'warning');
$meta['canonical'] = array('onoff');
-$meta['fnencode'] = array('multichoice','_choices' => array('url','safe','utf-8'));
+$meta['fnencode'] = array('multichoice','_choices' => array('url','safe','utf-8'),'_caution' => 'warning');
$meta['autoplural'] = array('onoff');
$meta['compress'] = array('onoff');
$meta['cssdatauri'] = array('numeric','_pattern' => '/^\d+$/');
$meta['gzip_output'] = array('onoff');
$meta['send404'] = array('onoff');
-$meta['compression'] = array('compression');
+$meta['compression'] = array('compression','_caution' => 'warning');
$meta['broken_iua'] = array('onoff');
-$meta['xsendfile'] = array('multichoice','_choices' => array(0,1,2,3));
-$meta['renderer_xhtml'] = array('renderer','_format' => 'xhtml','_choices' => array('xhtml'));
+$meta['xsendfile'] = array('multichoice','_choices' => array(0,1,2,3),'_caution' => 'warning');
+$meta['renderer_xhtml'] = array('renderer','_format' => 'xhtml','_choices' => array('xhtml'),'_caution' => 'warning');
$meta['readdircache'] = array('numeric');
$meta['_network'] = array('fieldset');
diff --git a/lib/plugins/plugin/lang/de-informal/lang.php b/lib/plugins/plugin/lang/de-informal/lang.php
index a082218d8..5d1649434 100644
--- a/lib/plugins/plugin/lang/de-informal/lang.php
+++ b/lib/plugins/plugin/lang/de-informal/lang.php
@@ -9,6 +9,7 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['menu'] = 'Plugins verwalten';
$lang['download'] = 'Herunterladen und installieren einer neuen Erweiterung';
diff --git a/lib/plugins/plugin/lang/hu/lang.php b/lib/plugins/plugin/lang/hu/lang.php
index 34309a53f..235d33a0e 100644
--- a/lib/plugins/plugin/lang/hu/lang.php
+++ b/lib/plugins/plugin/lang/hu/lang.php
@@ -8,6 +8,7 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
$lang['menu'] = 'Bővítménykezelő';
$lang['download'] = 'Új bővítmény letöltése és telepítése';
@@ -18,24 +19,24 @@ $lang['btn_delete'] = 'törlés';
$lang['btn_settings'] = 'beállítások';
$lang['btn_download'] = 'Letöltés';
$lang['btn_enable'] = 'Mentés';
-$lang['url'] = 'URL:';
+$lang['url'] = 'Cím';
$lang['installed'] = 'Telepítve:';
$lang['lastupdate'] = 'Utolsó frissítés:';
$lang['source'] = 'Forrás:';
$lang['unknown'] = 'ismeretlen';
$lang['updating'] = 'Frissítés...';
-$lang['updated'] = 'A %s bővítmény sikeresen frissült.';
-$lang['updates'] = 'A következő bővítmények sikeresen frissültek:';
+$lang['updated'] = 'A %s bővítmény frissítése sikeres';
+$lang['updates'] = 'A következő bővítmények frissítése sikeres:';
$lang['update_none'] = 'Nem találtam újabb verziót.';
$lang['deleting'] = 'Törlés...';
-$lang['deleted'] = 'A %s bővítményt eltávolítottam.';
+$lang['deleted'] = 'A %s bővítményt eltávolítva.';
$lang['downloading'] = 'Letöltés...';
-$lang['downloaded'] = 'A %s bővítmény sikeresen feltelepült.';
-$lang['downloads'] = 'A következő bővítmények sikeresen feltelepültek:';
-$lang['download_none'] = 'Nem találtam bővítményt, vagy ismeretlen hiba történt a letöltés/telepítés közben.';
+$lang['downloaded'] = 'A %s bővítmény telepítése sikeres.';
+$lang['downloads'] = 'A következő bővítmények telepítése sikeres.';
+$lang['download_none'] = 'Nem találtam bővítményt vagy ismeretlen hiba történt a letöltés/telepítés közben.';
$lang['plugin'] = 'Bővítmény:';
$lang['components'] = 'Részek';
-$lang['noinfo'] = 'Ez a bővítmény nem tartalmaz infót, lehet, hogy hibás.';
+$lang['noinfo'] = 'Ez a bővítmény nem tartalmaz információt, lehet, hogy hibás.';
$lang['name'] = 'Név:';
$lang['date'] = 'Dátum:';
$lang['type'] = 'Típus:';
@@ -43,14 +44,14 @@ $lang['desc'] = 'Leírás:';
$lang['author'] = 'Szerző:';
$lang['www'] = 'Web:';
$lang['error'] = 'Ismeretlen hiba lépett fel.';
-$lang['error_download'] = 'Nem tudom letölteni a bővítmény fájlt: %s';
+$lang['error_download'] = 'Nem tudom letölteni a fájlt a bővítményhez: %s';
$lang['error_badurl'] = 'Feltehetően rossz URL - nem tudom meghatározni a fájlnevet az URL-ből.';
$lang['error_dircreate'] = 'Nem tudom létrehozni az átmeneti könyvtárat a letöltéshez.';
$lang['error_decompress'] = 'A Bővítménykezelő nem tudta a letöltött állományt kicsomagolni. Ennek oka lehet hibás letöltés, ebben az esetben újra letöltéssel próbálkozhatsz, esetleg a tömörítés módja ismeretlen, ebben az esetben kézzel kell letölteni és telepíteni a bővítményt.';
-$lang['error_copy'] = 'Fájl másolási hiba történt a(z) <em>%s</em> bővítmény telepítése közben: vagy a lemezterület fogyott el, vagy az állomány hozzáférési jogosultságok nem megfelelőek. Emiatt előfordulhat, hogy a bővítményt csak részben sikerült telepíteni, és a wiki összeomolhat.';
-$lang['error_delete'] = 'Hiba történt a(z) <em>%s</em> bővítmény eltávolítása közben. A legvalószínűbb ok, hogy a könyvtár vagy állomány hozzáférési jogosultságok nem megfelelőek.';
+$lang['error_copy'] = 'Fájl másolási hiba történt a(z) <em>%s</em> bővítmény telepítése közben: vagy a lemezterület fogyott el, vagy az állomány hozzáférési jogosultságai nem megfelelőek. Emiatt előfordulhat, hogy a bővítményt csak részben sikerült telepíteni és a wiki összeomolhat.';
+$lang['error_delete'] = 'Hiba történt a(z) <em>%s</em> bővítmény eltávolítása közben. A legvalószínűbb ok, hogy a könyvtár vagy állomány hozzáférési jogosultságai nem megfelelőek.';
$lang['enabled'] = 'A(z) %s bővítmény bekapcsolva.';
-$lang['notenabled'] = 'A(z) %s bővítmény engedélyezése nem sikerült. Ellenőrizze a fájl-hozzáférési engedélyeket.';
+$lang['notenabled'] = 'A(z) %s bővítmény engedélyezése nem sikerült. Ellenőrizze a fájlhozzáférési jogosultságokat.';
$lang['disabled'] = 'A(z) %s bővítmény kikapcsolva.';
-$lang['notdisabled'] = 'A(z) %s bővítmény kikapcsolása nem sikerült. Ellenőrizze a fájl-hozzáférési engedélyeket.';
-$lang['packageinstalled'] = 'A bővítmény csomag(ok) feltelepült(ek): %d plugin(s): %s';
+$lang['notdisabled'] = 'A(z) %s bővítmény kikapcsolása nem sikerült. Ellenőrizze a fájlhozzáférési jogosultságokat.';
+$lang['packageinstalled'] = 'A bővítménycsomag(ok) feltelepült(ek): %d plugin(s): %s';
diff --git a/lib/plugins/plugin/lang/ko/admin_plugin.txt b/lib/plugins/plugin/lang/ko/admin_plugin.txt
index 7cbd08f7a..aeef5fedf 100644
--- a/lib/plugins/plugin/lang/ko/admin_plugin.txt
+++ b/lib/plugins/plugin/lang/ko/admin_plugin.txt
@@ -1,3 +1,3 @@
====== 플러그인 관리 ======
-이 페이지에서 Dokuwiki [[doku>plugins|플러그인]]에 관련된 모든 관리 작업을 합니다. 플러그인을 다운로드하거나 설치하기 위해서는 웹 서버가 플러그인 디렉토리에 대해 쓰기 권한을 가지고 있어야 합니다. \ No newline at end of file
+이 페이지에서 Dokuwiki [[doku>ko:plugins|플러그인]]에 관련된 모든 관리 작업을 합니다. 플러그인을 다운로드하거나 설치하기 위해서는 웹 서버가 플러그인 디렉토리에 대해 쓰기 권한을 가지고 있어야 합니다. \ No newline at end of file
diff --git a/lib/plugins/plugin/lang/ko/lang.php b/lib/plugins/plugin/lang/ko/lang.php
index 447fe667b..4e615b118 100644
--- a/lib/plugins/plugin/lang/ko/lang.php
+++ b/lib/plugins/plugin/lang/ko/lang.php
@@ -10,7 +10,7 @@
* @author erial2@gmail.com
* @author Myeongjin <aranet100@gmail.com>
*/
-$lang['menu'] = '플러그인 관리자';
+$lang['menu'] = '플러그인 관리';
$lang['download'] = '새 플러그인 다운로드 및 설치';
$lang['manage'] = '이미 설치한 플러그인';
$lang['btn_info'] = '정보';
@@ -22,7 +22,7 @@ $lang['btn_enable'] = '저장';
$lang['url'] = 'URL';
$lang['installed'] = '설치됨:';
$lang['lastupdate'] = '가장 나중에 업데이트됨:';
-$lang['source'] = '내용:';
+$lang['source'] = '원본:';
$lang['unknown'] = '알 수 없음';
$lang['updating'] = '업데이트 중 ...';
$lang['updated'] = '%s 플러그인을 성공적으로 업데이트했습니다';
diff --git a/lib/plugins/plugin/lang/sv/lang.php b/lib/plugins/plugin/lang/sv/lang.php
index a8578c03c..b7c23743b 100644
--- a/lib/plugins/plugin/lang/sv/lang.php
+++ b/lib/plugins/plugin/lang/sv/lang.php
@@ -1,11 +1,11 @@
<?php
+
/**
- * swedish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -14,7 +14,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/popularity/helper.php b/lib/plugins/popularity/helper.php
index 5bbeddba0..0e38bcb88 100644
--- a/lib/plugins/popularity/helper.php
+++ b/lib/plugins/popularity/helper.php
@@ -85,7 +85,7 @@ class helper_plugin_popularity extends Dokuwiki_Plugin {
function sendData($data){
$error = '';
$httpClient = new DokuHTTPClient();
- $status = $httpClient->sendRequest($this->submitUrl, $data, 'POST');
+ $status = $httpClient->sendRequest($this->submitUrl, array('data' => $data), 'POST');
if ( ! $status ){
$error = $httpClient->error;
}
diff --git a/lib/plugins/popularity/lang/de-informal/intro.txt b/lib/plugins/popularity/lang/de-informal/intro.txt
index ddae9347d..a414b6687 100644
--- a/lib/plugins/popularity/lang/de-informal/intro.txt
+++ b/lib/plugins/popularity/lang/de-informal/intro.txt
@@ -1,6 +1,6 @@
===== Rückmeldung zur Zufriedenheit =====
-Dieses Werkzeug sammelt anonym Daten über dein Wiki und erlaubt es dir diese an die Entwickler von DokuWiki zu senden. Dies hilft ihnen zu verstehen, wie DokuWiki von den Nutzern verwendet wird und stellt somit sicher, dass Entscheidungen für zukünftige Entwicklungen mit reellen Nutzungsstatistiken belegbar sind.
+Dieses Werkzeug sammelt anonym Daten über dein Wiki und erlaubt es dir diese an die Entwickler von DokuWiki zu senden. Dies hilft ihnen zu verstehen, wie DokuWiki von den Benutzern verwendet wird und stellt somit sicher, dass Entscheidungen für zukünftige Entwicklungen mit reellen Nutzungsstatistiken belegbar sind.
Bitte wiederhole diesen Schritt von Zeit zu Zeit, um die Entwickler zu informieren wenn dein Wiki wächst. Deine aktuelleren Datensätze werden anhand einer anonymen Identifikationsnummer zugeordnet.
diff --git a/lib/plugins/popularity/lang/de-informal/lang.php b/lib/plugins/popularity/lang/de-informal/lang.php
index 513a1b6e1..0abf90b0b 100644
--- a/lib/plugins/popularity/lang/de-informal/lang.php
+++ b/lib/plugins/popularity/lang/de-informal/lang.php
@@ -9,6 +9,7 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['name'] = 'Popularitätsrückmeldung (kann eine Weile dauern, bis es fertig geladen wurde)';
$lang['submit'] = 'Sende Daten';
diff --git a/lib/plugins/popularity/lang/de/intro.txt b/lib/plugins/popularity/lang/de/intro.txt
index dc014e029..ba88ce270 100644
--- a/lib/plugins/popularity/lang/de/intro.txt
+++ b/lib/plugins/popularity/lang/de/intro.txt
@@ -1,6 +1,6 @@
====== Popularitäts-Feedback ======
-Dieses [[doku>popularity|Werkzeug]] sammelt verschiedene anonyme Daten über Ihr Wiki und erlaubt es Ihnen, diese an die DokuWiki-Entwickler zurückzusenden. Diese Daten helfen den Entwicklern besser zu verstehen, wie DokuWiki eingesetzt wird und stellt sicher, dass zukünftige, die Weiterentwicklung von DokuWiki betreffende, Entscheidungen auf Basis echter Nutzerdaten getroffen werden.
+Dieses [[doku>popularity|Werkzeug]] sammelt verschiedene anonyme Daten über Ihr Wiki und erlaubt es Ihnen, diese an die DokuWiki-Entwickler zurückzusenden. Diese Daten helfen den Entwicklern besser zu verstehen, wie DokuWiki eingesetzt wird und stellt sicher, dass zukünftige, die Weiterentwicklung von DokuWiki betreffende, Entscheidungen auf Basis echter Benutzerdaten getroffen werden.
Bitte wiederholen Sie das Versenden der Daten von Zeit zu Zeit, um die Entwickler über das Wachstum Ihres Wikis auf dem Laufenden zu halten. Ihre wiederholten Dateneinsendungen werden über eine anonyme ID identifiziert.
diff --git a/lib/plugins/popularity/lang/hu/lang.php b/lib/plugins/popularity/lang/hu/lang.php
index 5dcd1adf0..5ee40eacc 100644
--- a/lib/plugins/popularity/lang/hu/lang.php
+++ b/lib/plugins/popularity/lang/hu/lang.php
@@ -8,6 +8,7 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
$lang['name'] = 'Visszajelzés a DokuWiki használatáról (sok időt vehet igénybe a betöltése)';
$lang['submit'] = 'Adatok elküldése';
diff --git a/lib/plugins/popularity/lang/ko/intro.txt b/lib/plugins/popularity/lang/ko/intro.txt
index c75c57ba5..0c884546a 100644
--- a/lib/plugins/popularity/lang/ko/intro.txt
+++ b/lib/plugins/popularity/lang/ko/intro.txt
@@ -1,6 +1,6 @@
====== 인기도 조사 ======
-설치된 위키의 익명 정보를 DokuWiki 개발자에게 보냅니다. 이 [[doku>popularity|도구]]는 DokuWiki가 실제 사용자에게 어떻게 사용되는지 DokuWiki 개발자에게 알려줌으로써 이 후 개발 시 참고가 됩니다.
+설치된 위키의 익명 정보를 DokuWiki 개발자에게 보냅니다. 이 [[doku>ko:popularity|도구]]는 DokuWiki가 실제 사용자에게 어떻게 사용되는지 DokuWiki 개발자에게 알려줌으로써 이 후 개발 시 참고가 됩니다.
설치된 위키가 커짐에 따라서 이 과정을 반복할 필요가 있습니다. 반복된 데이터는 익명 ID로 구별되어집니다.
diff --git a/lib/plugins/popularity/lang/sv/lang.php b/lib/plugins/popularity/lang/sv/lang.php
index 90d820ba0..942a708c4 100644
--- a/lib/plugins/popularity/lang/sv/lang.php
+++ b/lib/plugins/popularity/lang/sv/lang.php
@@ -1,8 +1,9 @@
<?php
+
/**
- * Swedish language file
- *
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -11,7 +12,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php
index ccad6e9de..beff10ced 100644
--- a/lib/plugins/revert/admin.php
+++ b/lib/plugins/revert/admin.php
@@ -128,7 +128,7 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin {
}
$cnt++;
- $date = strftime($conf['dformat'],$recent['date']);
+ $date = dformat($recent['date']);
echo ($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) ? '<li class="minor">' : '<li>';
echo '<div class="li">';
diff --git a/lib/plugins/revert/lang/de-informal/intro.txt b/lib/plugins/revert/lang/de-informal/intro.txt
index d5a092155..a1733af3a 100644
--- a/lib/plugins/revert/lang/de-informal/intro.txt
+++ b/lib/plugins/revert/lang/de-informal/intro.txt
@@ -1,3 +1,3 @@
-====== Seiten wieder herstellen ======
+====== Seiten wiederherstellen ======
-Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Geben Sie zunächst einen Suchbegriff (z.B. eine Spam URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem Sie sich vergewissert haben, dass die gefundenen Seiten wirklich Spam enthalten, können Sie die Seiten wieder herstellen.
+Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Gib zunächst einen Suchbegriff (z. B. eine Spam-URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem du dich vergewissert hast, dass die gefundenen Seiten wirklich Spam enthalten, kannst du die Seiten wiederherstellen.
diff --git a/lib/plugins/revert/lang/de-informal/lang.php b/lib/plugins/revert/lang/de-informal/lang.php
index 3a96429c7..7ca141e3c 100644
--- a/lib/plugins/revert/lang/de-informal/lang.php
+++ b/lib/plugins/revert/lang/de-informal/lang.php
@@ -9,13 +9,15 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
+ * @author Volker Bödker <volker@boedker.de>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
-$lang['menu'] = 'Zurückstellungsmanager';
+$lang['menu'] = 'Seiten wiederherstellen';
$lang['filter'] = 'Durchsuche als Spam markierte Seiten';
$lang['revert'] = 'Setze ausgewählte Seiten zurück.';
-$lang['reverted'] = '%s zu Revision %s zurückgesetzt';
+$lang['reverted'] = '%s zu Revision %s wiederhergestellt';
$lang['removed'] = '%s entfernt';
-$lang['revstart'] = 'Zurückstellungsprozess gestartet. Dies kann eine längere Zeit dauern. Wenn das Skript vor Fertigstellung stoppt, solltest du es in kleineren Stücken versuchen.';
-$lang['revstop'] = 'Zurückstellungsprozess erfolgreich beendet.';
-$lang['note1'] = 'Beachte: Diese Suche berücksichtigt Gross- und Kleinschreibung';
-$lang['note2'] = 'Beachte: Diese Seite wid zurückgestellt auf die letzte Version, die nicht den Spam-Ausdruck <i>%s</i> enthält.';
+$lang['revstart'] = 'Wiederherstellung gestartet. Dies kann eine längere Zeit dauern. Wenn das Skript vor Fertigstellung stoppt, solltest du es in kleineren Stücken versuchen.';
+$lang['revstop'] = 'Wiederherstellung erfolgreich beendet.';
+$lang['note1'] = 'Beachte: Diese Suche berücksichtigt Groß- und Kleinschreibung';
+$lang['note2'] = 'Beachte: Diese Seite wird wiederhergestellt auf die letzte Version, die nicht den Spam-Begriff <i>%s</i> enthält.';
diff --git a/lib/plugins/revert/lang/de/intro.txt b/lib/plugins/revert/lang/de/intro.txt
index d5a092155..fe74461d9 100644
--- a/lib/plugins/revert/lang/de/intro.txt
+++ b/lib/plugins/revert/lang/de/intro.txt
@@ -1,3 +1,3 @@
-====== Seiten wieder herstellen ======
+====== Seiten wiederherstellen ======
-Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Geben Sie zunächst einen Suchbegriff (z.B. eine Spam URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem Sie sich vergewissert haben, dass die gefundenen Seiten wirklich Spam enthalten, können Sie die Seiten wieder herstellen.
+Dieses Plugin dient der automatischen Wiederherstellung von Seiten nach einem Spam-Angriff. Geben Sie zunächst einen Suchbegriff (z. B. eine Spam-URL) ein um eine Liste betroffener Seiten zu erhalten. Nachdem Sie sich vergewissert haben, dass die gefundenen Seiten wirklich Spam enthalten, können Sie die Seiten wiederherstellen.
diff --git a/lib/plugins/revert/lang/de/lang.php b/lib/plugins/revert/lang/de/lang.php
index b430ce876..2db065f21 100644
--- a/lib/plugins/revert/lang/de/lang.php
+++ b/lib/plugins/revert/lang/de/lang.php
@@ -1,6 +1,6 @@
<?php
/**
- * Germanlanguage file
+ * German language file
*
* @author Michael Klier <chi@chimeric.de>
* @author Leo Moll <leo@yeasoft.com>
@@ -16,13 +16,14 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Paul Lachewsky <kaeptn.haddock@gmail.com>
* @author Pierre Corell <info@joomla-praxis.de>
+ * @author Matthias Schulte <dokuwiki@lupo49.de>
*/
-$lang['menu'] = 'Seiten wieder herstellen';
+$lang['menu'] = 'Seiten wiederherstellen';
$lang['filter'] = 'Nach betroffenen Seiten suchen';
-$lang['revert'] = 'Ausgewählte Seiten wieder herstellen';
+$lang['revert'] = 'Ausgewählte Seiten wiederherstellen';
$lang['reverted'] = '%s wieder hergestellt zu Version %s';
$lang['removed'] = '%s entfernt';
$lang['revstart'] = 'Wiederherstellung gestartet. Dies kann einige Zeit dauern. Wenn das Script abbricht, bevor alle Seiten wieder hergestellt wurden, reduzieren Sie die Anzahl der Seiten und wiederholen Sie den Vorgang.';
$lang['revstop'] = 'Wiederherstellung erfolgreich abgeschlossen.';
$lang['note1'] = 'Anmerkung: diese Suche unterscheidet Groß- und Kleinschreibung';
-$lang['note2'] = 'Anmerkung: die Seite wird zur letzten Version, die nicht den angegebenen Spam Begriff <i>%s</i> enthält, wieder hergestellt.';
+$lang['note2'] = 'Anmerkung: die Seite wird wiederhergestellt auf die letzte Version, die nicht den angegebenen Spam Begriff <i>%s</i> enthält.';
diff --git a/lib/plugins/revert/lang/hu/lang.php b/lib/plugins/revert/lang/hu/lang.php
index 058a63196..051e7b7d7 100644
--- a/lib/plugins/revert/lang/hu/lang.php
+++ b/lib/plugins/revert/lang/hu/lang.php
@@ -8,6 +8,7 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
$lang['menu'] = 'Visszaállítás kezelő (anti-SPAM)';
$lang['filter'] = 'SPAM tartalmú oldalak keresése';
@@ -16,5 +17,5 @@ $lang['reverted'] = '%s a következő változatra lett visszaállí
$lang['removed'] = '%s törölve';
$lang['revstart'] = 'A visszaállítási folyamat elindult. Ez hosszú ideig eltarthat. Ha időtúllépés miatt nem tud lefutni, kisebb darabbal kell próbálkozni.';
$lang['revstop'] = 'A visszaállítási folyamat sikeresen befejeződött.';
-$lang['note1'] = 'Megjegyzés: a keresés kisbetű-nagybetűre érzékeny';
+$lang['note1'] = 'Megjegyzés: a keresés kisbetű-nagybetű érzékeny';
$lang['note2'] = 'Megjegyzés: Az oldalt az utolsó olyan változatra állítjuk vissza, ami nem tartalmazza a megadott spam kifejezést: <i>%s</i>.';
diff --git a/lib/plugins/revert/lang/sv/lang.php b/lib/plugins/revert/lang/sv/lang.php
index 4a727b339..4a5b944f6 100644
--- a/lib/plugins/revert/lang/sv/lang.php
+++ b/lib/plugins/revert/lang/sv/lang.php
@@ -1,10 +1,11 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -13,9 +14,9 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
+ * @author Henrik <henrik@idealis.se>
*/
$lang['menu'] = 'Hantera återställningar';
$lang['filter'] = 'Sök efter spamsidor';
diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php
index 445836a50..3c8d38c5e 100644
--- a/lib/plugins/usermanager/admin.php
+++ b/lib/plugins/usermanager/admin.php
@@ -270,7 +270,9 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
$this->_htmlInputField($cmd."_usergroups","usergroups",$this->lang["user_groups"],$groups,$this->_auth->canDo("modGroups"),$indent+6);
if ($this->_auth->canDo("modPass")) {
- $notes[] = $this->lang['note_pass'];
+ if ($cmd == 'add') {
+ $notes[] = $this->lang['note_pass'];
+ }
if ($user) {
$notes[] = $this->lang['note_notify'];
}
@@ -296,11 +298,15 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
ptln(" </tr>",$indent);
ptln(" </tbody>",$indent);
ptln(" </table>",$indent);
- ptln(" </div>",$indent);
-
- foreach ($notes as $note)
- ptln("<div class=\"fn\">".$note."</div>",$indent);
+ if ($notes) {
+ ptln(" <ul class=\"notes\">");
+ foreach ($notes as $note) {
+ ptln(" <li><span class=\"li\">".$note."</span></li>",$indent);
+ }
+ ptln(" </ul>");
+ }
+ ptln(" </div>",$indent);
ptln("</form>",$indent);
}
@@ -311,6 +317,9 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
if($name == 'userpass'){
$fieldtype = 'password';
$autocomp = 'autocomplete="off"';
+ }elseif($name == 'usermail'){
+ $fieldtype = 'email';
+ $autocomp = '';
}else{
$fieldtype = 'text';
$autocomp = '';
diff --git a/lib/plugins/usermanager/lang/de-informal/lang.php b/lib/plugins/usermanager/lang/de-informal/lang.php
index 07390854f..791cfa74f 100644
--- a/lib/plugins/usermanager/lang/de-informal/lang.php
+++ b/lib/plugins/usermanager/lang/de-informal/lang.php
@@ -9,6 +9,7 @@
* @author Christian Wichmann <nospam@zone0.de>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
+ * @author Volker Bödker <volker@boedker.de>
*/
$lang['menu'] = 'Benutzerverwaltung';
$lang['noauth'] = '(Benutzeranmeldung ist nicht verfügbar)';
diff --git a/lib/plugins/usermanager/lang/de/lang.php b/lib/plugins/usermanager/lang/de/lang.php
index 0dd90cc68..2b9755de8 100644
--- a/lib/plugins/usermanager/lang/de/lang.php
+++ b/lib/plugins/usermanager/lang/de/lang.php
@@ -45,16 +45,16 @@ $lang['delete_ok'] = '%d Benutzer gelöscht';
$lang['delete_fail'] = '%d konnten nicht gelöscht werden.';
$lang['update_ok'] = 'Benutzerdaten erfolgreich geändert.';
$lang['update_fail'] = 'Änderung der Benutzerdaten fehlgeschlagen.';
-$lang['update_exists'] = 'Nutzername konnte nicht geändert werden, weil der angegebene Nutzer (%s) bereits existiert (alle anderen Änderungen wurden durchgeführt).';
+$lang['update_exists'] = 'Benutzername konnte nicht geändert werden, weil der angegebene Benutzer (%s) bereits existiert (alle anderen Änderungen wurden durchgeführt).';
$lang['start'] = 'Anfang';
$lang['prev'] = 'Vorherige';
$lang['next'] = 'Nächste';
$lang['last'] = 'Ende';
-$lang['edit_usermissing'] = 'Der ausgewählte Nutzer wurde nicht gefunden. Möglicherweise wurde er gelöscht oder der Nutzer wurde anderswo geändert.';
+$lang['edit_usermissing'] = 'Der ausgewählte Benutzer wurde nicht gefunden. Möglicherweise wurde er gelöscht oder der Benutzer wurde anderswo geändert.';
$lang['user_notify'] = 'Nutzer benachrichtigen';
$lang['note_notify'] = 'Benachrichtigungs-E-Mails werden nur versandt, wenn ein neues Passwort vergeben wurde.';
-$lang['note_group'] = 'Neue Nutzer werden der Standard-Gruppe (%s) hinzugefügt, wenn keine Gruppe angegeben wurde.';
-$lang['note_pass'] = 'Das Passwort wird automatisch generiert, wenn das entsprechende Feld leergelassen wird und die Benachrichtigung des Nutzers aktiviert ist.';
+$lang['note_group'] = 'Neue Benutzer werden der Standard-Gruppe (%s) hinzugefügt, wenn keine Gruppe angegeben wurde.';
+$lang['note_pass'] = 'Das Passwort wird automatisch generiert, wenn das entsprechende Feld leergelassen wird und die Benachrichtigung des Benutzers aktiviert ist.';
$lang['add_ok'] = 'Nutzer erfolgreich angelegt';
$lang['add_fail'] = 'Nutzer konnte nicht angelegt werden';
$lang['notify_ok'] = 'Benachrichtigungsmail wurde versandt';
diff --git a/lib/plugins/usermanager/lang/hu/lang.php b/lib/plugins/usermanager/lang/hu/lang.php
index 9b9740cb0..71a5b4bc9 100644
--- a/lib/plugins/usermanager/lang/hu/lang.php
+++ b/lib/plugins/usermanager/lang/hu/lang.php
@@ -8,12 +8,13 @@
* @author Szabó Dávid <szabo.david@gyumolcstarhely.hu>
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
+ * @author Marton Sebok <sebokmarton@gmail.com>
*/
$lang['menu'] = 'Felhasználók kezelése';
$lang['noauth'] = '(A felhasználói azonosítás nem működik.)';
$lang['nosupport'] = '(A felhasználók kezelése nem támogatott.)';
$lang['badauth'] = 'nem érvényes autentikációs technika';
-$lang['user_id'] = 'Felhasználó azonosító';
+$lang['user_id'] = 'Felhasználói azonosító';
$lang['user_pass'] = 'Jelszó';
$lang['user_name'] = 'Név';
$lang['user_mail'] = 'E-mail';
@@ -30,8 +31,8 @@ $lang['search'] = 'Keresés';
$lang['search_prompt'] = 'Keresés';
$lang['clear'] = 'Keresési szűrés törlése';
$lang['filter'] = 'Szűrés';
-$lang['summary'] = '%1$d-%2$d. felhasználókat mutatom a(z) %3$d megtalált felhasználóból. %4$d felhasználó van összesen.';
-$lang['nonefound'] = 'Nem találtam ilyen felhasználót. %d felhasználó van összesen.';
+$lang['summary'] = '%1$d-%2$d. felhasználók megjelenítése a(z) %3$d megtalált felhasználóból. %4$d felhasználó van összesen.';
+$lang['nonefound'] = 'Nincs ilyen felhasználó. %d felhasználó van összesen.';
$lang['delete_ok'] = '%d felhasználó törölve.';
$lang['delete_fail'] = '%d felhasználót nem sikerült törölni.';
$lang['update_ok'] = 'A felhasználó adatait sikeresen elmentettem.';
@@ -45,7 +46,7 @@ $lang['edit_usermissing'] = 'A kiválasztott felhasználót nem találom, a
$lang['user_notify'] = 'Felhasználó értesítése';
$lang['note_notify'] = 'Csak akkor küld értesítő e-mailt, ha a felhasználó új jelszót kapott.';
$lang['note_group'] = 'Ha nincs csoport meghatározva, az új felhasználó az alapértelmezett csoportba (%s) kerül.';
-$lang['note_pass'] = 'Ha a baloldali mező üres, és a felhasználó értesítés aktív, akkor generált jelszó lesz.';
+$lang['note_pass'] = 'Ha a baloldali mező üres és a felhasználó értesítés aktív, akkor a jelszót a rendszer generálja.';
$lang['add_ok'] = 'A felhasználó sikeresen hozzáadva.';
$lang['add_fail'] = 'A felhasználó hozzáadása nem sikerült.';
$lang['notify_ok'] = 'Értesítő levél elküldve.';
diff --git a/lib/plugins/usermanager/lang/sv/lang.php b/lib/plugins/usermanager/lang/sv/lang.php
index f8b530d90..68f5bbc31 100644
--- a/lib/plugins/usermanager/lang/sv/lang.php
+++ b/lib/plugins/usermanager/lang/sv/lang.php
@@ -1,10 +1,11 @@
<?php
+
/**
- * Swedish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Per Foreby <per@foreby.se>
* @author Nicklas Henriksson <nicklas[at]nihe.se>
- * @author Håkan Sandell <hakan.sandell[at]mydata.se>
+ * @author Håkan Sandell <hakan.sandell@home.se>
* @author Dennis Karlsson
* @author Tormod Otter Johansson <tormod@latast.se>
* @author emil@sys.nu
@@ -13,7 +14,6 @@
* @author Emil Lind <emil@sys.nu>
* @author Bogge Bogge <bogge@bogge.com>
* @author Peter Åström <eaustreum@gmail.com>
- * @author Håkan Sandell <hakan.sandell@home.se>
* @author mikael@mallander.net
* @author Smorkster Andersson smorkster@gmail.com
*/
diff --git a/lib/plugins/usermanager/style.css b/lib/plugins/usermanager/style.css
index ff8e5d9d1..506bd7928 100644
--- a/lib/plugins/usermanager/style.css
+++ b/lib/plugins/usermanager/style.css
@@ -13,6 +13,10 @@
#user__manager table {
margin-bottom: 1em;
}
+#user__manager ul.notes {
+ padding-left: 0;
+ padding-right: 1.4em;
+}
#user__manager input.button[disabled] {
color: #ccc!important;
border-color: #ccc!important;
diff --git a/lib/scripts/behaviour.js b/lib/scripts/behaviour.js
index f1c46bf4c..85ddf503e 100644
--- a/lib/scripts/behaviour.js
+++ b/lib/scripts/behaviour.js
@@ -5,6 +5,7 @@
* @author Adrian Lang <mail@adrianlang.de>
*/
jQuery.fn.dw_hide = function(fn) {
+ this.attr('aria-expanded', 'false');
return this.slideUp('fast', fn);
};
@@ -15,6 +16,7 @@ jQuery.fn.dw_hide = function(fn) {
* @author Adrian Lang <mail@adrianlang.de>
*/
jQuery.fn.dw_show = function(fn) {
+ this.attr('aria-expanded', 'true');
return this.slideDown('fast', fn);
};
diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js
index 5a5e829bd..b1dbff683 100644
--- a/lib/scripts/edit.js
+++ b/lib/scripts/edit.js
@@ -23,7 +23,7 @@ function createToolButton(icon,label,key,id,classname){
$btn.addClass(classname);
}
- $btn.attr('title', label);
+ $btn.attr('title', label).attr('aria-controls', 'wiki__text');
if(key){
$btn.attr('title', label + ' ['+key.toUpperCase()+']')
.attr('accessKey', key);
@@ -40,6 +40,7 @@ function createToolButton(icon,label,key,id,classname){
icon = DOKU_BASE + 'lib/images/toolbar/' + icon;
}
$ico.attr('src', icon);
+ $ico.attr('alt', '');
$ico.attr('width', 16);
$ico.attr('height', 16);
$btn.append($ico);
@@ -76,6 +77,7 @@ function createPicker(id,props,edid){
function $makebutton(title) {
var $btn = jQuery(document.createElement('button'))
.addClass('pickerbutton').attr('title', title)
+ .attr('aria-controls', edid)
.bind('click', bind(pickerInsert, title, edid))
.appendTo($picker);
return $btn;
@@ -93,6 +95,7 @@ function createPicker(id,props,edid){
}
jQuery(document.createElement('img'))
.attr('src', item)
+ .attr('alt', '')
.appendTo($makebutton(key));
}else if (typeof item == 'string'){
// a list of text -> treat as text picker
@@ -132,9 +135,9 @@ function pickerInsert(text,edid){
function addBtnActionSignature($btn, props, edid) {
if(typeof SIG != 'undefined' && SIG != ''){
$btn.bind('click', bind(insertAtCarret,edid,SIG));
- return true;
+ return edid;
}
- return false;
+ return '';
}
/**
diff --git a/lib/scripts/editor.js b/lib/scripts/editor.js
index 042e34608..2c0924eb7 100644
--- a/lib/scripts/editor.js
+++ b/lib/scripts/editor.js
@@ -65,6 +65,7 @@ var dw_editor = {
], function (_, img) {
jQuery(document.createElement('IMG'))
.attr('src', DOKU_BASE+'lib/images/' + img[0] + '.gif')
+ .attr('alt', '')
.click(img[1])
.appendTo($ctl);
});
diff --git a/lib/scripts/helpers.js b/lib/scripts/helpers.js
index d6f36967d..0b32e8781 100644
--- a/lib/scripts/helpers.js
+++ b/lib/scripts/helpers.js
@@ -3,25 +3,6 @@
*/
/**
- * Very simplistic Flash plugin check, probably works for Flash 8 and higher only
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-function hasFlash(version){
- var ver = 0;
- try{
- if(navigator.plugins != null && navigator.plugins.length > 0){
- ver = navigator.plugins["Shockwave Flash"].description.split(' ')[2].split('.')[0];
- }else{
- ver = (new ActiveXObject("ShockwaveFlash.ShockwaveFlash"))
- .GetVariable("$version").split(' ')[1].split(',')[0];
- }
- }catch(e){ }
-
- return ver >= version;
-}
-
-/**
* A PHP-style substr_replace
*
* Supports negative start and length and omitting length, but not
@@ -68,3 +49,18 @@ function bind(fnc/*, ... */) {
static_args.concat(Aps.call(arguments, 0)));
};
}
+
+/**
+ * Report an error from a JS file to the console
+ *
+ * @param e The error object
+ * @param file The file in which the error occurred
+ */
+function logError(e, file) {
+ if (window.console && console.error) {
+ console.error('The error "%s: %s" occurred in file "%s". ' +
+ 'If this is in a plugin try updating or disabling the plugin, ' +
+ 'if this is in a template try updating the template or switching to the "dokuwiki" template.',
+ e.name, e.message, file);
+ }
+}
diff --git a/lib/scripts/jquery/jquery.cookie.js b/lib/scripts/jquery/jquery.cookie.js
index 2d4c05a84..c4f99af00 100644
--- a/lib/scripts/jquery/jquery.cookie.js
+++ b/lib/scripts/jquery/jquery.cookie.js
@@ -1,13 +1,19 @@
/*!
- * jQuery Cookie Plugin v1.3
+ * jQuery Cookie Plugin v1.3.1
* https://github.com/carhartl/jquery-cookie
*
- * Copyright 2011, Klaus Hartl
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.opensource.org/licenses/GPL-2.0
+ * Copyright 2013 Klaus Hartl
+ * Released under the MIT license
*/
-(function ($, document, undefined) {
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+}(function ($) {
var pluses = /\+/g;
@@ -19,16 +25,22 @@
return decodeURIComponent(s.replace(pluses, ' '));
}
+ function converted(s) {
+ if (s.indexOf('"') === 0) {
+ // This is a quoted cookie as according to RFC2068, unescape
+ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
+ }
+ try {
+ return config.json ? JSON.parse(s) : s;
+ } catch(er) {}
+ }
+
var config = $.cookie = function (key, value, options) {
// write
if (value !== undefined) {
options = $.extend({}, config.defaults, options);
- if (value === null) {
- options.expires = -1;
- }
-
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
@@ -37,7 +49,9 @@
value = config.json ? JSON.stringify(value) : String(value);
return (document.cookie = [
- encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
+ config.raw ? key : encodeURIComponent(key),
+ '=',
+ config.raw ? value : encodeURIComponent(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
@@ -48,25 +62,34 @@
// read
var decode = config.raw ? raw : decoded;
var cookies = document.cookie.split('; ');
+ var result = key ? undefined : {};
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
- if (decode(parts.shift()) === key) {
- var cookie = decode(parts.join('='));
- return config.json ? JSON.parse(cookie) : cookie;
+ var name = decode(parts.shift());
+ var cookie = decode(parts.join('='));
+
+ if (key && key === name) {
+ result = converted(cookie);
+ break;
+ }
+
+ if (!key) {
+ result[name] = converted(cookie);
}
}
- return null;
+ return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
- if ($.cookie(key) !== null) {
- $.cookie(key, null, options);
+ if ($.cookie(key) !== undefined) {
+ // Must not alter options, thus extending a fresh object...
+ $.cookie(key, '', $.extend({}, options, { expires: -1 }));
return true;
}
return false;
};
-})(jQuery, document);
+}));
diff --git a/lib/scripts/media.js b/lib/scripts/media.js
index 182d5fefe..8ca21ecab 100644
--- a/lib/scripts/media.js
+++ b/lib/scripts/media.js
@@ -921,23 +921,4 @@ var dw_mediamanager = {
}
};
-// moved from helpers.js temporarily here
-/**
- * Very simplistic Flash plugin check, probably works for Flash 8 and higher only
- *
- */
-function hasFlash(version){
- var ver = 0, axo;
- try{
- if(navigator.plugins !== null && navigator.plugins.length > 0){
- ver = navigator.plugins["Shockwave Flash"].description.split(' ')[2].split('.')[0];
- }else{
- axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
- ver = axo.GetVariable("$version").split(' ')[1].split(',')[0];
- }
- }catch(e){ }
-
- return ver >= version;
-}
-
jQuery(dw_mediamanager.init);
diff --git a/lib/scripts/page.js b/lib/scripts/page.js
index 4ab0bf9b5..7b4958d82 100644
--- a/lib/scripts/page.js
+++ b/lib/scripts/page.js
@@ -62,7 +62,9 @@ dw_page = {
$fndiv = jQuery(document.createElement('div'))
.attr('id', popup_id)
.addClass('insitu-footnote JSpopup')
- .mouseleave(function () {jQuery(this).hide();});
+ .attr('aria-hidden', 'true')
+ .mouseleave(function () {jQuery(this).hide().attr('aria-hidden', 'true');})
+ .attr('role', 'tooltip');
jQuery('.dokuwiki:first').append($fndiv);
}
@@ -97,7 +99,7 @@ dw_page = {
content = content.replace(/\bid=(['"])([^"']+)\1/gi,'id="insitu__$2');
// now put the content into the wrapper
- dw_page.insituPopup(this, 'insitu__fn').html(content).show();
+ dw_page.insituPopup(this, 'insitu__fn').html(content).show().attr('aria-hidden', 'false');
},
/**
diff --git a/lib/scripts/toolbar.js b/lib/scripts/toolbar.js
index e33fa8677..88cae1e8c 100644
--- a/lib/scripts/toolbar.js
+++ b/lib/scripts/toolbar.js
@@ -52,8 +52,13 @@ function initToolbar(tbid,edid,tb, allowblock){
// type is a init function -> execute it
actionFunc = 'addBtnAction'+val.type.charAt(0).toUpperCase()+val.type.substring(1);
if( jQuery.isFunction(window[actionFunc]) ){
- if(window[actionFunc]($btn, val, edid)){
+ var pickerid = window[actionFunc]($btn, val, edid);
+ if(pickerid !== ''){
$toolbar.append($btn);
+ $btn.attr('aria-controls', pickerid);
+ if (actionFunc === 'addBtnActionPicker') {
+ $btn.attr('aria-haspopup', 'true');
+ }
}
return;
}
@@ -190,16 +195,17 @@ function tb_autohead(btn, props, edid){
*/
function addBtnActionPicker($btn, props, edid) {
var pickerid = 'picker'+(pickercounter++);
- createPicker(pickerid, props, edid);
+ var picker = createPicker(pickerid, props, edid);
+ jQuery(picker).attr('aria-hidden', 'true');
$btn.click(
function() {
pickerToggle(pickerid,$btn);
- return false;
+ return '';
}
);
- return true;
+ return pickerid;
}
/**
@@ -216,22 +222,26 @@ function addBtnActionLinkwiz($btn, props, edid) {
jQuery($btn).click(function(){
dw_linkwiz.val = props;
dw_linkwiz.toggle();
- return false;
+ return '';
});
- return true;
+ return 'link__wiz';
}
/**
- * Show/Hide a previosly created picker window
+ * Show/Hide a previously created picker window
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function pickerToggle(pickerid,$btn){
var $picker = jQuery('#' + pickerid),
pos = $btn.offset();
- $picker.toggleClass('a11y')
- .offset({left: pos.left+3, top: pos.top+$btn[0].offsetHeight+3});
+ if ($picker.hasClass('a11y')) {
+ $picker.removeClass('a11y').attr('aria-hidden', 'false');
+ } else {
+ $picker.addClass('a11y').attr('aria-hidden', 'true');
+ }
+ $picker.offset({left: pos.left+3, top: pos.top+$btn[0].offsetHeight+3});
}
/**
@@ -253,4 +263,5 @@ function fixtxt(str){
jQuery(function () {
initToolbar('tool__bar','wiki__text',toolbar);
+ jQuery('#tool__bar').attr('role', 'toolbar');
});
diff --git a/lib/scripts/tree.js b/lib/scripts/tree.js
index 96763053d..c4e1da3f7 100644
--- a/lib/scripts/tree.js
+++ b/lib/scripts/tree.js
@@ -14,6 +14,12 @@ jQuery.fn.dw_tree = function(overrides) {
init: function () {
this.$obj.delegate(this.toggle_selector, 'click', this,
this.toggle);
+ jQuery('ul:first', this.$obj).attr('role', 'tree');
+ jQuery('ul', this.$obj).not(':first').attr('role', 'group');
+ jQuery('li', this.$obj).attr('role', 'treeitem');
+ jQuery('li.open > ul', this.$obj).attr('aria-expanded', 'true');
+ jQuery('li.closed > ul', this.$obj).attr('aria-expanded', 'false');
+ jQuery('li.closed', this.$obj).attr('aria-live', 'assertive');
},
/**
@@ -35,8 +41,14 @@ jQuery.fn.dw_tree = function(overrides) {
$listitem = $clicky.closest('li');
$sublist = $listitem.find('ul').first();
opening = $listitem.hasClass('closed');
- $listitem.toggleClass('open closed');
dw_tree.toggle_display($clicky, opening);
+ if ($sublist.is(':visible')) {
+ $listitem.removeClass('open').addClass('closed');
+ $sublist.attr('aria-expanded', 'false');
+ } else {
+ $listitem.removeClass('closed').addClass('open');
+ $sublist.attr('aria-expanded', 'true');
+ }
// if already open, close by hiding the sublist
if (!opening) {
@@ -48,6 +60,8 @@ jQuery.fn.dw_tree = function(overrides) {
$sublist.hide();
if (typeof data !== 'undefined') {
$sublist.html(data);
+ $sublist.parent().attr('aria-busy', 'false').removeAttr('aria-live');
+ jQuery('li.closed', $sublist).attr('aria-live', 'assertive');
}
if ($listitem.hasClass('open')) {
// Only show if user didn’t close the list since starting
@@ -63,11 +77,11 @@ jQuery.fn.dw_tree = function(overrides) {
}
//prepare the new ul
- $sublist = jQuery('<ul class="idx"/>');
+ $sublist = jQuery('<ul class="idx" role="group"/>');
$listitem.append($sublist);
timeout = window.setTimeout(
- bind(show_sublist, '<li><img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="loading..." title="loading..." /></li>'), dw_tree.throbber_delay);
+ bind(show_sublist, '<li aria-busy="true"><img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="loading..." title="loading..." /></li>'), dw_tree.throbber_delay);
dw_tree.load_data(function (data) {
window.clearTimeout(timeout);
diff --git a/lib/scripts/tw-sack.js b/lib/scripts/tw-sack.js
index cc988f5be..b0e570151 100644
--- a/lib/scripts/tw-sack.js
+++ b/lib/scripts/tw-sack.js
@@ -2,6 +2,7 @@
/* ©2005 Gregory Wild-Smith */
/* www.twilightuniverse.com */
/* Software licenced under a modified X11 licence, see documentation or authors website for more details */
+/* @deprecated */
function sack(file){
this.AjaxFailedAlert = "Your browser does not support the enhanced functionality of this website, and therefore you will have an experience that differs from the intended one.\n";
diff --git a/lib/tpl/dokuwiki/css/_admin.css b/lib/tpl/dokuwiki/css/_admin.css
index c8f3694b5..a9518d0ed 100644
--- a/lib/tpl/dokuwiki/css/_admin.css
+++ b/lib/tpl/dokuwiki/css/_admin.css
@@ -50,7 +50,7 @@
.dokuwiki #admin__version {
clear: left;
float: right;
- color: __text_neu__;
+ color: @ini_text_neu;
background-color: inherit;
}
[dir=rtl] .dokuwiki #admin__version {
diff --git a/lib/tpl/dokuwiki/css/_diff.css b/lib/tpl/dokuwiki/css/_diff.css
index 58c24b5c7..b7c82d829 100644
--- a/lib/tpl/dokuwiki/css/_diff.css
+++ b/lib/tpl/dokuwiki/css/_diff.css
@@ -19,7 +19,7 @@
/* table header */
.dokuwiki table.diff th {
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
font-size: 110%;
font-weight: normal;
}
diff --git a/lib/tpl/dokuwiki/css/_edit.css b/lib/tpl/dokuwiki/css/_edit.css
index 92ce62126..f40aaa891 100644
--- a/lib/tpl/dokuwiki/css/_edit.css
+++ b/lib/tpl/dokuwiki/css/_edit.css
@@ -16,7 +16,7 @@
}
#draft__status {
float: right;
- color: __text_alt__;
+ color: @ini_text_alt;
background-color: inherit;
}
[dir=rtl] #draft__status {
@@ -35,8 +35,8 @@
/* picker popups (outside of .dokuwiki) */
div.picker {
width: 300px;
- border: 1px solid __border__;
- background-color: __background_alt__;
+ border: 1px solid @ini_border;
+ background-color: @ini_background_alt;
color: inherit;
}
/* picker for headlines */
@@ -106,7 +106,7 @@ div.picker button.toolbutton {
}
/* change background colour if summary is missing */
.dokuwiki .editBar .summary input.missing {
- color: __text__;
+ color: @ini_text;
background-color: #ffcccc;
}
@@ -114,7 +114,7 @@ div.picker button.toolbutton {
********************************************************************/
.dokuwiki div.preview {
- border: dotted __border__;
+ border: dotted @ini_border;
border-width: .2em 0;
padding: 1.4em 0;
margin-bottom: 1.4em;
@@ -138,6 +138,6 @@ div.picker button.toolbutton {
.dokuwiki div.section_highlight {
margin: 0 -1em; /* negative side margin = side padding + side border */
padding: 0 .5em;
- border: solid __background_alt__;
+ border: solid @ini_background_alt;
border-width: 0 .5em;
}
diff --git a/lib/tpl/dokuwiki/css/_fileuploader.css b/lib/tpl/dokuwiki/css/_fileuploader.css
index 42004de28..3c2cd4683 100644
--- a/lib/tpl/dokuwiki/css/_fileuploader.css
+++ b/lib/tpl/dokuwiki/css/_fileuploader.css
@@ -42,8 +42,8 @@
height: 100%;
min-height: 70px;
z-index: 2;
- background: __background_neu__;
- color: __text__;
+ background: @ini_background_neu;
+ color: @ini_text;
text-align: center;
}
@@ -57,7 +57,7 @@
}
.qq-upload-drop-area-active {
- background: __background_alt__;
+ background: @ini_background_alt;
}
/* list of files to upload */
@@ -70,7 +70,7 @@ div.qq-uploader ul {
.qq-uploader li {
margin: 0 0 5px;
- color: __text__;
+ color: @ini_text;
}
.qq-uploader li span,
diff --git a/lib/tpl/dokuwiki/css/_footnotes.css b/lib/tpl/dokuwiki/css/_footnotes.css
index a20f2964e..5d5f7ca30 100644
--- a/lib/tpl/dokuwiki/css/_footnotes.css
+++ b/lib/tpl/dokuwiki/css/_footnotes.css
@@ -16,7 +16,7 @@ div.insitu-footnote {
/*____________ footnotes at the bottom of the page ____________*/
.dokuwiki div.footnotes {
- border-top: 1px solid __border__;
+ border-top: 1px solid @ini_border;
padding: .5em 0 0 0;
margin: 1em 0 0 0;
clear: both;
diff --git a/lib/tpl/dokuwiki/css/_forms.css b/lib/tpl/dokuwiki/css/_forms.css
index 6744750ba..4d3f2b97a 100644
--- a/lib/tpl/dokuwiki/css/_forms.css
+++ b/lib/tpl/dokuwiki/css/_forms.css
@@ -48,7 +48,7 @@
.dokuwiki fieldset {
width: 400px;
text-align: center;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
padding: 0.5em;
margin: auto;
}
@@ -79,7 +79,10 @@
#dw__register fieldset {
padding-bottom: 0.7em;
}
-
+#dw__profiledelete {
+ display: block;
+ margin-top: 2.8em;
+}
/**
* Styles for the subscription page
diff --git a/lib/tpl/dokuwiki/css/_media_fullscreen.css b/lib/tpl/dokuwiki/css/_media_fullscreen.css
index 8d5e1e8ca..28e347882 100644
--- a/lib/tpl/dokuwiki/css/_media_fullscreen.css
+++ b/lib/tpl/dokuwiki/css/_media_fullscreen.css
@@ -38,7 +38,7 @@
}
#mediamanager__page .panelHeader {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
margin: 0 10px 10px 0;
padding: 10px 10px 8px;
text-align: left;
@@ -68,7 +68,7 @@
background: transparent url(../../images/resizecol.png) center center no-repeat;
}
#mediamanager__page .ui-resizable-e:hover {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
@@ -99,10 +99,10 @@
margin: 0 0 0 .3em;
border-radius: .5em .5em 0 0;
font-weight: normal;
- background-color: __background_alt__;
- color: __text__;
- border: 1px solid __border__;
- border-bottom-color: __background_alt__;
+ background-color: @ini_background_alt;
+ color: @ini_text;
+ border: 1px solid @ini_border;
+ border-bottom-color: @ini_background_alt;
line-height: 1.4em;
position: relative;
bottom: -1px;
@@ -118,7 +118,7 @@
right: 10px;
}
#mediamanager__page .namespaces .panelHeader {
- border-top: 1px solid __border__;
+ border-top: 1px solid @ini_border;
z-index: 1;
}
@@ -164,7 +164,7 @@
padding: 0;
}
#mediamanager__page .panelHeader ul li {
- color: __text__;
+ color: @ini_text;
float: left;
line-height: 1;
padding-left: 3px;
@@ -205,7 +205,7 @@
}
#mediamanager__page .filelist .panelContent ul li:hover {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#mediamanager__page .filelist li dt a {
@@ -231,8 +231,8 @@
display: -moz-inline-stack;
/* the right margin should visually be 10px, but because of its inline-block nature the whitespace inbetween is about 4px more */
margin: 0 6px 10px 0;
- background-color: __background_neu__;
- color: __text__;
+ background-color: @ini_background_neu;
+ color: @ini_text;
padding: 5px;
vertical-align: top;
text-align: center;
@@ -287,13 +287,13 @@
max-height: 50px;
margin: 0;
margin-bottom: 3px;
- background-color: __background__;
- color: __text__;
+ background-color: @ini_background;
+ color: @ini_text;
overflow: hidden;
}
#mediamanager__page .filelist .rows li:nth-child(2n+1) {
- background-color: __background_neu__;
+ background-color: @ini_background_neu;
}
#mediamanager__page .filelist .rows li dt {
@@ -372,11 +372,11 @@
#mediamanager__page .file dl dt {
font-weight: bold;
display: block;
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#mediamanager__page .file dl dd {
display: block;
- background-color: __background_neu__;
+ background-color: @ini_background_neu;
}
@@ -415,7 +415,7 @@
#mediamanager__page #page__revisions ul li div.li div {
font-size: 90%;
- color: __text_neu__;
+ color: @ini_text_neu;
padding-left: 18px;
}
@@ -438,7 +438,7 @@
padding: 0;
vertical-align: top;
text-align: left;
- border-color: __background__;
+ border-color: @ini_background;
}
[dir=rtl] #mediamanager__diff td,
[dir=rtl] #mediamanager__diff th {
@@ -447,7 +447,7 @@
#mediamanager__diff th {
font-weight: normal;
- background-color: __background__;
+ background-color: @ini_background;
line-height: 1.2;
}
#mediamanager__diff th a {
@@ -459,7 +459,7 @@
#mediamanager__diff dl dd strong{
background-color: __highlight__;
- color: __text__;
+ color: @ini_text;
font-weight: normal;
}
diff --git a/lib/tpl/dokuwiki/css/_media_popup.css b/lib/tpl/dokuwiki/css/_media_popup.css
index c776e6b8a..1fefd68b6 100644
--- a/lib/tpl/dokuwiki/css/_media_popup.css
+++ b/lib/tpl/dokuwiki/css/_media_popup.css
@@ -20,13 +20,13 @@ html.popup {
overflow: auto;
position: absolute;
left: 0;
- border-right: 1px solid __border__;
+ border-right: 1px solid @ini_border;
}
[dir=rtl] #mediamgr__aside {
left: auto;
right: 0;
border-right-width: 0;
- border-left: 1px solid __border__;
+ border-left: 1px solid @ini_border;
}
#mediamgr__aside .pad {
padding: .5em;
@@ -52,7 +52,7 @@ html.popup {
font-size: 1.5em;
margin-bottom: .5em;
padding-bottom: .2em;
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
}
/* left side
@@ -141,13 +141,13 @@ html.popup {
padding: .5em;
}
#media__content .odd {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#media__content .even {
}
/* highlight newly uploaded or edited file */
#media__content #scroll__here {
- border: 1px dashed __border__;
+ border: 1px dashed @ini_border;
}
/* link which inserts media file */
@@ -167,7 +167,7 @@ html.popup {
/* info how to insert media, if JS disabled */
#media__content div.example {
- color: __text_neu__;
+ color: @ini_text_neu;
margin-left: 1em;
}
diff --git a/lib/tpl/dokuwiki/css/_modal.css b/lib/tpl/dokuwiki/css/_modal.css
index a3d3be194..a46dff30e 100644
--- a/lib/tpl/dokuwiki/css/_modal.css
+++ b/lib/tpl/dokuwiki/css/_modal.css
@@ -18,11 +18,11 @@
}
#link__wiz_result {
- background-color: __background__;
+ background-color: @ini_background;
width: 293px;
height: 193px;
overflow: auto;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
margin: 3px auto;
text-align: left;
line-height: 1;
@@ -57,16 +57,16 @@
}
#link__wiz_result div.even {
- background-color: __background_neu__;
+ background-color: @ini_background_neu;
}
#link__wiz_result div.selected {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
#link__wiz_result span {
display: block;
- color: __text_neu__;
+ color: @ini_text_neu;
margin-left: 22px;
}
diff --git a/lib/tpl/dokuwiki/css/_search.css b/lib/tpl/dokuwiki/css/_search.css
index 0090308c9..a8972ae72 100644
--- a/lib/tpl/dokuwiki/css/_search.css
+++ b/lib/tpl/dokuwiki/css/_search.css
@@ -44,14 +44,14 @@
}
/* search snippet */
.dokuwiki dl.search_results dd {
- color: __text_alt__;
+ color: @ini_text_alt;
background-color: inherit;
margin: 0 0 1.2em 0;
}
/* search hit in normal text */
.dokuwiki .search_hit {
- color: __text__;
+ color: @ini_text;
background-color: __highlight__;
}
/* search hit in search results */
@@ -60,7 +60,7 @@
}
/* ellipsis separating snippets */
.dokuwiki .search_results .search_sep {
- color: __text__;
+ color: @ini_text;
background-color: inherit;
}
diff --git a/lib/tpl/dokuwiki/css/_tabs.css b/lib/tpl/dokuwiki/css/_tabs.css
index 845ec9a57..860545a27 100644
--- a/lib/tpl/dokuwiki/css/_tabs.css
+++ b/lib/tpl/dokuwiki/css/_tabs.css
@@ -17,7 +17,7 @@
width: 100%;
bottom: 0;
left: 0;
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
z-index: 1;
}
@@ -39,9 +39,9 @@
display: inline-block;
padding: .3em .8em;
margin: 0 0 0 .3em;
- background-color: __background_neu__;
- color: __text__;
- border: 1px solid __border__;
+ background-color: @ini_background_neu;
+ color: @ini_text;
+ border: 1px solid @ini_border;
border-radius: .5em .5em 0 0;
position: relative;
z-index: 0;
@@ -68,8 +68,8 @@
.dokuwiki ul.tabs li a:active,
.dokuwiki ul.tabs li a:focus,
.dokuwiki ul.tabs li strong {
- background-color: __background_alt__;
- color: __text__;
+ background-color: @ini_background_alt;
+ color: @ini_text;
text-decoration: none;
font-weight: normal;
}
@@ -78,5 +78,5 @@
.dokuwiki .tabs > ul li .active a,
.dokuwiki ul.tabs li strong {
z-index: 2;
- border-bottom-color: __background_alt__;
+ border-bottom-color: @ini_background_alt;
}
diff --git a/lib/tpl/dokuwiki/css/_toc.css b/lib/tpl/dokuwiki/css/_toc.css
index 1226b5b5b..469e9278c 100644
--- a/lib/tpl/dokuwiki/css/_toc.css
+++ b/lib/tpl/dokuwiki/css/_toc.css
@@ -11,7 +11,7 @@
float: right;
margin: 0 0 1.4em 1.4em;
width: 12em;
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
color: inherit;
}
[dir=rtl] #dw__toc {
diff --git a/lib/tpl/dokuwiki/css/basic.css b/lib/tpl/dokuwiki/css/basic.less
index a0a60d295..5886889fd 100644
--- a/lib/tpl/dokuwiki/css/basic.css
+++ b/lib/tpl/dokuwiki/css/basic.less
@@ -14,8 +14,8 @@ html {
}
html,
body {
- color: __text__;
- background: __background_site__ url(images/page-gradient.png) top left repeat-x;
+ color: @ini_text;
+ background: @ini_background_site url(images/page-gradient.png) top left repeat-x;
margin: 0;
padding: 0;
}
@@ -160,7 +160,7 @@ table {
border-collapse: collapse;
empty-cells: show;
border-spacing: 0;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
}
caption {
@@ -176,11 +176,11 @@ td {
padding: .3em .5em;
margin: 0;
vertical-align: top;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
}
th {
font-weight: bold;
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
text-align: left;
}
[dir=rtl] th {
@@ -196,7 +196,7 @@ a {
a:link,
a:visited {
text-decoration: none;
- color: __link__;
+ color: @ini_link;
}
a:link:hover,
a:visited:hover,
@@ -227,13 +227,14 @@ audio {
max-width: 100%;
}
#IE7 img,
-#IE8 img {
+#IE8 img,
+button img {
max-width: none;
}
hr {
- border-top: solid __border__;
- border-bottom: solid __background__;
+ border-top: solid @ini_border;
+ border-bottom: solid @ini_background;
border-width: 1px 0;
height: 0;
text-align: center;
@@ -252,7 +253,7 @@ em abbr {
}
mark {
- background-color: __highlight__;
+ background-color: @ini_highlight;
color: inherit;
}
@@ -265,23 +266,23 @@ kbd {
font-size: 1em;
direction: ltr;
text-align: left;
- background-color: __background_site__;
- color: __text__;
- box-shadow: inset 0 0 .3em __border__;
+ background-color: @ini_background_site;
+ color: @ini_text;
+ box-shadow: inset 0 0 .3em @ini_border;
border-radius: 2px;
}
pre {
overflow: auto;
word-wrap: normal;
- border: 1px solid __border__;
+ border: 1px solid @ini_border;
border-radius: 2px;
- box-shadow: inset 0 0 .5em __border__;
+ box-shadow: inset 0 0 .5em @ini_border;
padding: .7em 1em;
}
blockquote {
padding: 0 .5em;
- border: solid __border__;
+ border: solid @ini_border;
border-width: 0 0 0 .25em;
}
[dir=rtl] blockquote {
@@ -320,7 +321,7 @@ form {
fieldset {
padding: .7em 1em 0;
padding: .7rem 1rem; /* for those browsers understanding :last-child */
- border: 1px solid __text_alt__;
+ border: 1px solid @ini_text_alt;
}
fieldset > :last-child {
margin-bottom: 0;
@@ -356,6 +357,9 @@ progress {
box-sizing: border-box;
}
+select {
+ max-width: 100%;
+}
optgroup {
font-style: italic;
font-weight: bold;
@@ -402,11 +406,7 @@ button,
color: #333;
background-color: #eee;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPgo8bGluZWFyR3JhZGllbnQgaWQ9Imc4MjQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkZGRkYiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiNGNEY0RjQiIG9mZnNldD0iMC4zIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0VFRUVFRSIgb2Zmc2V0PSIwLjk5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0NDQ0NDQyIgb2Zmc2V0PSIuOTkiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNnODI0KSIgLz4KPC9zdmc+);
- background: -moz-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: -webkit-linear-gradient(top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: -o-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: -ms-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
- background: linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%);
+ .linear-gradient("top, #ffffff 0%, #f4f4f4 30%, #eeeeee 99%, #cccccc 99%");
border: 1px solid #ccc;
border-radius: 2px;
padding: .1em .5em;
@@ -440,11 +440,7 @@ button:focus,
border-color: #999;
background-color: #ddd;
background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPgo8bGluZWFyR3JhZGllbnQgaWQ9Imc2NzAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkZGRkYiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiNGNEY0RjQiIG9mZnNldD0iMC4zIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0RERERERCIgb2Zmc2V0PSIwLjk5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0JCQkJCQiIgb2Zmc2V0PSIuOTkiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNnNjcwKSIgLz4KPC9zdmc+);
- background: -moz-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: -webkit-linear-gradient(top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: -o-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: -ms-linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
- background: linear-gradient( top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%);
+ .linear-gradient("top, #ffffff 0%, #f4f4f4 30%, #dddddd 99%, #bbbbbb 99%");
}
input::-moz-focus-inner,
diff --git a/lib/tpl/dokuwiki/css/content.css b/lib/tpl/dokuwiki/css/content.less
index 119859e38..56551fe3b 100644
--- a/lib/tpl/dokuwiki/css/content.css
+++ b/lib/tpl/dokuwiki/css/content.less
@@ -8,16 +8,16 @@
/*____________ section indenting ____________
-.dokuwiki.page h1 {margin-left: 0;}
-.dokuwiki.page h2 {margin-left: .666em;}
-.dokuwiki.page h3 {margin-left: 1.776em;}
-.dokuwiki.page h4 {margin-left: 3em;}
-.dokuwiki.page h5 {margin-left: 4.5712em;}
-.dokuwiki.page div.level1 {margin-left: 0;}
-.dokuwiki.page div.level2 {margin-left: 1em;}
-.dokuwiki.page div.level3 {margin-left: 2em;}
-.dokuwiki.page div.level4 {margin-left: 3em;}
-.dokuwiki.page div.level5 {margin-left: 4em;}
+.dokuwiki .page h1 {margin-left: 0;}
+.dokuwiki .page h2 {margin-left: .666em;}
+.dokuwiki .page h3 {margin-left: 1.776em;}
+.dokuwiki .page h4 {margin-left: 3em;}
+.dokuwiki .page h5 {margin-left: 4.5712em;}
+.dokuwiki .page div.level1 {margin-left: 0;}
+.dokuwiki .page div.level2 {margin-left: 1em;}
+.dokuwiki .page div.level3 {margin-left: 2em;}
+.dokuwiki .page div.level4 {margin-left: 3em;}
+.dokuwiki .page div.level5 {margin-left: 4em;}
[dir=rtl] .dokuwiki .page h1 {margin-left: 0; margin-right: 0;}
[dir=rtl] .dokuwiki .page h2 {margin-left: 0; margin-right: .666em;}
@@ -32,54 +32,56 @@
*/
/* hx margin-left = (1 / font-size) * .levelx-margin */
-
/*____________ links to wiki pages (addition to _links) ____________*/
/* existing wikipage */
.dokuwiki a.wikilink1 {
- color: __existing__;
+ color: @ini_existing;
background-color: inherit;
}
+
/* not existing wikipage */
.dokuwiki a.wikilink2 {
- color: __missing__;
+ color: @ini_missing;
background-color: inherit;
}
-
/*____________ images ____________*/
/* embedded images (styles are already partly set in lib/styles/all.css) */
.dokuwiki img.media {
margin: .2em 0;
}
+
.dokuwiki img.medialeft {
margin: .2em 1em .2em 0;
}
+
.dokuwiki img.mediaright {
margin: .2em 0 .2em 1em;
}
+
.dokuwiki img.mediacenter {
margin: .2em auto;
}
-
/*____________ lists ____________*/
#dokuwiki__content ul li,
#dokuwiki__aside ul li {
- color: __text_alt__;
+ color: @ini_text_alt;
}
+
#dokuwiki__content ol li,
#dokuwiki__aside ol li {
- color: __text_neu__;
+ color: @ini_text_neu;
}
+
#dokuwiki__content li .li,
#dokuwiki__aside li .li {
- color: __text__;
+ color: @ini_text;
}
-
/*____________ tables ____________*/
/* div around each table */
@@ -87,6 +89,7 @@
overflow-x: auto;
margin-bottom: 1.4em;
}
+
.dokuwiki div.table table {
margin-bottom: 0;
}
@@ -94,14 +97,15 @@
.dokuwiki table.inline {
min-width: 50%;
}
+
.dokuwiki table.inline tr:hover td {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
+
.dokuwiki table.inline tr:hover th {
- background-color: __border__;
+ background-color: @ini_border;
}
-
/*____________ code ____________*/
/* fix if background-color hides underlining */
@@ -116,66 +120,61 @@
/* filenames for downloadable file and code blocks */
.dokuwiki dl.code,
.dokuwiki dl.file {
+ dt {
+ background-color: @ini_background_site;
+ .linear-gradient(~"top, @{ini_background_alt} 0%, @{ini_background_site} 100%");
+ color: inherit;
+ border: 1px solid @ini_border;
+ border-bottom-color: @ini_background_site;
+ border-top-left-radius: .3em;
+ border-top-right-radius: .3em;
+ padding: .3em .6em .1em;
+ margin-bottom: -1px;
+ float: left;
+
+ a {
+ background-color: transparent;
+ font-size: 0.875em;
+ font-weight: normal;
+ display: block;
+ min-height: 16px;
+ }
+ }
+
+ dd {
+ margin: 0;
+ clear: left;
+ min-height: 1px; /* for IE7 */
+ }
+
+ pre {
+ box-shadow: inset -4px -4px .5em -.3em @ini_border;
+ }
+}
+
+[dir=rtl] .dokuwiki dl.code,
+[dir=rtl] .dokuwiki dl.file {
+ dt {
+ float: right;
+ }
+
+ dd {
+ clear: right;
+ }
}
-.dokuwiki dl.code dt,
-.dokuwiki dl.file dt {
- background-color: __background_site__;
- background: -moz-linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- background: -webkit-linear-gradient(top, __background_alt__ 0%, __background_site__ 100%);
- background: -o-linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- background: -ms-linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- background: linear-gradient( top, __background_alt__ 0%, __background_site__ 100%);
- color: inherit;
- border: 1px solid __border__;
- border-bottom-color: __background_site__;
- border-top-left-radius: .3em;
- border-top-right-radius: .3em;
- padding: .3em .6em .1em;
- margin-bottom: -1px;
- float: left;
-}
-[dir=rtl] .dokuwiki dl.code dt,
-[dir=rtl] .dokuwiki dl.file dt {
- float: right;
-}
-.dokuwiki dl.code dt a,
-.dokuwiki dl.file dt a {
- background-color: transparent;
- font-size: 0.875em;
- font-weight: normal;
- display: block;
- min-height: 16px;
-}
-
-.dokuwiki dl.code dd,
-.dokuwiki dl.file dd {
- margin: 0;
- clear: left;
- min-height: 1px; /* for IE7 */
-}
-[dir=rtl] .dokuwiki dl.code dd,
-[dir=rtl] .dokuwiki dl.file dd {
- clear: right;
-}
-
-.dokuwiki dl.code pre,
-.dokuwiki dl.file pre {
- box-shadow: inset -4px -4px .5em -.3em __border__;
-}
-
-
/*____________ JS popup ____________*/
.JSpopup {
- background-color: __background__;
- color: __text__;
- border: 1px solid __border__;
- box-shadow: .1em .1em .1em __border__;
+ background-color: @ini_background;
+ color: @ini_text;
+ border: 1px solid @ini_border;
+ box-shadow: .1em .1em .1em @ini_border;
border-radius: 2px;
padding: .3em .5em;
font-size: .9em;
}
+
.dokuwiki form.search div.ajax_qsearch {
top: -.35em;
font-size: 1em;
@@ -186,12 +185,12 @@
.JSpopup ol {
padding-left: 0;
}
+
[dir=rtl] .JSpopup ul,
[dir=rtl] .JSpopup ol {
padding-right: 0;
}
-
/* changes to underscored CSS files
********************************************************************/
@@ -202,41 +201,49 @@
#dokuwiki__content span.curid a {
font-weight: normal;
}
+
#dokuwiki__content strong span.curid a {
font-weight: bold;
}
-
/*____________ changes to _edit ____________*/
-.dokuwiki div.toolbar button.toolbutton {
- border-radius: 0;
- border-left-width: 0;
- padding: .1em .35em;
-}
-.dokuwiki div.toolbar button.toolbutton:first-child {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
- border-left-width: 1px;
-}
-[dir=rtl] .dokuwiki div.toolbar button.toolbutton:first-child {
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
- border-left-width: 0;
- border-right-width: 1px;
-}
-.dokuwiki div.toolbar button.toolbutton:last-child {
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
-}
-[dir=rtl] .dokuwiki div.toolbar button.toolbutton:last-child {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- border-left-width: 1px;
+.dokuwiki div.toolbar {
+ button.toolbutton {
+ border-radius: 0;
+ border-left-width: 0;
+ padding: .1em .35em;
+ }
+
+ button.toolbutton:first-child {
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ border-left-width: 1px;
+ }
+
+ button.toolbutton:last-child {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ }
+}
+
+[dir=rtl] .dokuwiki div.toolbar {
+ button.toolbutton:last-child {
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-left-width: 1px;
+ }
+
+ button.toolbutton:first-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-left-width: 0;
+ border-right-width: 1px;
+ }
}
.dokuwiki div.section_highlight {
@@ -253,31 +260,34 @@
margin: 0 -2em;
padding: 0 2em;
}
+
.dokuwiki.hasSidebar div.preview {
- border-right: __sidebar_width__ solid __background_alt__;
+ border-right: @ini_sidebar_width solid @ini_background_alt;
}
+
[dir=rtl] .dokuwiki.hasSidebar div.preview {
border-right-width: 0;
- border-left: __sidebar_width__ solid __background_alt__;
+ border-left: @ini_sidebar_width solid @ini_background_alt;
}
+
.dokuwiki div.preview div.pad {
padding: 1.556em 0 2em;
}
-
/*____________ changes to _toc ____________*/
#dw__toc {
- margin: -1.556em -2em .5em 1.4em;
- width: __sidebar_width__;
- border-left: 1px solid __border__;
- background: __background__;
+ margin: -1.556em -2em .5em 1.4em;
+ width: @ini_sidebar_width;
+ border-left: 1px solid @ini_border;
+ background: @ini_background;
color: inherit;
}
+
[dir=rtl] #dw__toc {
margin: -1.556em 1.4em .5em -2em;
border-left-width: 0;
- border-right: 1px solid __border__;
+ border-right: 1px solid @ini_border;
}
.dokuwiki h3.toggle {
@@ -286,6 +296,7 @@
font-size: .875em;
letter-spacing: .1em;
}
+
#dokuwiki__aside h3.toggle {
display: none;
}
@@ -296,6 +307,7 @@
height: 5px;
margin: .4em 0 0;
}
+
.dokuwiki .toggle.closed strong {
background-position: 0 -5px;
}
@@ -304,59 +316,72 @@
display: none;
}
+#dw__toc {
+ > div {
+ font-size: 0.875em;
+ padding: .5em 1em 1em;
+ }
-#dw__toc > div {
- font-size: 0.875em;
- padding: .5em 1em 1em;
-}
-#dw__toc ul {
- padding: 0 0 0 1.2em;
+ ul {
+ padding: 0 0 0 1.2em;
+
+ li {
+ list-style-image: url(images/toc-bullet.png);
+ }
+ }
+
+ ul li.clear {
+ list-style: none;
+ }
+
+ ul li div.li {
+ padding: .2em 0;
+ }
}
+
[dir=rtl] #dw__toc ul {
padding: 0 1.5em 0 0;
}
-#dw__toc ul li {
- list-style-image: url(images/toc-bullet.png);
-}
-#dw__toc ul li.clear {
- list-style: none;
-}
-#dw__toc ul li div.li {
- padding: .2em 0;
-}
-
/*____________ changes to _imgdetail ____________*/
#dokuwiki__detail {
padding: 0;
-}
-#dokuwiki__detail img {
- float: none;
- margin-bottom: 1.4em;
-}
-#dokuwiki__detail div.img_detail {
- float: none;
-}
-#dokuwiki__detail div.img_detail dl {
- overflow: hidden;
-}
-#dokuwiki__detail div.img_detail dl dt {
- float: left;
- width: 9em;
- text-align: right;
- clear: left;
-}
-[dir=rtl] #dokuwiki__detail div.img_detail dl dt {
- float: right;
- text-align: left;
- clear: right;
-}
-#dokuwiki__detail div.img_detail dl dd {
- margin-left: 9.5em;
-}
-[dir=rtl] #dokuwiki__detail div.img_detail dl dd {
- margin-left: 0;
- margin-right: 9.5em;
-}
+ img {
+ float: none;
+ margin-bottom: 1.4em;
+ }
+
+ div.img_detail {
+ float: none;
+ }
+
+ div.img_detail dl {
+ overflow: hidden;
+ }
+
+ div.img_detail dl dt {
+ float: left;
+ width: 9em;
+ text-align: right;
+ clear: left;
+ }
+
+ div.img_detail dl dd {
+ margin-left: 9.5em;
+ }
+}
+
+[dir=rtl] #dokuwiki__detail div.img_detail {
+ dl dt {
+ float: right;
+ text-align: left;
+ clear: right;
+ }
+
+ dl dd {
+ margin-left: 0;
+ margin-right: 9.5em;
+ }
+} \ No newline at end of file
diff --git a/lib/tpl/dokuwiki/css/design.css b/lib/tpl/dokuwiki/css/design.css
deleted file mode 100644
index 457414839..000000000
--- a/lib/tpl/dokuwiki/css/design.css
+++ /dev/null
@@ -1,405 +0,0 @@
-/**
- * This file provides the main design styles for the
- * bits that surround the content.
- *
- * @author Anika Henke <anika@selfthinker.org>
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Clarence Lee <clarencedglee@gmail.com>
- */
-
-/* header
-********************************************************************/
-
-#dokuwiki__header {
- padding: 2em 0 1.5em;
-}
-
-#dokuwiki__header .headings,
-#dokuwiki__header .tools {
- margin-bottom: 1.5em;
- width: 49%;
-}
-#dokuwiki__header h1 img {
- float: left;
- margin-right: .5em;
-}
-[dir=rtl] #dokuwiki__header h1 img {
- float: right;
- margin-left: .5em;
- margin-right: 0;
-}
-#dokuwiki__header h1 span {
- display: block;
- padding-top: 10px;
-}
-#dokuwiki__header h1 {
- margin: 0;
- font-size: 1.5em;
- font-weight: normal;
-}
-#dokuwiki__header h1 a {
- text-decoration: none;
- color: __text__;
- background-color: inherit;
-}
-#dokuwiki__header h1 a:hover,
-#dokuwiki__header h1 a:active,
-#dokuwiki__header h1 a:focus {
-}
-#dokuwiki__header p.claim {
- margin-bottom: 0;
- font-size: 0.875em;
-}
-
-#dokuwiki__header .tools {
- margin-top: .2em;
-}
-
-
-/* tools
-********************************************************************/
-
-/* highlight selected tool */
-.mode_admin a.action.admin,
-.mode_login a.action.login,
-.mode_register a.action.register,
-.mode_profile a.action.profile,
-.mode_recent a.action.recent,
-.mode_index a.action.index,
-.mode_media a.action.media,
-.mode_revisions a.action.revs,
-.mode_backlink a.action.backlink,
-.mode_subscribe a.action.subscribe {
- font-weight: bold;
-}
-
-#dokuwiki__header .tools ul {
- padding-left: 0;
- margin-bottom: 0;
-}
-#dokuwiki__header .tools li {
- font-size: 0.875em;
- margin-left: 1em;
- list-style: none;
- display: inline;
-}
-[dir=rtl] #dokuwiki__header .tools li {
- margin-right: 1em;
- margin-left: 0;
-}
-#dokuwiki__header .tools form.search div.ajax_qsearch li {
- font-size: 1em;
- margin-left: 0;
- display: block;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-#dokuwiki__usertools a.action {
- padding-left: 20px;
- background: transparent url(images/usertools.png) no-repeat 0 0;
-}
-[dir=rtl] #dokuwiki__usertools a.action {
- padding-left: 0;
- padding-right: 20px;
-}
-[dir=rtl] #IE7 #dokuwiki__usertools a.action {
- display: inline-block;
-}
-
-
-#dokuwiki__header .mobileTools {
- display: none; /* hide mobile tools dropdown to only show in mobile view */
-}
-
-/*____________ user tools ____________*/
-
-#dokuwiki__usertools {
- position: absolute;
- top: .5em;
- right: .5em;
- text-align: right;
- width: 100%;
-}
-[dir=rtl] #dokuwiki__usertools {
- text-align: left;
- left: 40px;
- right: auto;
-}
-#dokuwiki__usertools ul {
- margin: 0 auto;
- padding: 0;
- max-width: __site_width__;
-}
-#dokuwiki__usertools ul li.user {
-}
-
-#dokuwiki__usertools a.action.admin {
- background-position: left 0;
-}
-[dir=rtl] #dokuwiki__usertools a.action.admin {
- background-position: right 0;
-}
-#dokuwiki__usertools a.action.profile {
- background-position: left -32px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.profile {
- background-position: right -32px;
-}
-#dokuwiki__usertools a.action.register {
- background-position: left -64px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.register {
- background-position: right -64px;
-}
-#dokuwiki__usertools a.action.login {
- background-position: left -96px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.login {
- background-position: right -96px;
-}
-#dokuwiki__usertools a.action.logout {
- background-position: left -128px;
-}
-[dir=rtl] #dokuwiki__usertools a.action.logout {
- background-position: right -128px;
-}
-
-
-/*____________ site tools ____________*/
-
-#dokuwiki__sitetools {
- text-align: right;
-}
-[dir=rtl] #dokuwiki__sitetools {
- text-align: left;
-}
-
-#dokuwiki__sitetools form.search {
- display: block;
- font-size: 0.875em;
- position: relative;
-}
-#IE7 #dokuwiki__sitetools form.search {
- min-height: 1px;
- z-index: 21;
-}
-#dokuwiki__sitetools form.search input.edit {
- width: 18em;
- padding: .35em 22px .35em .1em;
-}
-[dir=rtl] #dokuwiki__sitetools form.search input.edit {
- padding: .35em .1em .35em 22px;
-}
-#dokuwiki__sitetools form.search input.button {
- background: transparent url(images/search.png) no-repeat 0 0;
- border-width: 0;
- width: 19px;
- height: 14px;
- text-indent: -99999px;
- margin-left: -20px;
- box-shadow: none;
- padding: 0;
-}
-[dir=rtl] #dokuwiki__sitetools form.search input.button {
- background-position: 5px 0;
- margin-left: 0;
- margin-right: -20px;
- position: relative;
-}
-
-#dokuwiki__sitetools ul {
- margin-top: 0.5em;
-}
-#dokuwiki__sitetools li {
-}
-
-/*____________ breadcrumbs ____________*/
-
-.dokuwiki div.breadcrumbs {
- border-top: 1px solid __border__;
- border-bottom: 1px solid __background__;
- margin-bottom: .5em;
- font-size: 0.875em;
- clear: both;
-}
-.dokuwiki div.breadcrumbs div {
- padding: .1em .35em;
-}
-
-.dokuwiki div.breadcrumbs div:only-child {
- border-top: 1px solid __background__;
- border-bottom: 1px solid __border__;
-}
-.dokuwiki div.breadcrumbs div:first-child {
- border-top: 1px solid __background__;
-}
-#IE7 .dokuwiki div.breadcrumbs div,
-#IE8 .dokuwiki div.breadcrumbs div {
- border-bottom: 1px solid __border__;
-}
-.dokuwiki div.breadcrumbs div:last-child {
- border-bottom: 1px solid __border__;
-}
-
-.dokuwiki div.breadcrumbs a {
- color: __link__;
- background-color: inherit;
-}
-.dokuwiki div.breadcrumbs .bcsep {
- font-size: 0.75em;
-}
-
-
-/* sidebar
-********************************************************************/
-
-#dokuwiki__aside {
-}
-#dokuwiki__aside > .pad {
- font-size: 0.875em;
- overflow: hidden;
- word-wrap: break-word;
-}
-
-/* make sidebar more condensed */
-
-#dokuwiki__aside h1 {
- font-size: 1.714em;
- margin-bottom: .292em;
-}
-#dokuwiki__aside h2 {
- margin-bottom: .333em;
-}
-#dokuwiki__aside h3 {
- margin-bottom: .444em;
-}
-#dokuwiki__aside h4 {
- margin-bottom: .5em;
-}
-#dokuwiki__aside h5 {
- margin-bottom: .5714em;
-}
-
-#dokuwiki__aside p,
-#dokuwiki__aside ul,
-#dokuwiki__aside ol,
-#dokuwiki__aside dl,
-#dokuwiki__aside pre,
-#dokuwiki__aside table,
-#dokuwiki__aside fieldset,
-#dokuwiki__aside hr,
-#dokuwiki__aside blockquote,
-#dokuwiki__aside address {
- margin-bottom: .7em;
-}
-
-#dokuwiki__aside ul,
-#dokuwiki__aside ol {
- padding-left: .5em;
-}
-[dir=rtl] #dokuwiki__aside ul,
-[dir=rtl] #dokuwiki__aside ol {
- padding-right: .5em;
-}
-#dokuwiki__aside li ul,
-#dokuwiki__aside li ol {
- margin-bottom: 0;
- padding: 0;
-}
-
-#dokuwiki__aside a:link,
-#dokuwiki__aside a:visited {
- color: __link__;
- background-color: inherit;
-}
-
-
-/* content
-********************************************************************/
-
-#dokuwiki__content {
-}
-
-.dokuwiki .pageId {
- position: absolute;
- top: -2.3em;
- right: -1em;
- overflow: hidden;
- padding: 1em 1em 0;
-}
-[dir=rtl] .dokuwiki .pageId {
- right: auto;
- left: -1em;
-}
-.dokuwiki .pageId span {
- font-size: 0.875em;
- border: solid __background_alt__;
- border-width: 1px 1px 0;
- background-color: __background__;
- color: __text_alt__;
- padding: .1em .35em;
- border-top-left-radius: 2px;
- border-top-right-radius: 2px;
- box-shadow: 0 0 .5em __text_alt__;
- display: block;
-}
-
-.dokuwiki div.page {
- background: __background__;
- color: inherit;
- border: 1px solid __background_alt__;
- box-shadow: 0 0 .5em __text_alt__;
- border-radius: 2px;
- padding: 1.556em 2em 2em;
- margin-bottom: .5em;
- overflow: hidden;
- word-wrap: break-word;
-}
-
-.dokuwiki .docInfo {
- font-size: 0.875em;
- text-align: right;
-}
-[dir=rtl] .dokuwiki .docInfo {
- text-align: left;
-}
-
-/* license note under edit window */
-.dokuwiki div.license {
- font-size: 93.75%;
-}
-
-
-/* footer
-********************************************************************/
-
-.dokuwiki .wrapper {
- margin-bottom: 1.4em;
-}
-
-#dokuwiki__footer {
- margin-bottom: 1em;
- text-align: center;
-}
-#dokuwiki__footer > .pad {
- font-size: 0.875em;
-}
-
-#dokuwiki__footer div.license {
- margin-bottom: 0.5em;
- font-size: 100%;
-}
-
-[dir=rtl] #dokuwiki__footer .license img {
- margin: 0 0 0 .5em;
-}
-
-#dokuwiki__footer div.buttons a img {
- opacity: 0.5;
-}
-#dokuwiki__footer div.buttons a:hover img,
-#dokuwiki__footer div.buttons a:active img,
-#dokuwiki__footer div.buttons a:focus img {
- opacity: 1;
-}
diff --git a/lib/tpl/dokuwiki/css/design.less b/lib/tpl/dokuwiki/css/design.less
new file mode 100644
index 000000000..42292de49
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/design.less
@@ -0,0 +1,439 @@
+/**
+ * This file provides the main design styles for the
+ * bits that surround the content.
+ *
+ * @author Anika Henke <anika@selfthinker.org>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Clarence Lee <clarencedglee@gmail.com>
+ */
+
+/* header
+********************************************************************/
+
+#dokuwiki__header {
+ padding: 2em 0 1.5em;
+
+ .headings,
+ .tools {
+ margin-bottom: 1.5em;
+ width: 49%;
+ }
+ .tools {
+ margin-top: .2em;
+ }
+
+ h1 {
+ margin: 0;
+ font-size: 1.5em;
+ font-weight: normal;
+
+ img {
+ float: left;
+ margin-right: .5em;
+ }
+
+ span {
+ display: block;
+ padding-top: 10px;
+ }
+
+ a {
+ text-decoration: none;
+ color: @ini_text;
+ background-color: inherit;
+ }
+ }
+
+ p.claim {
+ margin-bottom: 0;
+ font-size: 0.875em;
+ }
+}
+
+[dir=rtl] #dokuwiki__header h1 img {
+ float: right;
+ margin-left: .5em;
+ margin-right: 0;
+}
+
+/* tools
+********************************************************************/
+
+/* highlight selected tool */
+.mode_admin a.action.admin,
+.mode_login a.action.login,
+.mode_register a.action.register,
+.mode_profile a.action.profile,
+.mode_recent a.action.recent,
+.mode_index a.action.index,
+.mode_media a.action.media,
+.mode_revisions a.action.revs,
+.mode_backlink a.action.backlink,
+.mode_subscribe a.action.subscribe {
+ font-weight: bold;
+}
+
+#dokuwiki__header .tools {
+ ul {
+ padding-left: 0;
+ margin-bottom: 0;
+ }
+
+ li {
+ font-size: 0.875em;
+ margin-left: 1em;
+ list-style: none;
+ display: inline;
+ }
+
+ form.search div.ajax_qsearch li {
+ font-size: 1em;
+ margin-left: 0;
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+}
+
+[dir=rtl] #dokuwiki__header .tools li {
+ margin-right: 1em;
+ margin-left: 0;
+}
+
+#dokuwiki__usertools a.action {
+ padding-left: 20px;
+ background: transparent url(images/usertools.png) no-repeat 0 0;
+}
+
+[dir=rtl] #dokuwiki__usertools a.action {
+ padding-left: 0;
+ padding-right: 20px;
+}
+
+[dir=rtl] #IE7 #dokuwiki__usertools a.action {
+ display: inline-block;
+}
+
+#dokuwiki__header .mobileTools {
+ display: none; /* hide mobile tools dropdown to only show in mobile view */
+}
+
+/*____________ user tools ____________*/
+
+#dokuwiki__usertools {
+ position: absolute;
+ top: .5em;
+ right: .5em;
+ text-align: right;
+ width: 100%;
+
+ ul {
+ margin: 0 auto;
+ padding: 0;
+ max-width: @ini_site_width;
+ }
+
+ a.action.admin {
+ background-position: left 0;
+ }
+
+ a.action.profile {
+ background-position: left -32px;
+ }
+
+ a.action.register {
+ background-position: left -64px;
+ }
+
+ a.action.login {
+ background-position: left -96px;
+ }
+
+ a.action.logout {
+ background-position: left -128px;
+ }
+}
+
+[dir=rtl] #dokuwiki__usertools {
+ text-align: left;
+ left: 40px;
+ right: auto;
+
+ a.action.admin {
+ background-position: right 0;
+ }
+
+ a.action.profile {
+ background-position: right -32px;
+ }
+
+ a.action.register {
+ background-position: right -64px;
+ }
+
+ a.action.login {
+ background-position: right -96px;
+ }
+
+ a.action.logout {
+ background-position: right -128px;
+ }
+}
+
+/*____________ site tools ____________*/
+
+#dokuwiki__sitetools {
+ text-align: right;
+
+ form.search {
+ display: block;
+ font-size: 0.875em;
+ position: relative;
+
+ input.edit {
+ width: 18em;
+ padding: .35em 22px .35em .1em;
+ }
+
+ input.button {
+ background: transparent url(images/search.png) no-repeat 0 0;
+ border-width: 0;
+ width: 19px;
+ height: 14px;
+ text-indent: -99999px;
+ margin-left: -20px;
+ box-shadow: none;
+ padding: 0;
+ }
+ }
+
+ ul {
+ margin-top: 0.5em;
+ }
+}
+
+[dir=rtl] #dokuwiki__sitetools {
+ text-align: left;
+
+ form.search {
+ input.edit {
+ padding: .35em .1em .35em 22px;
+ }
+
+ input.button {
+ background-position: 5px 0;
+ margin-left: 0;
+ margin-right: -20px;
+ position: relative;
+ }
+ }
+}
+
+#IE7 #dokuwiki__sitetools form.search {
+ min-height: 1px;
+ z-index: 21;
+}
+
+/*____________ breadcrumbs ____________*/
+
+.dokuwiki div.breadcrumbs {
+ border-top: 1px solid @ini_border;
+ border-bottom: 1px solid @ini_background;
+ margin-bottom: .5em;
+ font-size: 0.875em;
+ clear: both;
+
+ div {
+ padding: .1em .35em;
+ }
+
+ div:only-child {
+ border-top: 1px solid @ini_background;
+ border-bottom: 1px solid @ini_border;
+ }
+
+ div:first-child {
+ border-top: 1px solid @ini_background;
+ }
+
+ div:last-child {
+ border-bottom: 1px solid @ini_border;
+ }
+
+ a {
+ color: @ini_link;
+ background-color: inherit;
+ }
+
+ .bcsep {
+ font-size: 0.75em;
+ }
+}
+
+#IE7 .dokuwiki div.breadcrumbs div,
+#IE8 .dokuwiki div.breadcrumbs div {
+ border-bottom: 1px solid @ini_border;
+}
+
+/* sidebar
+********************************************************************/
+
+#dokuwiki__aside {
+
+ > .pad {
+ font-size: 0.875em;
+ overflow: hidden;
+ word-wrap: break-word;
+ }
+
+ /* make sidebar more condensed */
+
+ h1 {
+ font-size: 1.714em;
+ margin-bottom: .292em;
+ }
+
+ h2 {
+ margin-bottom: .333em;
+ }
+
+ h3 {
+ margin-bottom: .444em;
+ }
+
+ h4 {
+ margin-bottom: .5em;
+ }
+
+ h5 {
+ margin-bottom: .5714em;
+ }
+
+ p,
+ ul,
+ ol,
+ dl,
+ pre,
+ table,
+ fieldset,
+ hr,
+ blockquote,
+ address {
+ margin-bottom: .7em;
+ }
+
+ ul,
+ ol {
+ padding-left: .5em;
+ }
+
+ li ul,
+ li ol {
+ margin-bottom: 0;
+ padding: 0;
+ }
+
+ a:link,
+ a:visited {
+ color: @ini_link;
+ background-color: inherit;
+ }
+}
+
+[dir=rtl] #dokuwiki__aside ul,
+[dir=rtl] #dokuwiki__aside ol {
+ padding-right: .5em;
+}
+
+/* content
+********************************************************************/
+
+.dokuwiki .pageId {
+ position: absolute;
+ top: -2.3em;
+ right: -1em;
+ overflow: hidden;
+ padding: 1em 1em 0;
+
+ span {
+ font-size: 0.875em;
+ border: solid @ini_background_alt;
+ border-width: 1px 1px 0;
+ background-color: @ini_background;
+ color: @ini_text_alt;
+ padding: .1em .35em;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ box-shadow: 0 0 .5em @ini_text_alt;
+ display: block;
+ }
+}
+
+.dokuwiki div.page {
+ background: @ini_background;
+ color: inherit;
+ border: 1px solid @ini_background_alt;
+ box-shadow: 0 0 .5em @ini_text_alt;
+ border-radius: 2px;
+ padding: 1.556em 2em 2em;
+ margin-bottom: .5em;
+ overflow: hidden;
+ word-wrap: break-word;
+}
+
+.dokuwiki .docInfo {
+ font-size: 0.875em;
+ text-align: right;
+}
+
+/* license note under edit window */
+.dokuwiki div.license {
+ font-size: 93.75%;
+}
+
+[dir=rtl] .dokuwiki .docInfo {
+ text-align: left;
+}
+
+[dir=rtl] .dokuwiki .pageId {
+ right: auto;
+ left: -1em;
+}
+
+/* footer
+********************************************************************/
+
+.dokuwiki .wrapper {
+ margin-bottom: 1.4em;
+}
+
+#dokuwiki__footer {
+ margin-bottom: 1em;
+ text-align: center;
+
+ > .pad {
+ font-size: 0.875em;
+ }
+
+ div.license {
+ margin-bottom: 0.5em;
+ font-size: 100%;
+ }
+
+ div.buttons a {
+ img {
+ opacity: 0.5;
+ }
+
+ &:hover img,
+ &:active img,
+ &:focus img {
+ opacity: 1;
+ }
+ }
+
+}
+
+[dir=rtl] #dokuwiki__footer .license img {
+ margin: 0 0 0 .5em;
+}
diff --git a/lib/tpl/dokuwiki/css/includes.css b/lib/tpl/dokuwiki/css/includes.css
deleted file mode 100644
index bc189962f..000000000
--- a/lib/tpl/dokuwiki/css/includes.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * This file provides styles for included seperate html files
- * (added through "include hooks").
- */
diff --git a/lib/tpl/dokuwiki/css/mixins.less b/lib/tpl/dokuwiki/css/mixins.less
new file mode 100644
index 000000000..a88767e97
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/mixins.less
@@ -0,0 +1,10 @@
+/**
+ * linear gradient x-browser support
+ */
+.linear-gradient(@declaration: 0) {
+ background: -moz-linear-gradient( @declaration);
+ background: -webkit-linear-gradient(@declaration);
+ background: -o-linear-gradient( @declaration);
+ background: -ms-linear-gradient( @declaration);
+ background: linear-gradient( @declaration);
+} \ No newline at end of file
diff --git a/lib/tpl/dokuwiki/css/mobile.css b/lib/tpl/dokuwiki/css/mobile.less
index 71f80599d..289f5afa3 100644
--- a/lib/tpl/dokuwiki/css/mobile.css
+++ b/lib/tpl/dokuwiki/css/mobile.less
@@ -13,7 +13,7 @@
/* for screen widths in the tablet range
********************************************************************/
-@media only screen and (max-width: __tablet_width__) {
+@media only screen and (max-width: @ini_tablet_width) {
#screen__mode {
z-index: 1; /* for detecting media queries in JavaScript (see script.js) */
@@ -29,10 +29,10 @@
[dir=rtl] #dokuwiki__aside > .pad {
margin: 0 0 .5em;
/* style like .page */
- background: __background__;
+ background: @ini_background;
color: inherit;
border: 1px solid #eee;
- box-shadow: 0 0 .5em __text_alt__;
+ box-shadow: 0 0 .5em @ini_text_alt;
border-radius: 2px;
padding: 1em;
margin-bottom: .5em;
@@ -40,22 +40,24 @@
#dokuwiki__aside h3.toggle {
font-size: 1em;
-}
-#dokuwiki__aside h3.toggle.closed {
- margin-bottom: 0;
- padding-bottom: 0;
-}
-#dokuwiki__aside h3.toggle.open {
- border-bottom: 1px solid __border__;
+
+ &.closed {
+ margin-bottom: 0;
+ padding-bottom: 0;
+ }
+ &.open {
+ border-bottom: 1px solid @ini_border;
+ }
}
.showSidebar #dokuwiki__content {
float: none;
margin-left: 0;
width: 100%;
-}
-.showSidebar #dokuwiki__content > .pad {
- margin-left: 0;
+
+ > .pad {
+ margin-left: 0;
+ }
}
[dir=rtl] .showSidebar #dokuwiki__content,
@@ -69,7 +71,7 @@
margin: 0 0 1em 0;
width: auto;
border-left-width: 0;
- border-bottom: 1px solid __border__;
+ border-bottom: 1px solid @ini_border;
}
[dir=rtl] #dw__toc {
float: none;
@@ -119,7 +121,7 @@
/* for screen widths in the smartphone range
********************************************************************/
-@media only screen and (max-width: __phone_width__) {
+@media only screen and (max-width: @ini_phone_width) {
#screen__mode {
z-index: 2; /* for detecting media queries in JavaScript (see script.js) */
@@ -133,9 +135,10 @@ body {
#dokuwiki__site {
max-width: 100%;
-}
-#dokuwiki__site > .site {
- padding: 0 .5em;
+
+ > .site {
+ padding: 0 .5em;
+ }
}
#dokuwiki__header {
padding: .5em 0;
@@ -154,19 +157,21 @@ body {
list-style: none;
padding-left: 0;
margin: 0;
+
+ li {
+ margin-left: .35em;
+ display: inline;
+ }
}
[dir=rtl] #dokuwiki__header ul.a11y.skip {
left: auto !important;
right: 0 !important;
float: left;
padding-right: 0;
-}
-#dokuwiki__header ul.a11y.skip li {
- margin-left: .35em;
- display: inline;
-}
-[dir=rtl] #dokuwiki__header ul.a11y.skip li {
- margin: 0 .35em 0 0;
+
+ li {
+ margin: 0 .35em 0 0;
+ }
}
#dokuwiki__header .headings,
@@ -264,13 +269,14 @@ body {
.dokuwiki label.block {
text-align: left;
+
+ span {
+ display: block;
+ }
}
[dir=rtl] .dokuwiki label.block {
text-align: right;
}
-.dokuwiki label.block span {
- display: block;
-}
/* _edit */
.dokuwiki div.section_highlight {
diff --git a/lib/tpl/dokuwiki/css/pagetools.css b/lib/tpl/dokuwiki/css/pagetools.less
index 21e5c13ec..850e75d7a 100644
--- a/lib/tpl/dokuwiki/css/pagetools.css
+++ b/lib/tpl/dokuwiki/css/pagetools.less
@@ -85,7 +85,7 @@
}
#dokuwiki__pagetools ul li a:before {
- content: url(images/pagetools-sprite.png);
+ content: url(images/pagetools-sprite.png?v=2);
display: inline-block;
font-size: 0;
line-height: 0;
@@ -101,10 +101,10 @@
#dokuwiki__pagetools:hover ul,
#dokuwiki__pagetools ul li a:focus,
#dokuwiki__pagetools ul li a:active {
- background-color: __background__;
- border-color: __border__;
+ background-color: @ini_background;
+ border-color: @ini_border;
border-radius: 2px;
- box-shadow: 2px 2px 2px __text_alt__;
+ box-shadow: 2px 2px 2px @ini_text_alt;
}
#dokuwiki__pagetools:hover ul li a,
@@ -124,7 +124,7 @@
[dir=rtl] #dokuwiki__pagetools:hover ul,
[dir=rtl] #dokuwiki__pagetools ul li a:focus {
- box-shadow: -2px 2px 2px __text_alt__;
+ box-shadow: -2px 2px 2px @ini_text_alt;
}
[dir=rtl] #dokuwiki__pagetools:hover li a,
@@ -158,264 +158,267 @@
text-decoration: none;
}
#dokuwiki__pagetools ul li a:hover {
- background-color: __background_alt__;
+ background-color: @ini_background_alt;
}
/*____________ all available icons in sprite ____________*/
+#dokuwiki__pagetools ul li a.edit:before {
+ margin-top: -90px;
+}
#dokuwiki__pagetools ul li a.edit {
- background-position: right 0;
+ background-position: right -90px;
}
#dokuwiki__pagetools ul li a.edit:hover,
#dokuwiki__pagetools ul li a.edit:active,
#dokuwiki__pagetools ul li a.edit:focus {
- background-position: right -45px;
+ background-position: right -135px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.edit {
- background-position: left 0;
+ background-position: left -90px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.edit:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.edit:active,
[dir=rtl] #dokuwiki__pagetools ul li a.edit:focus {
- background-position: left -45px;
+ background-position: left -135px;
}
#dokuwiki__pagetools ul li a.create:before {
- margin-top: -90px;
+ margin-top: -180px;
}
#dokuwiki__pagetools ul li a.create {
- background-position: right -90px;
+ background-position: right -180px;
}
#dokuwiki__pagetools ul li a.create:hover,
#dokuwiki__pagetools ul li a.create:active,
#dokuwiki__pagetools ul li a.create:focus {
- background-position: right -135px;
+ background-position: right -225px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.create {
- background-position: left -90px;
+ background-position: left -180px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.create:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.create:active,
[dir=rtl] #dokuwiki__pagetools ul li a.create:focus {
- background-position: left -135px;
+ background-position: left -225px;
}
#dokuwiki__pagetools ul li a.show {
- background-position: right -270px;
+ background-position: right -360px;
}
#dokuwiki__pagetools ul li a.show:before {
- margin-top: -270px;
+ margin-top: -360px;
}
#dokuwiki__pagetools ul li a.show:hover,
#dokuwiki__pagetools ul li a.show:active,
#dokuwiki__pagetools ul li a.show:focus {
- background-position: right -315px;
+ background-position: right -405px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.show {
- background-position: left -270px;
+ background-position: left -360px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.show:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.show:active,
[dir=rtl] #dokuwiki__pagetools ul li a.show:focus {
- background-position: left -315px;
+ background-position: left -405px;
}
#dokuwiki__pagetools ul li a.source {
- background-position: right -360px;
+ background-position: right -450px;
}
#dokuwiki__pagetools ul li a.source:before {
- margin-top: -360px;
+ margin-top: -450px;
}
#dokuwiki__pagetools ul li a.source:hover,
#dokuwiki__pagetools ul li a.source:active,
#dokuwiki__pagetools ul li a.source:focus {
- background-position: right -405px;
+ background-position: right -495px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.source {
- background-position: left -360px;
+ background-position: left -450px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.source:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.source:active,
[dir=rtl] #dokuwiki__pagetools ul li a.source:focus {
- background-position: left -405px;
+ background-position: left -495px;
}
#dokuwiki__pagetools ul li a.draft {
- background-position: right -180px;
+ background-position: right -270px;
}
#dokuwiki__pagetools ul li a.draft:before {
- margin-top: -180px;
+ margin-top: -270px;
}
#dokuwiki__pagetools ul li a.draft:hover,
#dokuwiki__pagetools ul li a.draft:active,
#dokuwiki__pagetools ul li a.draft:focus {
- background-position: right -225px;
+ background-position: right -315px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.draft {
- background-position: left -180px;
+ background-position: left -270px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.draft:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.draft:active,
[dir=rtl] #dokuwiki__pagetools ul li a.draft:focus {
- background-position: left -225px;
+ background-position: left -315px;
}
#dokuwiki__pagetools ul li a.revs {
- background-position: right -540px;
+ background-position: right -630px;
}
#dokuwiki__pagetools ul li a.revs:before {
- margin-top: -540px;
+ margin-top: -630px;
}
#dokuwiki__pagetools ul li a.revs:hover,
#dokuwiki__pagetools ul li a.revs:active,
#dokuwiki__pagetools ul li a.revs:focus,
.mode_revisions #dokuwiki__pagetools ul li a.revs {
- background-position: right -585px;
+ background-position: right -675px;
}
.mode_revisions #dokuwiki__pagetools ul li a.revs:before {
- margin-top: -585px;
+ margin-top: -675px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.revs {
- background-position: left -540px;
+ background-position: left -630px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.revs:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.revs:active,
[dir=rtl] #dokuwiki__pagetools ul li a.revs:focus,
[dir=rtl] .mode_revisions #dokuwiki__pagetools ul li a.revs {
- background-position: left -585px;
+ background-position: left -675px;
}
#dokuwiki__pagetools ul li a.backlink {
- background-position: right -630px;
+ background-position: right -720px;
}
#dokuwiki__pagetools ul li a.backlink:before {
- margin-top: -630px;
+ margin-top: -720px;
}
#dokuwiki__pagetools ul li a.backlink:hover,
#dokuwiki__pagetools ul li a.backlink:active,
#dokuwiki__pagetools ul li a.backlink:focus,
.mode_backlink #dokuwiki__pagetools ul li a.backlink {
- background-position: right -675px;
+ background-position: right -765px;
}
.mode_backlink #dokuwiki__pagetools ul li a.backlink:before {
- margin-top: -675px;
+ margin-top: -765px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.backlink {
- background-position: left -630px;
+ background-position: left -720px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.backlink:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.backlink:active,
[dir=rtl] #dokuwiki__pagetools ul li a.backlink:focus,
[dir=rtl] .mode_backlink #dokuwiki__pagetools ul li a.backlink {
- background-position: left -675px;
+ background-position: left -765px;
}
#dokuwiki__pagetools ul li a.top {
- background-position: right -810px;
+ background-position: right -900px;
}
#dokuwiki__pagetools ul li a.top:before{
- margin-top: -810px;
+ margin-top: -900px;
}
#dokuwiki__pagetools ul li a.top:hover,
#dokuwiki__pagetools ul li a.top:active,
#dokuwiki__pagetools ul li a.top:focus {
- background-position: right -855px;
+ background-position: right -945px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.top {
- background-position: left -810px;
+ background-position: left -900px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.top:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.top:active,
[dir=rtl] #dokuwiki__pagetools ul li a.top:focus {
- background-position: left -855px;
+ background-position: left -945px;
}
#dokuwiki__pagetools ul li a.revert {
- background-position: right -450px;
+ background-position: right -540px;
}
#dokuwiki__pagetools ul li a.revert:before {
- margin-top: -450px;
+ margin-top: -540px;
}
#dokuwiki__pagetools ul li a.revert:hover,
#dokuwiki__pagetools ul li a.revert:active,
#dokuwiki__pagetools ul li a.revert:focus,
.mode_revert #dokuwiki__pagetools ul li a.revert {
- background-position: right -495px;
+ background-position: right -585px;
}
.mode_revert #dokuwiki__pagetools ul li a.revert:before {
- margin-top: -450px;
+ margin-top: -540px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.revert {
- background-position: left -450px;
+ background-position: left -540px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.revert:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.revert:active,
[dir=rtl] #dokuwiki__pagetools ul li a.revert:focus,
[dir=rtl] .mode_revert #dokuwiki__pagetools ul li a.revert {
- background-position: left -495px;
+ background-position: left -585px;
}
#dokuwiki__pagetools ul li a.subscribe {
- background-position: right -720px;
+ background-position: right -810px;
}
#dokuwiki__pagetools ul li a.subscribe:before {
- margin-top: -720px;
+ margin-top: -810px;
}
#dokuwiki__pagetools ul li a.subscribe:hover,
#dokuwiki__pagetools ul li a.subscribe:active,
#dokuwiki__pagetools ul li a.subscribe:focus,
.mode_subscribe #dokuwiki__pagetools ul li a.subscribe {
- background-position: right -765px;
+ background-position: right -855px;
}
.mode_subscribe #dokuwiki__pagetools ul li a.subscribe:before {
- margin-top: -765px;
+ margin-top: -855px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.subscribe {
- background-position: left -720px;
+ background-position: left -810px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.subscribe:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.subscribe:active,
[dir=rtl] #dokuwiki__pagetools ul li a.subscribe:focus,
[dir=rtl] .mode_subscribe #dokuwiki__pagetools ul li a.subscribe {
- background-position: left -765px;
+ background-position: left -855px;
}
#dokuwiki__pagetools ul li a.mediaManager {
- background-position: right -900px;
+ background-position: right -990px;
}
#dokuwiki__pagetools ul li a.mediaManager:before {
- margin-top: -900px;
+ margin-top: -990px;
}
#dokuwiki__pagetools ul li a.mediaManager:hover,
#dokuwiki__pagetools ul li a.mediaManager:active,
#dokuwiki__pagetools ul li a.mediaManager:focus {
- background-position: right -945px;
+ background-position: right -1035px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager {
- background-position: left -900px;
+ background-position: left -990px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager:active,
[dir=rtl] #dokuwiki__pagetools ul li a.mediaManager:focus {
- background-position: left -945px;
+ background-position: left -1035px;
}
#dokuwiki__pagetools ul li a.back {
- background-position: right -990px;
+ background-position: right -1080px;
}
-#dokuwiki__pagetools ul li a.back {
- margin-top: -990px;
+#dokuwiki__pagetools ul li a.back:before {
+ margin-top: -1080px;
}
#dokuwiki__pagetools ul li a.back:hover,
#dokuwiki__pagetools ul li a.back:active,
#dokuwiki__pagetools ul li a.back:focus {
- background-position: right -1035px;
+ background-position: right -1125px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.back {
- background-position: left -990px;
+ background-position: left -1080px;
}
[dir=rtl] #dokuwiki__pagetools ul li a.back:hover,
[dir=rtl] #dokuwiki__pagetools ul li a.back:active,
[dir=rtl] #dokuwiki__pagetools ul li a.back:focus {
- background-position: left -1035px;
+ background-position: left -1125px;
}
diff --git a/lib/tpl/dokuwiki/css/structure.css b/lib/tpl/dokuwiki/css/structure.css
deleted file mode 100644
index 00642e90b..000000000
--- a/lib/tpl/dokuwiki/css/structure.css
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * This file provides styles for the general layout structure.
- *
- * @author Anika Henke <anika@selfthinker.org>
- */
-
-body {
- margin: 0 auto;
-}
-#dokuwiki__site {
- margin: 0 auto;
- max-width: __site_width__;
-}
-#dokuwiki__site > .site {
- padding: 0 .5em;
-}
-
-#dokuwiki__header {
- width: 100%;
-}
-#dokuwiki__header > .pad {
-}
- #dokuwiki__header .headings {
- float: left;
- }
- [dir=rtl] #dokuwiki__header .headings {
- float: right;
- text-align: right;
- }
- #dokuwiki__header .tools {
- float: right;
- text-align: right;
- }
- [dir=rtl] #dokuwiki__header .tools {
- float: left;
- text-align: left;
- }
-
-#dokuwiki__site .wrapper {
- position: relative;
-}
-
- #dokuwiki__aside {
- width: __sidebar_width__;
- float: left;
- position: relative;
- display: block;
- }
- [dir=rtl] #dokuwiki__aside {
- float: right;
- }
- #dokuwiki__aside > .pad {
- margin: 0 1.5em 0 0;
- }
- [dir=rtl] #dokuwiki__aside > .pad {
- margin: 0 0 0 1.5em;
- }
-
- .showSidebar #dokuwiki__content {
- float: right;
- margin-left: -__sidebar_width__;
- width: 100%;
- }
- [dir=rtl] .showSidebar #dokuwiki__content {
- float: left;
- margin-left: 0;
- margin-right: -__sidebar_width__;
- }
- .showSidebar #dokuwiki__content > .pad {
- margin-left: __sidebar_width__;
- }
- [dir=rtl] .showSidebar #dokuwiki__content > .pad {
- margin-left: 0;
- margin-right: __sidebar_width__;
- }
-
-#dokuwiki__footer {
- clear: both;
-}
-#dokuwiki__footer > .pad {
-}
diff --git a/lib/tpl/dokuwiki/css/structure.less b/lib/tpl/dokuwiki/css/structure.less
new file mode 100644
index 000000000..3ea2f83eb
--- /dev/null
+++ b/lib/tpl/dokuwiki/css/structure.less
@@ -0,0 +1,89 @@
+/**
+ * This file provides styles for the general layout structure.
+ *
+ * @author Anika Henke <anika@selfthinker.org>
+ */
+body {
+ margin: 0 auto;
+}
+
+#dokuwiki__site {
+ margin: 0 auto;
+ max-width: @ini_site_width;
+}
+
+#dokuwiki__site > .site {
+ padding: 0 .5em;
+}
+
+#dokuwiki__header {
+ width: 100%;
+
+ .headings {
+ float: left;
+ }
+
+ .tools {
+ float: right;
+ text-align: right;
+ }
+}
+
+[dir=rtl] #dokuwiki__header {
+ .headings {
+ float: right;
+ text-align: right;
+ }
+
+ .tools {
+ float: left;
+ text-align: left;
+ }
+}
+
+#dokuwiki__site .wrapper {
+ position: relative;
+}
+
+#dokuwiki__aside {
+ width: @ini_sidebar_width;
+ float: left;
+ position: relative;
+ display: block;
+
+ > .pad {
+ margin: 0 1.5em 0 0;
+ }
+}
+
+[dir=rtl] #dokuwiki__aside {
+ float: right;
+ > .pad {
+ margin: 0 0 0 1.5em;
+ }
+}
+
+.showSidebar #dokuwiki__content {
+ float: right;
+ margin-left: (-1 * @ini_sidebar_width);
+ width: 100%;
+
+ > .pad {
+ margin-left: @ini_sidebar_width;
+ }
+}
+
+[dir=rtl] .showSidebar #dokuwiki__content {
+ float: left;
+ margin-left: 0;
+ margin-right: (-1 * @ini_sidebar_width);
+
+ > .pad {
+ margin-left: 0;
+ margin-right: @ini_sidebar_width;
+ }
+}
+
+#dokuwiki__footer {
+ clear: both;
+}
diff --git a/lib/tpl/dokuwiki/detail.php b/lib/tpl/dokuwiki/detail.php
index d2ed530a3..7e46231d3 100644
--- a/lib/tpl/dokuwiki/detail.php
+++ b/lib/tpl/dokuwiki/detail.php
@@ -28,8 +28,8 @@ header('X-UA-Compatible: IE=edge,chrome=1');
<body>
<!--[if lte IE 7 ]><div id="IE7"><![endif]--><!--[if IE 8 ]><div id="IE8"><![endif]-->
- <div id="dokuwiki__site"><div id="dokuwiki__top"
- class="dokuwiki site mode_<?php echo $ACT ?>">
+ <div id="dokuwiki__site"><div id="dokuwiki__top" class="site <?php echo tpl_classes(); ?> <?php
+ echo ($showSidebar) ? 'showSidebar' : ''; ?> <?php echo ($hasSidebar) ? 'hasSidebar' : ''; ?>">
<?php include('tpl_header.php') ?>
@@ -109,16 +109,32 @@ header('X-UA-Compatible: IE=edge,chrome=1');
<h3 class="a11y"><?php echo $lang['page_tools']; ?></h3>
<div class="tools">
<ul>
- <?php // View in media manager; @todo: transfer logic to backend
+ <?php
+ $data = array();
+
+ // View in media manager; @todo: transfer logic to backend
$imgNS = getNS($IMG);
$authNS = auth_quickaclcheck("$imgNS:*");
if (($authNS >= AUTH_UPLOAD) && function_exists('media_managerURL')) {
$mmURL = media_managerURL(array('ns' => $imgNS, 'image' => $IMG));
- echo '<li><a href="'.$mmURL.'" class="mediaManager"><span>'.$lang['img_manager'].'</span></a></li>';
+ $data['mediaManager'] = '<li><a href="'.$mmURL.'" class="mediaManager"><span>'.$lang['img_manager'].'</span></a></li>';
}
- ?>
- <?php // Back to [ID]; @todo: transfer logic to backend
- echo '<li><a href="'.wl($ID).'" class="back"><span>'.$lang['img_backto'].' '.$ID.'</span></a></li>';
+
+ // Back to [ID]; @todo: transfer logic to backend
+ $data['img_backto'] = '<li><a href="'.wl($ID).'" class="back"><span>'.$lang['img_backto'].' '.$ID.'</span></a></li>';
+
+ // the page tools can be ammended through a custom plugin hook
+ // if you're deriving from this template and your design is close enough to
+ // the dokuwiki template you might want to trigger a DOKUWIKI event instead
+ // of using $conf['tpl'] here
+ $hook = 'TEMPLATE_'.strtoupper($conf['tpl']).'_PAGETOOLS_DISPLAY';
+ $evt = new Doku_Event($hook, $data);
+ if($evt->advise_before()){
+ foreach($evt->data as $k => $html) echo $html;
+ }
+ $evt->advise_after();
+ unset($data);
+ unset($evt);
?>
</ul>
</div>
diff --git a/lib/tpl/dokuwiki/images/pagetools-sprite.png b/lib/tpl/dokuwiki/images/pagetools-sprite.png
index 898f0f4a6..b6e808717 100644
--- a/lib/tpl/dokuwiki/images/pagetools-sprite.png
+++ b/lib/tpl/dokuwiki/images/pagetools-sprite.png
Binary files differ
diff --git a/lib/tpl/dokuwiki/images/pagetools/00_default.png b/lib/tpl/dokuwiki/images/pagetools/00_default.png
new file mode 100644
index 000000000..95d122e17
--- /dev/null
+++ b/lib/tpl/dokuwiki/images/pagetools/00_default.png
Binary files differ
diff --git a/lib/tpl/dokuwiki/main.php b/lib/tpl/dokuwiki/main.php
index 43a0c0da7..9e507d86d 100644
--- a/lib/tpl/dokuwiki/main.php
+++ b/lib/tpl/dokuwiki/main.php
@@ -27,9 +27,8 @@ $showSidebar = $hasSidebar && ($ACT=='show');
<body>
<!--[if lte IE 7 ]><div id="IE7"><![endif]--><!--[if IE 8 ]><div id="IE8"><![endif]-->
- <div id="dokuwiki__site"><div id="dokuwiki__top"
- class="dokuwiki site mode_<?php echo $ACT ?> <?php echo ($showSidebar) ? 'showSidebar' : '';
- ?> <?php echo ($hasSidebar) ? 'hasSidebar' : ''; ?>">
+ <div id="dokuwiki__site"><div id="dokuwiki__top" class="site <?php echo tpl_classes(); ?> <?php
+ echo ($showSidebar) ? 'showSidebar' : ''; ?> <?php echo ($hasSidebar) ? 'hasSidebar' : ''; ?>">
<?php include('tpl_header.php') ?>
@@ -75,12 +74,27 @@ $showSidebar = $hasSidebar && ($ACT=='show');
<div class="tools">
<ul>
<?php
- tpl_action('edit', 1, 'li', 0, '<span>', '</span>');
- tpl_action('revert', 1, 'li', 0, '<span>', '</span>');
- tpl_action('revisions', 1, 'li', 0, '<span>', '</span>');
- tpl_action('backlink', 1, 'li', 0, '<span>', '</span>');
- tpl_action('subscribe', 1, 'li', 0, '<span>', '</span>');
- tpl_action('top', 1, 'li', 0, '<span>', '</span>');
+ $data = array(
+ 'edit' => tpl_action('edit', 1, 'li', 1, '<span>', '</span>'),
+ 'revert' => tpl_action('revert', 1, 'li', 1, '<span>', '</span>'),
+ 'revisions' => tpl_action('revisions', 1, 'li', 1, '<span>', '</span>'),
+ 'backlink' => tpl_action('backlink', 1, 'li', 1, '<span>', '</span>'),
+ 'subscribe' => tpl_action('subscribe', 1, 'li', 1, '<span>', '</span>'),
+ 'top' => tpl_action('top', 1, 'li', 1, '<span>', '</span>')
+ );
+
+ // the page tools can be ammended through a custom plugin hook
+ // if you're deriving from this template and your design is close enough to
+ // the dokuwiki template you might want to trigger a DOKUWIKI event instead
+ // of using $conf['tpl'] here
+ $hook = 'TEMPLATE_'.strtoupper($conf['tpl']).'_PAGETOOLS_DISPLAY';
+ $evt = new Doku_Event($hook, $data);
+ if($evt->advise_before()){
+ foreach($evt->data as $k => $html) echo $html;
+ }
+ $evt->advise_after();
+ unset($data);
+ unset($evt);
?>
</ul>
</div>
diff --git a/lib/tpl/dokuwiki/style.ini b/lib/tpl/dokuwiki/style.ini
index 77bb98236..897b6e6da 100644
--- a/lib/tpl/dokuwiki/style.ini
+++ b/lib/tpl/dokuwiki/style.ini
@@ -9,10 +9,15 @@
; Define the stylesheets your template uses here. The second value
; defines for which output media the style should be loaded. Currently
; print, screen and all are supported.
+; You can reference CSS and LESS files here. Files referenced here will
+; be checked for updates when considering a cache rebuild while files
+; included through LESS' @import statements are not
[stylesheets]
-css/basic.css = screen
+css/mixins.less = screen
+
+css/basic.less = screen
css/_imgdetail.css = screen
css/_media_popup.css = screen
css/_media_fullscreen.css = screen
@@ -28,19 +33,20 @@ css/_edit.css = screen
css/_modal.css = screen
css/_forms.css = screen
css/_admin.css = screen
-css/structure.css = screen
-css/design.css = screen
-css/pagetools.css = screen
-css/content.css = screen
-css/includes.css = screen
+css/structure.less = screen
+css/design.less = screen
+css/pagetools.less = screen
+css/content.less = screen
-css/mobile.css = all
+css/mobile.less = all
css/print.css = print
; This section is used to configure some placeholder values used in
; the stylesheets. Changing this file is the simplest method to
; give your wiki a new look.
+; Placeholders defined here will also be made available as LESS variables
+; (with surrounding underscores removed, and the prefix @ini_ added)
[replacements]
@@ -48,32 +54,32 @@ css/print.css = print
;------ guaranteed dokuwiki color placeholders that every plugin can use
; main text and background colors
-__text__ = "#333"
-__background__ = "#fff"
+__text__ = "#333" ; @ini_text
+__background__ = "#fff" ; @ini_background
; alternative text and background colors
-__text_alt__ = "#999"
-__background_alt__ = "#eee"
+__text_alt__ = "#999" ; @ini_text_alt
+__background_alt__ = "#eee" ; @ini_background_alt
; neutral text and background colors
-__text_neu__ = "#666"
-__background_neu__ = "#ddd"
+__text_neu__ = "#666" ; @ini_text_neu
+__background_neu__ = "#ddd" ; @ini_background_neu
; border color
-__border__ = "#ccc"
+__border__ = "#ccc" ; @ini_border
; highlighted text (e.g. search snippets)
-__highlight__ = "#ff9"
+__highlight__ = "#ff9" ; @ini_highlight
;--------------------------------------------------------------------------
-__background_site__ = "#fbfaf9"
+__background_site__ = "#fbfaf9" ; @ini_background_site
; these are used for links
-__link__ = "#2b73b7"
-__existing__ = "#080"
-__missing__ = "#d30"
+__link__ = "#2b73b7" ; @ini_link
+__existing__ = "#080" ; @ini_existing
+__missing__ = "#d30" ; @ini_missing
; site and sidebar widths
-__site_width__ = "75em"
-__sidebar_width__ = "16em"
+__site_width__ = "75em" ; @ini_site_width
+__sidebar_width__ = "16em" ; @ini_sidebar_width
; cut off points for mobile devices
-__tablet_width__ = "800px"
-__phone_width__ = "480px"
+__tablet_width__ = "800px" ; @ini_tablet_width
+__phone_width__ = "480px" ; @ini_phone_width