summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnika Henke <anika@selfthinker.org>2014-01-26 17:38:22 +0000
committerAnika Henke <anika@selfthinker.org>2014-01-26 17:38:22 +0000
commit8fe276f7d4bf70c4a798e1c5e7bb3da72a33877d (patch)
tree1e3ce9edacc852741af07c070176bd04fb61c4b4
parentc5393ecb1aa570830d21e9dc95b4c21cd9aa9c01 (diff)
parentca605ff6763b98b580278988791dc5e57fc05a74 (diff)
downloadrpg-8fe276f7d4bf70c4a798e1c5e7bb3da72a33877d.tar.gz
rpg-8fe276f7d4bf70c4a798e1c5e7bb3da72a33877d.tar.bz2
Merge remote-tracking branch 'origin/master' into video-audio
-rw-r--r--.gitattributes6
-rw-r--r--.travis.yml12
-rw-r--r--_test/tests/inc/common_basicinfo.test.php10
-rw-r--r--_test/tests/inc/common_mediainfo.test.php10
-rw-r--r--_test/tests/inc/common_pageinfo.test.php66
-rw-r--r--_test/tests/inc/indexer_indexing.test.php17
-rw-r--r--_test/tests/inc/mailer.test.php14
-rw-r--r--_test/tests/inc/parser/parser_table.test.php19
-rw-r--r--_test/tests/lib/exe/css_at_import_less.test.php78
-rw-r--r--_test/tests/lib/exe/css_css_loadfile.test.php42
-rw-r--r--_test/tests/test/basic.test.php12
-rwxr-xr-xbin/striplangs.php2
-rw-r--r--data/deleted.files11
-rw-r--r--doku.php6
-rw-r--r--feed.php35
-rw-r--r--inc/Mailer.class.php10
-rw-r--r--inc/RemoteAPICore.php23
-rw-r--r--inc/Tar.class.php2
-rw-r--r--inc/actions.php2
-rw-r--r--inc/config_cascade.php3
-rw-r--r--inc/farm.php2
-rw-r--r--inc/form.php2
-rw-r--r--inc/html.php14
-rw-r--r--inc/indexer.php3
-rw-r--r--inc/lang/ar/lang.php14
-rw-r--r--inc/lang/bg/lang.php56
-rw-r--r--inc/lang/bn/admin.txt3
-rw-r--r--inc/lang/bn/adminplugins.txt1
-rw-r--r--inc/lang/bn/backlinks.txt3
-rw-r--r--inc/lang/bn/conflict.txt5
-rw-r--r--inc/lang/bn/denied.txt3
-rw-r--r--inc/lang/bn/diff.txt3
-rw-r--r--inc/lang/bn/draft.txt5
-rw-r--r--inc/lang/bn/edit.txt1
-rw-r--r--inc/lang/bn/editrev.txt2
-rw-r--r--inc/lang/bn/index.txt3
-rw-r--r--inc/lang/bn/lang.php119
-rw-r--r--inc/lang/da/lang.php2
-rw-r--r--inc/lang/de-informal/lang.php6
-rw-r--r--inc/lang/de/lang.php7
-rw-r--r--inc/lang/el/lang.php7
-rw-r--r--inc/lang/en/lang.php1
-rw-r--r--inc/lang/eo/lang.php4
-rw-r--r--inc/lang/es/lang.php6
-rw-r--r--inc/lang/fa/lang.php2
-rw-r--r--inc/lang/fi/lang.php17
-rw-r--r--inc/lang/fr/lang.php6
-rw-r--r--inc/lang/he/lang.php35
-rw-r--r--inc/lang/hu/lang.php6
-rw-r--r--inc/lang/id/lang.php16
-rw-r--r--inc/lang/it/lang.php5
-rw-r--r--inc/lang/ja/lang.php5
-rw-r--r--inc/lang/ja/subscr_digest.txt2
-rw-r--r--inc/lang/ja/subscr_list.txt2
-rw-r--r--inc/lang/ja/subscr_single.txt2
-rw-r--r--inc/lang/ko/denied.txt2
-rw-r--r--inc/lang/ko/editrev.txt2
-rw-r--r--inc/lang/ko/lang.php54
-rw-r--r--inc/lang/ko/mailtext.txt16
-rw-r--r--inc/lang/ko/password.txt4
-rw-r--r--inc/lang/ko/register.txt2
-rw-r--r--inc/lang/ko/registermail.txt14
-rw-r--r--inc/lang/ko/searchpage.txt4
-rw-r--r--inc/lang/ko/subscr_digest.txt6
-rw-r--r--inc/lang/ko/subscr_list.txt4
-rw-r--r--inc/lang/ko/subscr_single.txt12
-rw-r--r--inc/lang/ko/uploadmail.txt18
-rw-r--r--inc/lang/nl/edit.txt2
-rw-r--r--inc/lang/nl/lang.php2
-rw-r--r--inc/lang/no/lang.php33
-rw-r--r--inc/lang/pl/lang.php22
-rw-r--r--inc/lang/pt-br/editrev.txt2
-rw-r--r--inc/lang/pt-br/index.txt2
-rw-r--r--inc/lang/pt-br/lang.php8
-rw-r--r--inc/lang/ro/admin.txt2
-rw-r--r--inc/lang/ro/adminplugins.txt2
-rw-r--r--inc/lang/ro/backlinks.txt1
-rw-r--r--inc/lang/ro/conflict.txt7
-rw-r--r--inc/lang/ro/denied.txt6
-rw-r--r--inc/lang/ro/diff.txt3
-rw-r--r--inc/lang/ro/draft.txt7
-rw-r--r--inc/lang/ro/edit.txt3
-rw-r--r--inc/lang/ro/editrev.txt3
-rw-r--r--inc/lang/ro/index.txt4
-rw-r--r--inc/lang/ro/install.html12
-rw-r--r--inc/lang/ro/lang.php24
-rw-r--r--inc/lang/ro/locked.txt3
-rw-r--r--inc/lang/ro/login.txt6
-rw-r--r--inc/lang/ro/mailtext.txt23
-rw-r--r--inc/lang/ro/newpage.txt4
-rw-r--r--inc/lang/ro/norev.txt6
-rw-r--r--inc/lang/ro/password.txt8
-rw-r--r--inc/lang/ro/preview.txt3
-rw-r--r--inc/lang/ro/pwconfirm.txt13
-rw-r--r--inc/lang/ro/read.txt4
-rw-r--r--inc/lang/ro/recent.txt6
-rw-r--r--inc/lang/ro/register.txt3
-rw-r--r--inc/lang/ro/registermail.txt13
-rw-r--r--inc/lang/ro/resendpwd.txt4
-rw-r--r--inc/lang/ro/resetpwd.txt4
-rw-r--r--inc/lang/ro/revisions.txt7
-rw-r--r--inc/lang/ro/searchpage.txt2
-rw-r--r--inc/lang/ro/showrev.txt2
-rw-r--r--inc/lang/ro/stopwords.txt6
-rw-r--r--inc/lang/ro/subscr_digest.txt18
-rw-r--r--inc/lang/ro/subscr_form.txt3
-rw-r--r--inc/lang/ro/subscr_list.txt16
-rw-r--r--inc/lang/ro/subscr_single.txt22
-rw-r--r--inc/lang/ro/updateprofile.txt3
-rw-r--r--inc/lang/ro/uploadmail.txt8
-rw-r--r--inc/lang/ru/lang.php6
-rw-r--r--inc/lang/sk/lang.php4
-rw-r--r--inc/lang/sl/lang.php7
-rw-r--r--inc/lang/sv/lang.php10
-rw-r--r--inc/lang/sv/subscr_digest.txt19
-rw-r--r--inc/lang/vi/lang.php221
-rw-r--r--inc/lang/zh-tw/lang.php23
-rw-r--r--inc/lang/zh/lang.php13
-rw-r--r--inc/media.php68
-rw-r--r--inc/pageutils.php3
-rw-r--r--inc/parser/parser.php4
-rw-r--r--inc/parser/renderer.php12
-rw-r--r--inc/parserutils.php2
-rw-r--r--inc/template.php12
-rw-r--r--install.php10
-rw-r--r--lib/exe/css.php136
-rw-r--r--lib/exe/detail.php2
-rw-r--r--lib/images/_deprecated.txt12
-rw-r--r--lib/images/arrow_down.gifbin273 -> 0 bytes
-rw-r--r--lib/images/arrow_up.gifbin274 -> 0 bytes
-rw-r--r--lib/images/at.gifbin57 -> 0 bytes
-rw-r--r--lib/images/close.pngbin137 -> 0 bytes
-rw-r--r--lib/images/del.pngbin355 -> 0 bytes
-rw-r--r--lib/images/edit.gifbin142 -> 0 bytes
-rw-r--r--lib/images/list-minus.gifbin64 -> 0 bytes
-rw-r--r--lib/images/list-plus.gifbin67 -> 0 bytes
-rw-r--r--lib/images/pencil.pngbin391 -> 0 bytes
-rw-r--r--lib/plugins/acl/admin.php2
-rw-r--r--lib/plugins/acl/lang/bg/lang.php4
-rw-r--r--lib/plugins/acl/lang/fi/lang.php5
-rw-r--r--lib/plugins/acl/lang/id/lang.php4
-rw-r--r--lib/plugins/acl/lang/ko/lang.php3
-rw-r--r--lib/plugins/acl/lang/no/lang.php6
-rw-r--r--lib/plugins/acl/lang/pl/lang.php4
-rw-r--r--lib/plugins/acl/lang/vi/lang.php71
-rw-r--r--lib/plugins/authad/adLDAP/adLDAP.php1900
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPComputers.php304
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPContacts.php588
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPExchange.php778
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPFolders.php356
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPGroups.php1262
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPUsers.php1364
-rw-r--r--lib/plugins/authad/adLDAP/classes/adLDAPUtils.php526
-rw-r--r--lib/plugins/authad/adLDAP/collections/adLDAPCollection.php274
-rw-r--r--lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php92
-rw-r--r--lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php92
-rw-r--r--lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php92
-rw-r--r--lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php92
-rw-r--r--lib/plugins/authad/lang/ar/settings.php12
-rw-r--r--lib/plugins/authad/lang/bg/settings.php29
-rw-r--r--lib/plugins/authad/lang/de/settings.php3
-rw-r--r--lib/plugins/authad/lang/el/settings.php8
-rw-r--r--lib/plugins/authad/lang/es/settings.php2
-rw-r--r--lib/plugins/authad/lang/fi/settings.php7
-rw-r--r--lib/plugins/authad/lang/hu/settings.php2
-rw-r--r--lib/plugins/authad/lang/ko/settings.php4
-rw-r--r--lib/plugins/authad/lang/nl/settings.php2
-rw-r--r--lib/plugins/authad/lang/pl/settings.php7
-rw-r--r--lib/plugins/authad/lang/pt-br/settings.php2
-rw-r--r--lib/plugins/authad/lang/ru/settings.php7
-rw-r--r--lib/plugins/authad/lang/sk/settings.php5
-rw-r--r--lib/plugins/authad/lang/zh/settings.php2
-rw-r--r--lib/plugins/authldap/auth.php2
-rw-r--r--lib/plugins/authldap/lang/ar/settings.php13
-rw-r--r--lib/plugins/authldap/lang/bg/settings.php7
-rw-r--r--lib/plugins/authldap/lang/da/settings.php6
-rw-r--r--lib/plugins/authldap/lang/es/settings.php13
-rw-r--r--lib/plugins/authldap/lang/fi/settings.php9
-rw-r--r--lib/plugins/authldap/lang/he/settings.php8
-rw-r--r--lib/plugins/authldap/lang/it/settings.php4
-rw-r--r--lib/plugins/authldap/lang/ko/settings.php4
-rw-r--r--lib/plugins/authldap/lang/pl/settings.php5
-rw-r--r--lib/plugins/authldap/lang/ru/settings.php2
-rw-r--r--lib/plugins/authldap/lang/sk/settings.php6
-rw-r--r--lib/plugins/authldap/lang/zh-tw/settings.php6
-rw-r--r--lib/plugins/authldap/lang/zh/settings.php2
-rw-r--r--lib/plugins/authmysql/lang/bg/settings.php16
-rw-r--r--lib/plugins/authmysql/lang/da/settings.php17
-rw-r--r--lib/plugins/authmysql/lang/es/settings.php12
-rw-r--r--lib/plugins/authmysql/lang/hu/settings.php57
-rw-r--r--lib/plugins/authmysql/lang/it/settings.php7
-rw-r--r--lib/plugins/authmysql/lang/ja/settings.php2
-rw-r--r--lib/plugins/authmysql/lang/ko/settings.php9
-rw-r--r--lib/plugins/authmysql/lang/pl/settings.php5
-rw-r--r--lib/plugins/authmysql/lang/sk/settings.php4
-rw-r--r--lib/plugins/authpgsql/lang/bg/settings.php7
-rw-r--r--lib/plugins/authpgsql/lang/da/settings.php12
-rw-r--r--lib/plugins/authpgsql/lang/hu/settings.php59
-rw-r--r--lib/plugins/authpgsql/lang/ja/settings.php2
-rw-r--r--lib/plugins/authpgsql/lang/ko/settings.php9
-rw-r--r--lib/plugins/authpgsql/lang/sk/settings.php1
-rw-r--r--lib/plugins/config/lang/ko/lang.php4
-rw-r--r--lib/plugins/config/settings/config.class.php6
-rw-r--r--lib/plugins/plugin/classes/ap_download.class.php2
-rw-r--r--lib/plugins/plugin/lang/bg/lang.php4
-rw-r--r--lib/plugins/plugin/lang/fi/lang.php5
-rw-r--r--lib/plugins/plugin/lang/hu/admin_plugin.txt2
-rw-r--r--lib/plugins/plugin/lang/hu/lang.php9
-rw-r--r--lib/plugins/plugin/lang/id/lang.php5
-rw-r--r--lib/plugins/plugin/lang/ko/lang.php1
-rw-r--r--lib/plugins/plugin/lang/no/lang.php7
-rw-r--r--lib/plugins/plugin/lang/pl/lang.php4
-rw-r--r--lib/plugins/plugin/lang/zh/lang.php3
-rw-r--r--lib/plugins/popularity/lang/bg/lang.php5
-rw-r--r--lib/plugins/popularity/lang/fi/lang.php5
-rw-r--r--lib/plugins/popularity/lang/ko/lang.php1
-rw-r--r--lib/plugins/popularity/lang/no/lang.php7
-rw-r--r--lib/plugins/popularity/lang/pl/lang.php5
-rw-r--r--lib/plugins/revert/lang/ar/lang.php1
-rw-r--r--lib/plugins/revert/lang/bg/lang.php4
-rw-r--r--lib/plugins/revert/lang/fi/lang.php5
-rw-r--r--lib/plugins/revert/lang/hu/lang.php5
-rw-r--r--lib/plugins/revert/lang/ko/intro.txt2
-rw-r--r--lib/plugins/revert/lang/ko/lang.php2
-rw-r--r--lib/plugins/revert/lang/no/lang.php9
-rw-r--r--lib/plugins/revert/lang/pl/lang.php4
-rw-r--r--lib/plugins/revert/lang/sv/lang.php1
-rw-r--r--lib/plugins/usermanager/_test/csv_export.test.php59
-rw-r--r--lib/plugins/usermanager/_test/csv_import.test.php185
-rw-r--r--lib/plugins/usermanager/_test/mocks.class.php58
-rw-r--r--lib/plugins/usermanager/admin.php44
-rw-r--r--lib/plugins/usermanager/lang/bg/lang.php5
-rw-r--r--lib/plugins/usermanager/lang/da/lang.php18
-rw-r--r--lib/plugins/usermanager/lang/de/lang.php5
-rw-r--r--lib/plugins/usermanager/lang/fi/lang.php5
-rw-r--r--lib/plugins/usermanager/lang/fr/lang.php4
-rw-r--r--lib/plugins/usermanager/lang/hu/import.txt12
-rw-r--r--lib/plugins/usermanager/lang/hu/lang.php7
-rw-r--r--lib/plugins/usermanager/lang/id/lang.php5
-rw-r--r--lib/plugins/usermanager/lang/it/lang.php3
-rw-r--r--lib/plugins/usermanager/lang/ja/import.txt2
-rw-r--r--lib/plugins/usermanager/lang/ja/lang.php2
-rw-r--r--lib/plugins/usermanager/lang/ko/lang.php11
-rw-r--r--lib/plugins/usermanager/lang/no/lang.php7
-rw-r--r--lib/plugins/usermanager/lang/pl/lang.php5
-rw-r--r--lib/plugins/usermanager/lang/pt-br/lang.php6
-rw-r--r--lib/plugins/usermanager/lang/zh-tw/import.txt9
-rw-r--r--lib/plugins/usermanager/lang/zh-tw/lang.php32
-rw-r--r--lib/plugins/usermanager/lang/zh/lang.php2
-rw-r--r--lib/scripts/jquery/jquery-migrate.js1022
-rw-r--r--lib/scripts/jquery/jquery-migrate.min.js3
-rw-r--r--lib/scripts/jquery/jquery.min.js3
-rw-r--r--lib/tpl/dokuwiki/detail.php13
-rw-r--r--lib/tpl/dokuwiki/main.php23
-rw-r--r--lib/tpl/dokuwiki/style.ini3
255 files changed, 6440 insertions, 5222 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..0fefdf647
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,6 @@
+* text eol=lf
+
+*.png binary
+*.gif binary
+*.ico binary
+*.xcf binary
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..79eea48b7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,12 @@
+language: php
+php:
+ - "5.5"
+ - "5.4"
+ - "5.3"
+notifications:
+ irc:
+ channels:
+ - "chat.freenode.net#dokuwiki"
+ on_success: change
+ on_failure: change
+script: cd _test && phpunit --stderr
diff --git a/_test/tests/inc/common_basicinfo.test.php b/_test/tests/inc/common_basicinfo.test.php
index 0369474c9..8359c0877 100644
--- a/_test/tests/inc/common_basicinfo.test.php
+++ b/_test/tests/inc/common_basicinfo.test.php
@@ -18,12 +18,12 @@ class common_infofunctions_test extends DokuWikiTest {
function _get_info() {
global $USERINFO;
- $info = array (
- 'isadmin' => true,
+ $info = array (
+ 'isadmin' => true,
'ismanager' => true,
- 'userinfo' => $USERINFO,
- 'perm' => 255,
- 'namespace' => false,
+ 'userinfo' => $USERINFO,
+ 'perm' => 255,
+ 'namespace' => false,
'ismobile' => false,
'client' => 'testuser',
);
diff --git a/_test/tests/inc/common_mediainfo.test.php b/_test/tests/inc/common_mediainfo.test.php
index 0e67fbcd9..cc5b17ec7 100644
--- a/_test/tests/inc/common_mediainfo.test.php
+++ b/_test/tests/inc/common_mediainfo.test.php
@@ -18,12 +18,12 @@ class common_basicinfo_test extends DokuWikiTest {
function _get_info() {
global $USERINFO;
- $info = array (
- 'isadmin' => true,
+ $info = array (
+ 'isadmin' => true,
'ismanager' => true,
- 'userinfo' => $USERINFO,
- 'perm' => 255,
- 'namespace' => false,
+ 'userinfo' => $USERINFO,
+ 'perm' => 255,
+ 'namespace' => false,
'ismobile' => false,
'client' => 'testuser',
);
diff --git a/_test/tests/inc/common_pageinfo.test.php b/_test/tests/inc/common_pageinfo.test.php
index c54fbce26..0a1ea0a8f 100644
--- a/_test/tests/inc/common_pageinfo.test.php
+++ b/_test/tests/inc/common_pageinfo.test.php
@@ -31,18 +31,18 @@ class common_pageinfo_test extends DokuWikiTest {
'ismobile' => false,
'client' => 'testuser',
);
- $info['rev'] = null;
- $info['subscribed'] = false;
- $info['locked'] = false;
- $info['exists'] = false;
- $info['writable'] = true;
- $info['editable'] = true;
- $info['lastmod'] = false;
- $info['meta'] = array();
- $info['ip'] = null;
- $info['user'] = null;
- $info['sum'] = null;
- $info['editor'] = null;
+ $info['rev'] = null;
+ $info['subscribed'] = false;
+ $info['locked'] = false;
+ $info['exists'] = false;
+ $info['writable'] = true;
+ $info['editable'] = true;
+ $info['lastmod'] = false;
+ $info['meta'] = array();
+ $info['ip'] = null;
+ $info['user'] = null;
+ $info['sum'] = null;
+ $info['editor'] = null;
return $info;
}
@@ -72,15 +72,15 @@ class common_pageinfo_test extends DokuWikiTest {
$rev = filemtime($filename);
$info = $this->_get_expected_pageinfo();
- $info['id'] = 'wiki:syntax';
+ $info['id'] = 'wiki:syntax';
$info['namespace'] = 'wiki';
$info['filepath'] = $filename;
- $info['exists'] = true;
- $info['lastmod'] = $rev;
- $info['meta'] = p_get_metadata($ID);
+ $info['exists'] = true;
+ $info['lastmod'] = $rev;
+ $info['meta'] = p_get_metadata($ID);
$this->assertEquals($info, pageinfo());
- }
+ }
/**
* check info keys and values for anonymous user
@@ -88,8 +88,8 @@ class common_pageinfo_test extends DokuWikiTest {
function test_anonymoususer(){
global $ID,$conf,$REV;
- unset($_SERVER['REMOTE_USER']);
- global $USERINFO; $USERINFO = array();
+ unset($_SERVER['REMOTE_USER']);
+ global $USERINFO; $USERINFO = array();
$ID = 'wiki:syntax';
$filename = $conf['datadir'].'/wiki/syntax.txt';
@@ -104,15 +104,15 @@ class common_pageinfo_test extends DokuWikiTest {
$info['meta'] = p_get_metadata($ID);
$info['rev'] = '';
- $info = array_merge($info, array(
- 'isadmin' => false,
- 'ismanager' => false,
- 'perm' => 8,
- 'client' => '1.2.3.4',
+ $info = array_merge($info, array(
+ 'isadmin' => false,
+ 'ismanager' => false,
+ 'perm' => 8,
+ 'client' => '1.2.3.4',
));
unset($info['userinfo']);
$this->assertEquals($info, pageinfo());
- }
+ }
/**
* check info keys and values with $REV
@@ -135,7 +135,7 @@ class common_pageinfo_test extends DokuWikiTest {
$this->assertEquals($info, pageinfo());
$this->assertEquals($rev-100, $REV);
- }
+ }
/**
* check info keys and values with $RANGE
@@ -146,7 +146,7 @@ class common_pageinfo_test extends DokuWikiTest {
$ID = 'wiki:syntax';
$filename = $conf['datadir'].'/wiki/syntax.txt';
$rev = filemtime($filename);
- $range = '1000-2000';
+ $range = '1000-2000';
$info = $this->_get_expected_pageinfo();
$info['id'] = 'wiki:syntax';
@@ -160,18 +160,18 @@ class common_pageinfo_test extends DokuWikiTest {
// expected result $RANGE unchanged
$RANGE = $range;
- $this->assertEquals($info, pageinfo());
+ $this->assertEquals($info, pageinfo());
$this->assertFalse(isset($REV));
- $this->assertEquals($range,$RANGE);
+ $this->assertEquals($range,$RANGE);
// check $RANGE with $REV = current
// expected result: $RANGE unchanged, $REV cleared
$REV = $rev;
- $info['rev'] = '';
+ $info['rev'] = '';
- $this->assertEquals($info, pageinfo());
+ $this->assertEquals($info, pageinfo());
$this->assertEquals('',$REV);
- $this->assertEquals($range,$RANGE);
+ $this->assertEquals($range,$RANGE);
// check with a real $REV
// expected result: $REV and $RANGE are cleared
@@ -218,7 +218,7 @@ class common_pageinfo_test extends DokuWikiTest {
p_set_metadata($ID,array('last_change' => false));
$this->assertEquals($info, pageinfo());
- $this->assertEquals($info['meta']['last_change'], p_get_metadata($ID,'last_change'));
+ $this->assertEquals($info['meta']['last_change'], p_get_metadata($ID,'last_change'));
// fake an external edit, pageinfo should clear the last change from meta data
// and not return any editor data
diff --git a/_test/tests/inc/indexer_indexing.test.php b/_test/tests/inc/indexer_indexing.test.php
index 628e82e00..3d8278d6c 100644
--- a/_test/tests/inc/indexer_indexing.test.php
+++ b/_test/tests/inc/indexer_indexing.test.php
@@ -42,4 +42,21 @@ class indexer_indexing_test extends DokuWikiTest {
$query = array('001', '01');
$this->assertEquals(array('001' => array(), '01' => array('testpage')), $indexer->lookupKey('numkey', $query));
}
+
+ public function test_numeric_twice() {
+ $indexer = idx_get_indexer();
+ $indexer->addPageWords('testpage', '| 1010 | Dallas |');
+ $query = array('1010');
+ $this->assertEquals(array('1010' => array('testpage' => 1)), $indexer->lookup($query));
+ $indexer->addPageWords('notfound', '| 1010 | Dallas |');
+ $this->assertEquals(array('1010' => array('testpage' => 1, 'notfound' => 1)), $indexer->lookup($query));
+ }
+
+ public function test_numeric_twice_meta() {
+ $indexer = idx_get_indexer();
+ $indexer->addMetaKeys('testpage', 'onezero', array('1010'));
+ $indexer->addMetaKeys('notfound', 'onezero', array('1010'));
+ $query = '1010';
+ $this->assertEquals(array('notfound', 'testpage'), $indexer->lookupKey('onezero', $query));
+ }
} \ No newline at end of file
diff --git a/_test/tests/inc/mailer.test.php b/_test/tests/inc/mailer.test.php
index bac0c39ba..4541d9906 100644
--- a/_test/tests/inc/mailer.test.php
+++ b/_test/tests/inc/mailer.test.php
@@ -154,7 +154,19 @@ class mailer_test extends DokuWikiTest {
$headers['Cc'] = '';
$header = $mail->prepareHeaders();
$this->assertEquals(0, preg_match('/(^|\n)Bcc: (\n|$)/', $header), 'Bcc found in headers.');
- $this->assertEquals(0, preg_match('/(^|\n)Cc: (\n|$)/', $header), 'Bcc found in headers.');
+ $this->assertEquals(0, preg_match('/(^|\n)Cc: (\n|$)/', $header), 'Cc found in headers.');
+ }
+
+ function test_nullTOorCCorBCC() {
+ $mail = new TestMailer();
+ $headers = &$mail->propRef('headers');
+ $headers['Bcc'] = NULL;
+ $headers['Cc'] = NULL;
+ $headers['To'] = NULL;
+ $header = $mail->prepareHeaders();
+ $this->assertEquals(0, preg_match('/(^|\n)Bcc: (\n|$)/', $header), 'Bcc found in headers.');
+ $this->assertEquals(0, preg_match('/(^|\n)Cc: (\n|$)/', $header), 'Cc found in headers.');
+ $this->assertEquals(0, preg_match('/(^|\n)To: (\n|$)/', $header), 'To found in headers.');
}
/**
diff --git a/_test/tests/inc/parser/parser_table.test.php b/_test/tests/inc/parser/parser_table.test.php
index 542a307b8..bc19ebff9 100644
--- a/_test/tests/inc/parser/parser_table.test.php
+++ b/_test/tests/inc/parser/parser_table.test.php
@@ -626,5 +626,24 @@ def');
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
+
+ function testTable_FS1833() {
+ $syntax = " \n| Row 0 Col 1 |\n";
+ $this->P->addMode('table',new Doku_Parser_Mode_Table());
+ $this->P->parse($syntax);
+ $calls = array (
+ array('document_start',array()),
+ array('table_open',array(1, 1, 2)),
+ array('tablerow_open',array()),
+ array('tablecell_open',array(1,'left',1)),
+ array('cdata',array(' Row 0 Col 1 ')),
+ array('tablecell_close',array()),
+ array('tablerow_close',array()),
+ array('table_close',array(strlen($syntax))),
+ array('document_end',array()),
+ );
+ $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
+ }
+
}
diff --git a/_test/tests/lib/exe/css_at_import_less.test.php b/_test/tests/lib/exe/css_at_import_less.test.php
new file mode 100644
index 000000000..4a6efcf44
--- /dev/null
+++ b/_test/tests/lib/exe/css_at_import_less.test.php
@@ -0,0 +1,78 @@
+<?php
+
+require_once DOKU_INC.'lib/exe/css.php';
+
+class css_at_import_less_test extends DokuWikiTest {
+
+ protected $file = '';
+ protected $import = '';
+
+ public function setUpFiles($subdir = '') {
+
+ $dir = TMP_DIR . $subdir;
+ if (!is_dir($dir)) {
+ mkdir($dir, 0777, true);
+ }
+ if (!is_dir($dir)) {
+ $this->markTestSkipped('Could not create directory.');
+ }
+
+ $this->file = tempnam($dir, 'css');
+
+ $import = '';
+ do {
+ if ($import) unlink($import);
+ $import = tempnam($dir, 'less');
+ $ok = rename($import, $import.'.less');
+ } while (!$ok);
+
+ $this->import = $import.'.less';
+ }
+
+ private function csstest($input, $expected_css, $expected_less) {
+ $location = "http://test.com/";
+ io_saveFile($this->file, $input);
+ $css = css_loadfile($this->file, $location);
+ $less = css_parseless($css);
+ $this->assertEquals($expected_css, $css);
+ $this->assertEquals($expected_less, $less);
+ }
+
+ public function test_basic() {
+ $this->setUpFiles();
+
+ $import = preg_replace('#(^.*[/])#','',$this->import);
+ $in_css = '@import "'.$import.'";';
+ $in_less = '@foo: "bar";
+content: @foo;';
+
+ $expected_css = '@import "/'.$import.'";';
+ $expected_less = 'content: "bar";';
+
+ io_saveFile($this->import, $in_less);
+ $this->csstest($in_css, $expected_css, $expected_less);
+ }
+
+ public function test_subdirectory() {
+ $this->setUpFiles('/foo/bar');
+
+ $import = preg_replace('#(^.*[/])#','',$this->import);
+ $in_css = '@import "'.$import.'";';
+ $in_less = '@foo: "bar";
+content: @foo;';
+
+ $expected_css = '@import "/foo/bar/'.$import.'";';
+ $expected_less = 'content: "bar";';
+
+ io_saveFile($this->import, $in_less);
+ $this->csstest($in_css, $expected_css, $expected_less);
+ }
+
+ public function tearDown() {
+ unlink($this->file);
+ unlink($this->import);
+ unset($this->file, $this->import);
+ }
+}
+
+//Setup VIM: ex: et ts=4 sw=4 :
diff --git a/_test/tests/lib/exe/css_css_loadfile.test.php b/_test/tests/lib/exe/css_css_loadfile.test.php
index c89b69b2c..624becd29 100644
--- a/_test/tests/lib/exe/css_css_loadfile.test.php
+++ b/_test/tests/lib/exe/css_css_loadfile.test.php
@@ -3,13 +3,16 @@
require_once DOKU_INC.'lib/exe/css.php';
class css_css_loadfile_test extends DokuWikiTest {
+
+ protected $file = '';
+
public function setUp() {
- $this->file = tempnam('/tmp', 'css');
+ $this->file = tempnam(TMP_DIR, 'css');
}
private function csstest($input, $output = null, $location = 'http://www.example.com/') {
io_saveFile($this->file, $input);
- $this->assertEquals(css_loadfile($this->file, $location), (is_null($output) ? $input : $output));
+ $this->assertEquals((is_null($output) ? $input : $output), css_loadfile($this->file, $location));
}
public function test_url_relative() {
@@ -32,11 +35,15 @@ class css_css_loadfile_test extends DokuWikiTest {
public function test_import_relative() {
$this->csstest('@import "test/test.png";', '@import "http://www.example.com/test/test.png";');
$this->csstest('@import \'test/test.png\';', '@import \'http://www.example.com/test/test.png\';');
+ $this->csstest('@import url(test/test.png);', '@import url(http://www.example.com/test/test.png);');
+ $this->csstest('@import url("test/test.png");', '@import url("http://www.example.com/test/test.png");');
}
public function test_import_absolute() {
$this->csstest('@import "/test/test.png";');
$this->csstest('@import \'/test/test.png\';');
+ $this->csstest('@import url(/test/test.png);');
+ $this->csstest('@import url("/test/test.png");');
}
public function test_import_with_protocol() {
@@ -44,6 +51,37 @@ class css_css_loadfile_test extends DokuWikiTest {
$this->csstest('@import "https://www.test.com/test/test.png";');
$this->csstest('@import \'http://www.test.com/test/test.png\';');
$this->csstest('@import \'https://www.test.com/test/test.png\';');
+ $this->csstest('@import url(http://www.test.com/test/test.png);');
+ $this->csstest('@import url("http://www.test.com/test/test.png");');
+ }
+
+ public function test_less_basic() {
+ $this->csstest('@import "test.less"', '@import "/test.less"');
+ $this->csstest('@import "/test.less"', '@import "/test.less"');
+ $this->csstest('@import "foo/test.less"', '@import "/foo/test.less"');
+ $this->csstest('@import url(http://test.less)');
+ }
+
+ // more expected use, where less @import(ed) from e.g. lib/plugins/plugin_name
+ public function test_less_subdirectories() {
+
+ unlink($this->file);
+
+ $dir = TMP_DIR.'/foo/bar';
+ if (!is_dir($dir)) {
+ mkdir($dir, 0777, true);
+ }
+ if (!is_dir($dir)) {
+ $this->markTestSkipped('Could not create directory.');
+ }
+
+ $this->file = tempnam($dir, 'css');
+
+ $this->csstest('@import "test.less"', '@import "/foo/bar/test.less"');
+ $this->csstest('@import \'test.less\'', '@import \'/foo/bar/test.less\'');
+ $this->csstest('@import url(test.less)', '@import url(/foo/bar/test.less)');
+
+ $this->csstest('@import "abc/test.less"', '@import "/foo/bar/abc/test.less"');
}
public function tearDown() {
diff --git a/_test/tests/test/basic.test.php b/_test/tests/test/basic.test.php
index 05778ccf9..86acef935 100644
--- a/_test/tests/test/basic.test.php
+++ b/_test/tests/test/basic.test.php
@@ -123,11 +123,11 @@ class InttestsBasicTest extends DokuWikiTest {
$request = new TestRequest();
// doku
- $response = $request->get();
- $this->assertEquals('doku.php',$request->getScript());
+ $response = $request->get();
+ $this->assertEquals('doku.php',$request->getScript());
- $response = $request->get(array(),'/doku.php?id=wiki:dokuwiki&test=foo');
- $this->assertEquals('doku.php',$request->getScript());
+ $response = $request->get(array(),'/doku.php?id=wiki:dokuwiki&test=foo');
+ $this->assertEquals('doku.php',$request->getScript());
// fetch
$response = $request->get(array(),'/lib/exe/fetch.php?media=wiki:dokuwiki-128.png');
@@ -149,8 +149,8 @@ class InttestsBasicTest extends DokuWikiTest {
$request = new TestRequest();
$response = $request->get(array(),'/lib/exe/fetch.php?media=wiki:dokuwiki-128.png');
- $headers = $response->getHeaders();
- $this->assertTrue(!empty($headers));
+ $headers = $response->getHeaders();
+ $this->assertTrue(!empty($headers));
}
function testGetHeader(){
diff --git a/bin/striplangs.php b/bin/striplangs.php
index ac95626c9..2bfddcea4 100755
--- a/bin/striplangs.php
+++ b/bin/striplangs.php
@@ -15,7 +15,7 @@ require_once DOKU_INC.'inc/cliopts.php';
function usage($show_examples = false) {
print "Usage: striplangs.php [-h [-x]] [-e] [-k lang1[,lang2]..[,langN]]
- Removes all languages from the instalation, besides the ones
+ Removes all languages from the installation, besides the ones
after the -k option. English language is never removed!
OPTIONS
diff --git a/data/deleted.files b/data/deleted.files
index 59f1f0ab8..63335d3cc 100644
--- a/data/deleted.files
+++ b/data/deleted.files
@@ -2,6 +2,17 @@
# but were removed later. An up to date DokuWiki should not have any of
# the files installed
+# removed in 2013-11-18
+lib/images/arrow_down.gif
+lib/images/arrow_up.gif
+lib/images/at.gif
+lib/images/close.png
+lib/images/del.png
+lib/images/edit.gif
+lib/images/list-minus.gif
+lib/images/list-plus.gif
+lib/images/pencil.png
+
# removed in 2013-10-28
lib/images/interwiki/meatball.gif
lib/images/interwiki/wiki.gif
diff --git a/doku.php b/doku.php
index b7d9ec0eb..d861aa4fb 100644
--- a/doku.php
+++ b/doku.php
@@ -9,7 +9,7 @@
*/
// update message version
-$updateVersion = 41;
+$updateVersion = 43;
// xdebug_start_profiling();
@@ -47,10 +47,10 @@ $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
$SUF = cleanText($INPUT->post->str('suffix'));
$SUM = $INPUT->post->str('summary');
-//make infos about the selected page available
+//make info about the selected page available
$INFO = pageinfo();
-//export minimal infos to JS, plugins can add more
+//export minimal info to JS, plugins can add more
$JSINFO['id'] = $ID;
$JSINFO['namespace'] = (string) $INFO['namespace'];
diff --git a/feed.php b/feed.php
index 77c8b28df..bdce666d2 100644
--- a/feed.php
+++ b/feed.php
@@ -429,22 +429,19 @@ function rss_buildItems(&$rss, &$data, $opt) {
$cat = getNS($id);
if($cat) $item->category = $cat;
}
-
- // Add only visible items
- if(isVisiblePage($id)) {
- // finally add the item to the feed object, after handing it to registered plugins
- $evdata = array(
- 'item' => &$item,
- 'opt' => &$opt,
- 'ditem' => &$ditem,
- 'rss' => &$rss
- );
- $evt = new Doku_Event('FEED_ITEM_ADD', $evdata);
- if($evt->advise_before()) {
- $rss->addItem($item);
- }
- $evt->advise_after(); // for completeness
+
+ // finally add the item to the feed object, after handing it to registered plugins
+ $evdata = array(
+ 'item' => &$item,
+ 'opt' => &$opt,
+ 'ditem' => &$ditem,
+ 'rss' => &$rss
+ );
+ $evt = new Doku_Event('FEED_ITEM_ADD', $evdata);
+ if($evt->advise_before()) {
+ $rss->addItem($item);
}
+ $evt->advise_after(); // for completeness
}
}
$event->advise_after();
@@ -479,8 +476,12 @@ function rssListNamespace($opt) {
$ns = str_replace(':', '/', $ns);
$data = array();
- sort($data);
- search($data, $conf['datadir'], 'search_list', '', $ns);
+ $search_opts = array(
+ 'depth' => 1,
+ 'pagesonly' => true,
+ 'listfiles' => true
+ );
+ search($data, $conf['datadir'], 'search_universal', $search_opts, $ns);
return $data;
}
diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php
index 186bd531a..2ac2c1d60 100644
--- a/inc/Mailer.class.php
+++ b/inc/Mailer.class.php
@@ -576,7 +576,7 @@ class Mailer {
protected function prepareHeaders() {
$headers = '';
foreach($this->headers as $key => $val) {
- if ($val === '') continue;
+ if ($val === '' || is_null($val)) continue;
$headers .= $this->wrappedHeaderLine($key, $val);
}
return $headers;
@@ -640,16 +640,16 @@ class Mailer {
) return false;
// The To: header is special
- if(isset($this->headers['To'])) {
- $to = $this->headers['To'];
+ if(array_key_exists('To', $this->headers)) {
+ $to = (string)$this->headers['To'];
unset($this->headers['To']);
} else {
$to = '';
}
// so is the subject
- if(isset($this->headers['Subject'])) {
- $subject = $this->headers['Subject'];
+ if(array_key_exists('Subject', $this->headers)) {
+ $subject = (string)$this->headers['Subject'];
unset($this->headers['Subject']);
} else {
$subject = '';
diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php
index 74c6689ac..a26c2d0de 100644
--- a/inc/RemoteAPICore.php
+++ b/inc/RemoteAPICore.php
@@ -3,7 +3,7 @@
/**
* Increased whenever the API is changed
*/
-define('DOKU_API_VERSION', 8);
+define('DOKU_API_VERSION', 9);
class RemoteAPICore {
@@ -24,6 +24,10 @@ class RemoteAPICore {
'return' => 'int',
'doc' => 'Tries to login with the given credentials and sets auth cookies.',
'public' => '1'
+ ), 'dokuwiki.logoff' => array(
+ 'args' => array(),
+ 'return' => 'int',
+ 'doc' => 'Tries to logoff by expiring auth cookies and the associated PHP session.'
), 'dokuwiki.getPagelist' => array(
'args' => array('string', 'array'),
'return' => 'array',
@@ -88,12 +92,12 @@ class RemoteAPICore {
), 'wiki.getPageInfo' => array(
'args' => array('string'),
'return' => 'array',
- 'doc' => 'Returns a struct with infos about the page.',
+ 'doc' => 'Returns a struct with info about the page.',
'name' => 'pageInfo'
), 'wiki.getPageInfoVersion' => array(
'args' => array('string', 'int'),
'return' => 'array',
- 'doc' => 'Returns a struct with infos about the page.',
+ 'doc' => 'Returns a struct with info about the page.',
'name' => 'pageInfo'
), 'wiki.getPageVersions' => array(
'args' => array('string', 'int'),
@@ -136,7 +140,7 @@ class RemoteAPICore {
), 'wiki.getAttachmentInfo' => array(
'args' => array('string'),
'return' => 'array',
- 'doc' => 'Returns a struct with infos about the attachment.'
+ 'doc' => 'Returns a struct with info about the attachment.'
), 'dokuwiki.getXMLRPCAPIVersion' => array(
'args' => array(),
'name' => 'getAPIVersion',
@@ -767,6 +771,17 @@ class RemoteAPICore {
return $ok;
}
+ function logoff(){
+ global $conf;
+ global $auth;
+ if(!$conf['useacl']) return 0;
+ if(!$auth) return 0;
+
+ auth_logoff();
+
+ return 1;
+ }
+
private function resolvePageId($id) {
$id = cleanID($id);
if(empty($id)) {
diff --git a/inc/Tar.class.php b/inc/Tar.class.php
index bc87d7d29..903f7f35c 100644
--- a/inc/Tar.class.php
+++ b/inc/Tar.class.php
@@ -114,7 +114,7 @@ class Tar {
$header = $this->parseHeader($read);
if(!is_array($header)) continue;
- $this->skipbytes(ceil($header['size'] / 512) * 512, 1);
+ $this->skipbytes(ceil($header['size'] / 512) * 512);
$result[] = $header;
}
diff --git a/inc/actions.php b/inc/actions.php
index 5a59d852d..50cbe369f 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -53,7 +53,7 @@ function act_dispatch(){
}
}
- //display some infos
+ //display some info
if($ACT == 'check'){
check();
$ACT = 'show';
diff --git a/inc/config_cascade.php b/inc/config_cascade.php
index e1ab0eead..2c4f1612b 100644
--- a/inc/config_cascade.php
+++ b/inc/config_cascade.php
@@ -50,9 +50,6 @@ $config_cascade = array_merge(
),
'userstyle' => array(
'screen' => DOKU_CONF.'userstyle.css',
- // @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
- 'rtl' => DOKU_CONF.'userrtl.css',
'print' => DOKU_CONF.'userprint.css',
'feed' => DOKU_CONF.'userfeed.css',
'all' => DOKU_CONF.'userall.css',
diff --git a/inc/farm.php b/inc/farm.php
index 54692928d..cee61816c 100644
--- a/inc/farm.php
+++ b/inc/farm.php
@@ -135,9 +135,7 @@ $config_cascade = array(
),
),
'userstyle' => array(
- 'default' => DOKU_CONF.'userstyle.css', // 'default' was renamed to 'screen' on 2011-02-26, so will be deprecated in the next version
'screen' => DOKU_CONF.'userstyle.css',
- 'rtl' => DOKU_CONF.'userrtl.css', // deprecated since version after 2012-04-09
'print' => DOKU_CONF.'userprint.css',
'feed' => DOKU_CONF.'userfeed.css',
'all' => DOKU_CONF.'userall.css',
diff --git a/inc/form.php b/inc/form.php
index bdf520a2e..a4cd2e682 100644
--- a/inc/form.php
+++ b/inc/form.php
@@ -680,7 +680,7 @@ function form_wikitext($attrs) {
// mandatory attributes
unset($attrs['name']);
unset($attrs['id']);
- return '<textarea name="wikitext" id="wiki__text" '
+ return '<textarea name="wikitext" id="wiki__text" dir="auto" '
.buildAttributes($attrs,true).'>'.DOKU_LF
.formText($attrs['_text'])
.'</textarea>';
diff --git a/inc/html.php b/inc/html.php
index bbe29e371..7f473cdb6 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -28,20 +28,6 @@ function html_wikilink($id,$name=null,$search=''){
}
/**
- * Helps building long attribute lists
- *
- * @deprecated Use buildAttributes instead
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-function html_attbuild($attributes){
- $ret = '';
- foreach ( $attributes as $key => $value ) {
- $ret .= $key.'="'.formText($value).'" ';
- }
- return trim($ret);
-}
-
-/**
* The loginform
*
* @author Andreas Gohr <andi@splitbrain.org>
diff --git a/inc/indexer.php b/inc/indexer.php
index 658fb966b..07f29b542 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', 7);
+define('INDEXER_VERSION', 8);
// 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);
@@ -215,6 +215,7 @@ class Doku_Indexer {
foreach (array_keys($words) as $wlen) {
$word_idx = $this->getIndex('w', $wlen);
foreach ($words[$wlen] as $word => $freq) {
+ $word = (string)$word;
$wid = array_search($word, $word_idx, true);
if ($wid === false) {
$wid = count($word_idx);
diff --git a/inc/lang/ar/lang.php b/inc/lang/ar/lang.php
index fdb407da0..157513429 100644
--- a/inc/lang/ar/lang.php
+++ b/inc/lang/ar/lang.php
@@ -8,6 +8,7 @@
* @author Usama Akkad <uahello@gmail.com>
* @author uahello@gmail.com
* @author Ahmad Abd-Elghany <tolpa1@gmail.com>
+ * @author alhajr <alhajr300@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'rtl';
@@ -32,8 +33,8 @@ $lang['btn_upload'] = 'ارفع';
$lang['btn_cancel'] = 'ألغ';
$lang['btn_index'] = 'خريطة موقع';
$lang['btn_secedit'] = 'حرر';
-$lang['btn_login'] = 'لج';
-$lang['btn_logout'] = 'اخرج';
+$lang['btn_login'] = 'تسجيل الدخول';
+$lang['btn_logout'] = 'خروج';
$lang['btn_admin'] = 'المدير';
$lang['btn_update'] = 'حدّث';
$lang['btn_delete'] = 'احذف';
@@ -266,6 +267,8 @@ $lang['subscr_m_unsubscribe'] = 'ألغ الاشتراك';
$lang['subscr_m_subscribe'] = 'اشترك';
$lang['subscr_m_receive'] = 'استقبال';
$lang['subscr_style_every'] = 'بريدا على كل تغيير';
+$lang['subscr_style_digest'] = 'البريد الإلكتروني, ملخص للتغييرات لكل صفحة (كل يوم %.2f)';
+$lang['subscr_style_list'] = 'قائمة بالصفحات التي تم تغييرها منذ آخر بريد الإلكتروني (كل يوم %.2f)';
$lang['authtempfail'] = 'تصريح المشترك غير متوفر مؤقتاً، إن استمرت هذه الحالة يرجى مراسلة المدير';
$lang['authpwdexpire'] = 'ستنتهي صلاحية كلمة السر في %d . عليك بتغييرها سريعا.';
$lang['i_chooselang'] = 'اختر لغتك';
@@ -297,8 +300,12 @@ $lang['i_policy'] = 'تصريح ACL مبدئي';
$lang['i_pol0'] = 'ويكي مفتوحة؛ أي القراءة والكتابة والتحميل مسموحة للجميع';
$lang['i_pol1'] = 'ويكي عامة؛ أي القراءة للجميع ولكن الكتابة والتحميل للمشتركين المسجلين فقط';
$lang['i_pol2'] = 'ويكي مغلقة؛ أي القراءة والكتابة والتحميل للمشتركين المسجلين فقط';
+$lang['i_allowreg'] = 'السماح للمستخدمين بتسجيل أنفسهم';
$lang['i_retry'] = 'إعادة المحاولة';
$lang['i_license'] = 'اختر الرخصة التي تريد وضع المحتوى تحتها:';
+$lang['i_license_none'] = 'لا تظهر أية معلومات للترخيص';
+$lang['i_pop_field'] = 'من فضلك، ساعدنا على تحسين تجربة دوكي ويكي:';
+$lang['i_pop_label'] = 'مرة واحدة في شهر، إرسال بيانات استخدام المجهول للمطورين دوكي ويكي';
$lang['recent_global'] = 'انت تراقب حاليا التغييرات داخل نطاق <b>%s</b>. يمكنك أيضا <a href="%s">عرض أحدث تغييرات الويكي كلها</a>.';
$lang['years'] = '%d سنة مضت';
$lang['months'] = '%d شهرا مضى';
@@ -331,3 +338,6 @@ $lang['media_perm_read'] = 'عفوا، لست مخولا بقراءة ال
$lang['media_perm_upload'] = 'عفوا، لست مخولا برفع الملفات.';
$lang['media_update'] = 'ارفع إصدارا أحدث';
$lang['media_restore'] = 'استرجع هذه النسخة';
+$lang['currentns'] = 'مساحة الاسم الحالية';
+$lang['searchresult'] = 'نتيجة البحث';
+$lang['wikimarkup'] = 'علامات الوكي';
diff --git a/inc/lang/bg/lang.php b/inc/lang/bg/lang.php
index e909980db..bb74ff1ca 100644
--- a/inc/lang/bg/lang.php
+++ b/inc/lang/bg/lang.php
@@ -1,20 +1,20 @@
<?php
+
/**
- * Bulgarian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Nikolay Vladimirov <nikolay@vladimiroff.com>
* @author Viktor Usunov <usun0v@mail.bg>
* @author Kiril <neohidra@gmail.com>
+ * @author Ivan Peltekov <ivan.peltekov@abv.bg>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
-$lang['doublequoteopening'] = '"'; //&ldquo;
-$lang['doublequoteclosing'] = '"'; //&rdquo;
-$lang['singlequoteopening'] = '‘'; //&lsquo;
-$lang['singlequoteclosing'] = '’'; //&rsquo;
-$lang['apostrophe'] = '’'; //&rsquo;
-
+$lang['doublequoteopening'] = '"';
+$lang['doublequoteclosing'] = '"';
+$lang['singlequoteopening'] = '‘';
+$lang['singlequoteclosing'] = '’';
+$lang['apostrophe'] = '’';
$lang['btn_edit'] = 'Редактиране';
$lang['btn_source'] = 'Преглед на кода';
$lang['btn_show'] = 'Преглед на страницата';
@@ -50,7 +50,7 @@ $lang['btn_revert'] = 'Възстановяване';
$lang['btn_register'] = 'Регистриране';
$lang['btn_apply'] = 'Прилагане';
$lang['btn_media'] = 'Диспечер на файлове';
-
+$lang['btn_deleteuser'] = 'Изтрий профила ми';
$lang['loggedinas'] = 'Вписани сте като';
$lang['user'] = 'Потребител';
$lang['pass'] = 'Парола';
@@ -62,10 +62,10 @@ $lang['fullname'] = 'Истинско име';
$lang['email'] = 'Електронна поща';
$lang['profile'] = 'Потребителски профил';
$lang['badlogin'] = 'Грешно потребителско име или парола.';
+$lang['badpassconfirm'] = 'Съжаляваме, паролата е грешна';
$lang['minoredit'] = 'Промените са незначителни';
-$lang['draftdate'] = 'Черновата е автоматично записана на'; // full dformat date will be added
+$lang['draftdate'] = 'Черновата е автоматично записана на';
$lang['nosecedit'] = 'Страницата бе междувременно променена, презареждане на страницата поради неактуална информация.';
-
$lang['regmissing'] = 'Моля, попълнете всички полета.';
$lang['reguexists'] = 'Вече съществува потребител с избраното име.';
$lang['regsuccess'] = 'Потребителят е създаден, а паролата е пратена по електронната поща.';
@@ -75,12 +75,15 @@ $lang['regbadmail'] = 'Въведеният адрес изглежд
$lang['regbadpass'] = 'Двете въведени пароли не съвпадат, моля опитайте отново.';
$lang['regpwmail'] = 'Паролата ви за DokuWiki';
$lang['reghere'] = 'Все още нямате профил? Направете си';
-
$lang['profna'] = 'Wiki-то не поддържа промяна на профила';
$lang['profnochange'] = 'Няма промени.';
$lang['profnoempty'] = 'Въвеждането на име и ел. поща е задължително';
$lang['profchanged'] = 'Потребителският профил е обновен успешно.';
-
+$lang['profnodelete'] = 'Не е възможно изтриване на потребители в това wiki ';
+$lang['profdeleteuser'] = 'Изтрий профила ми';
+$lang['profdeleted'] = 'Вашият профил е премахнат от това wiki ';
+$lang['profconfdelete'] = 'Искам да изтрия профила си от това wiki. <br/> Веднъж изтрит, профила не може да бъде възстановен!';
+$lang['profconfdeletemissing'] = 'Не и маркирана опцията за потвърждение';
$lang['pwdforget'] = 'Забравили сте паролата си? Получете нова';
$lang['resendna'] = 'Wiki-то не поддържа повторно пращане на паролата.';
$lang['resendpwd'] = 'Задаване на нова парола за';
@@ -89,10 +92,8 @@ $lang['resendpwdnouser'] = 'Потребителят не е намере
$lang['resendpwdbadauth'] = 'Кодът за потвърждение е невалиден. Проверете дали сте използвали целия линк за потвърждение.';
$lang['resendpwdconfirm'] = 'Линк за потвърждение е пратен по електронната поща.';
$lang['resendpwdsuccess'] = 'Новата ви паролата е пратена по електронната поща.';
-
$lang['license'] = 'Ако не е посочено друго, съдържанието на Wiki-то е лицензирано под следния лиценз:';
$lang['licenseok'] = 'Бележка: Редактирайки страницата, Вие се съгласявате да лицензирате промените (които сте направили) под следния лиценз:';
-
$lang['searchmedia'] = 'Търсене на файл: ';
$lang['searchmedia_in'] = 'Търсене в %s';
$lang['txt_upload'] = 'Изберете файл за качване';
@@ -101,7 +102,6 @@ $lang['txt_overwrt'] = 'Презапиши съществуващит
$lang['maxuploadsize'] = 'Макс. размер за отделните файлове е %s.';
$lang['lockedby'] = 'В момента е заключена от';
$lang['lockexpire'] = 'Ще бъде отключена на';
-
$lang['js']['willexpire'] = 'Страницата ще бъде отключена за редактиране след минута.\nЗа предотвратяване на конфликти, ползвайте бутона "Преглед", за рестартиране на брояча за заключване.';
$lang['js']['notsavedyet'] = 'Незаписаните промени ще бъдат загубени. Желаете ли да продължите?';
$lang['js']['searchmedia'] = 'Търсене на файлове';
@@ -143,10 +143,8 @@ $lang['js']['media_done_btn'] = 'Готово';
$lang['js']['media_drop'] = 'Влачете и пуснете файливе тук, за да бъдат качени';
$lang['js']['media_cancel'] = 'премахване';
$lang['js']['media_overwrt'] = 'Презапиши съществуващите файлове';
-
$lang['rssfailed'] = 'Възникна грешка при получаването на емисията: ';
$lang['nothingfound'] = 'Нищо не е открито.';
-
$lang['mediaselect'] = 'Файлове';
$lang['fileupload'] = 'Качване на файлове';
$lang['uploadsucc'] = 'Качването е успешно';
@@ -171,7 +169,6 @@ $lang['mediaextchange'] = 'Разширението на файла е с
$lang['reference'] = 'Връзки за';
$lang['ref_inuse'] = 'Файлът не може да бъде изтрит, защото все още се ползва от следните страници:';
$lang['ref_hidden'] = 'Някои връзки са към страници, които нямате права да четете';
-
$lang['hits'] = 'Съвпадения';
$lang['quickhits'] = 'Съвпадащи имена на страници';
$lang['toc'] = 'Съдържание';
@@ -201,18 +198,15 @@ $lang['site_tools'] = 'Инструменти за сайта';
$lang['page_tools'] = 'Инструменти за страници';
$lang['skip_to_content'] = 'към съдържанието';
$lang['sidebar'] = 'Странична лента';
-
$lang['mail_newpage'] = 'добавена страница: ';
$lang['mail_changed'] = 'променена страница: ';
$lang['mail_subscribe_list'] = 'променени страници в именно пространство: ';
$lang['mail_new_user'] = 'нов потребител: ';
$lang['mail_upload'] = 'качен файл: ';
-
$lang['changes_type'] = 'Преглед на променените';
$lang['pages_changes'] = 'Страници';
$lang['media_changes'] = 'Файлове';
$lang['both_changes'] = 'Страници и файлове';
-
$lang['qb_bold'] = 'Удебелен текст';
$lang['qb_italic'] = 'Курсив текст';
$lang['qb_underl'] = 'Подчертан текст';
@@ -237,11 +231,8 @@ $lang['qb_media'] = 'Добавяне на изображения
$lang['qb_sig'] = 'Вмъкване на подпис';
$lang['qb_smileys'] = 'Усмивчици';
$lang['qb_chars'] = 'Специални знаци';
-
$lang['upperns'] = 'към майчиното именно пространство';
-
$lang['admin_register'] = 'Добавяне на нов потребител';
-
$lang['metaedit'] = 'Редактиране на метаданни';
$lang['metasaveerr'] = 'Записването на метаданните се провали';
$lang['metasaveok'] = 'Метаданните са запазени успешно';
@@ -259,7 +250,6 @@ $lang['img_keywords'] = 'Ключови думи';
$lang['img_width'] = 'Ширина';
$lang['img_height'] = 'Височина';
$lang['img_manager'] = 'Преглед в диспечера на файлове';
-
$lang['subscr_subscribe_success'] = '%s е добавен към списъка с абониралите се за %s';
$lang['subscr_subscribe_error'] = 'Грешка при добавянето на %s към списъка с абониралите се за %s';
$lang['subscr_subscribe_noaddress'] = 'Добавянето ви към списъка с абонати не е възможно поради липсата на свързан адрес (на ел. поща) с профила ви.';
@@ -267,7 +257,6 @@ $lang['subscr_unsubscribe_success'] = '%s е премахнат от списъ
$lang['subscr_unsubscribe_error'] = 'Грешка при премахването на %s от списъка с абониралите се за %s';
$lang['subscr_already_subscribed'] = '%s е вече абониран за %s';
$lang['subscr_not_subscribed'] = '%s не е абониран за %s';
-// Manage page for subscriptions
$lang['subscr_m_not_subscribed'] = 'Не сте абониран за текущата страницата или именно пространство.';
$lang['subscr_m_new_header'] = 'Добави абонамент';
$lang['subscr_m_current_header'] = 'Текущи абонаменти';
@@ -277,12 +266,8 @@ $lang['subscr_m_receive'] = 'Получаване';
$lang['subscr_style_every'] = 'на ел. писмо при всяка промяна';
$lang['subscr_style_digest'] = 'на ел. писмо с обобщение на промените във всяка страница (всеки %.2f дни)';
$lang['subscr_style_list'] = 'на списък с променените страници от последното ел. писмо (всеки %.2f дни)';
-
-/* auth.class language support */
$lang['authtempfail'] = 'Удостоверяването на потребители не е възможно за момента. Ако продължи дълго, моля уведомете администратора на Wiki страницата.';
$lang['authpwdexpire'] = 'Срока на паролата ви ще изтече след %d дни. Препорачително е да я смените по-скоро.';
-
-/* installer strings */
$lang['i_chooselang'] = 'Изберете вашия изик';
$lang['i_installer'] = 'Инсталатор на DokuWiki';
$lang['i_wikiname'] = 'Име на Wiki-то';
@@ -299,19 +284,18 @@ $lang['i_writeerr'] = '<code>%s</code> не можа да бъде с
$lang['i_badhash'] = 'Файлът dokuwiki.php не може да бъде разпознат или е променен (hash=<code>%s</code>)';
$lang['i_badval'] = '<code>%s</code> - непозволена или празна стойност';
$lang['i_success'] = 'Настройването приключи успешно. Вече можете да изтриете файла install.php. Продължете към <a href="doku.php?id=wiki:welcome">Вашето ново DokuWiki</a>.';
-
$lang['i_failure'] = 'Възникнаха грешки при записването на файловете с настройки. Вероятно ще се наложи да ги поправите ръчно,
за да можете да ползвате <a href="doku.php?id=wiki:welcome">Вашето ново DokuWiki</a>.';
$lang['i_policy'] = 'Първоначална политика за достъп';
$lang['i_pol0'] = 'Отворено Wiki (всеки може да чете, пише и качва)';
$lang['i_pol1'] = 'Публично Wiki (всеки може да чете, само регистрирани пишат и качват)';
$lang['i_pol2'] = 'Затворено Wiki (само регистрирани четат, пишат и качват)';
+$lang['i_allowreg'] = 'Разрешете на потребителите за се регистрират сами';
$lang['i_retry'] = 'Повторен опит';
$lang['i_license'] = 'Моля, изберете лиценз под който желаете да публикувате съдържанието:';
$lang['i_license_none'] = 'Без показване на информация относно лиценза';
$lang['i_pop_field'] = 'Моля, помогнете за усъвършенстването на DokuWiki:';
$lang['i_pop_label'] = 'Изпращане на анонимна информация до разработчиците на DokuWiki, веднъж седмично';
-
$lang['recent_global'] = 'В момента преглеждате промените в именно пространство <b>%s</b>. Може да прегледате и <a href="%s">промените в цялото Wiki</a>.';
$lang['years'] = 'преди %d години';
$lang['months'] = 'преди %d месеца';
@@ -320,9 +304,7 @@ $lang['days'] = 'преди %d дни';
$lang['hours'] = 'преди %d часа';
$lang['minutes'] = 'преди %d минути';
$lang['seconds'] = 'преди %d секунди';
-
$lang['wordblock'] = 'Направените от Вас промени не са съхранени, защото съдържат забранен текст (SPAM).';
-
$lang['media_uploadtab'] = 'Качване';
$lang['media_searchtab'] = 'Търсене';
$lang['media_file'] = 'Файл';
@@ -346,5 +328,5 @@ $lang['media_perm_read'] = 'За съжаление нямате дост
$lang['media_perm_upload'] = 'За съжаление нямате достатъчно права, за да можете да качите файла.';
$lang['media_update'] = 'Качване на нова версия';
$lang['media_restore'] = 'Възстановяване на тази версия';
-
-//Setup VIM: ex: et ts=2 :
+$lang['searchresult'] = 'Резултати от търсенето';
+$lang['plainhtml'] = 'Обикновен HTML';
diff --git a/inc/lang/bn/admin.txt b/inc/lang/bn/admin.txt
new file mode 100644
index 000000000..ede23c764
--- /dev/null
+++ b/inc/lang/bn/admin.txt
@@ -0,0 +1,3 @@
+====== প্রশাসন ======
+
+আপনি DokuWiki পাওয়া প্রশাসনিক কাজগুলো একটি তালিকা পেতে পারেন নীচে. \ No newline at end of file
diff --git a/inc/lang/bn/adminplugins.txt b/inc/lang/bn/adminplugins.txt
new file mode 100644
index 000000000..c491ff9b4
--- /dev/null
+++ b/inc/lang/bn/adminplugins.txt
@@ -0,0 +1 @@
+===== অতিরিক্ত প্লাগইন ===== \ No newline at end of file
diff --git a/inc/lang/bn/backlinks.txt b/inc/lang/bn/backlinks.txt
new file mode 100644
index 000000000..61a7cac3f
--- /dev/null
+++ b/inc/lang/bn/backlinks.txt
@@ -0,0 +1,3 @@
+====== ব্যাকলিঙ্কগুলি ======
+
+এই বর্তমান পৃষ্ঠায় ফিরে সংযোগ আছে বলে মনে হচ্ছে যে পেজের একটি তালিকা. \ No newline at end of file
diff --git a/inc/lang/bn/conflict.txt b/inc/lang/bn/conflict.txt
new file mode 100644
index 000000000..b18ad9531
--- /dev/null
+++ b/inc/lang/bn/conflict.txt
@@ -0,0 +1,5 @@
+====== একটি নতুন সংস্করণ উপস্থিত ======
+
+আপনি সম্পাদিত ডকুমেন্টের একটি নতুন সংস্করণ বিদ্যমান. আপনি এটি সম্পাদনা যখন অন্য ব্যবহারকারীর নথি পরিবর্তিত যখন এটি হয়.
+
+পুঙ্খানুপুঙ্খভাবে নিচে দেখানো পার্থক্য পরীক্ষা, তারপর রাখা যা সংস্করণে ঠিক. আপনি "সংরক্ষণ" চয়ন, আপনার সংস্করণ সংরক্ষিত হবে অথবা বর্তমান সংস্করণ রাখা ''বাতিল'' হিট করুন. \ No newline at end of file
diff --git a/inc/lang/bn/denied.txt b/inc/lang/bn/denied.txt
new file mode 100644
index 000000000..711275bad
--- /dev/null
+++ b/inc/lang/bn/denied.txt
@@ -0,0 +1,3 @@
+====== অনুমতি অস্বীকার =====
+
+দুঃখিত, আপনি কি এগিয়ে যেতে যথেষ্ট অধিকার নেই. সম্ভবত আপনি লগইন ভুলে গেছেন? \ No newline at end of file
diff --git a/inc/lang/bn/diff.txt b/inc/lang/bn/diff.txt
new file mode 100644
index 000000000..5952e28da
--- /dev/null
+++ b/inc/lang/bn/diff.txt
@@ -0,0 +1,3 @@
+====== পার্থক্য ======
+
+এর মানে আপনি পৃষ্ঠার দুটি সংস্করণের মধ্যে পার্থক্য দেখায়. \ No newline at end of file
diff --git a/inc/lang/bn/draft.txt b/inc/lang/bn/draft.txt
new file mode 100644
index 000000000..0b614f485
--- /dev/null
+++ b/inc/lang/bn/draft.txt
@@ -0,0 +1,5 @@
+====== খসড়া ফাইল ====== পাওয়া
+
+এই পৃষ্ঠাতে আপনার সর্বশেষ সম্পাদনা সময় সঠিকভাবে সম্পন্ন করা হয় নি. DokuWiki স্বয়ংক্রিয়ভাবে আপনি এখন আপনার সম্পাদনা চালিয়ে যেতে ব্যবহার করতে পারেন যা আপনার কাজ করার সময় একটি খসড়া সংরক্ষিত. আপনি আপনার শেষ সময় থেকে সংরক্ষিত ছিল যে তথ্য দেখতে পারেন নিচে.
+
+আপনি / /ফিরাইয়া আনা / / আপনার হারিয়ে সম্পাদনা সময়, / / মুছে দিন / / স্বতঃসংরক্ষিত খসড়া অথবা / / বাতিল / / সম্পাদনা প্রক্রিয়া পুনরুদ্ধার করতে চান তা স্থির করুন. \ No newline at end of file
diff --git a/inc/lang/bn/edit.txt b/inc/lang/bn/edit.txt
new file mode 100644
index 000000000..b294b6461
--- /dev/null
+++ b/inc/lang/bn/edit.txt
@@ -0,0 +1 @@
+পাতা সম্পাদনা করুন এবং ''সংরক্ষণ'' আঘাত. দেখুন [[উইকি: সিনট্যাক্স]] উইকি সিনট্যাক্স জন্য. আপনি এটি **উন্নত** করতে পারেন শুধুমাত্র যদি পাতাটি সম্পাদনা করুন. আপনি কিছু কিছু বিষয় পরীক্ষা আপনার প্রথম পদক্ষেপ করা শিখতে চান [[খেলার মাঠ: খেলার মাঠ | খেলার মাঠ]]. \ No newline at end of file
diff --git a/inc/lang/bn/editrev.txt b/inc/lang/bn/editrev.txt
new file mode 100644
index 000000000..1ea72367e
--- /dev/null
+++ b/inc/lang/bn/editrev.txt
@@ -0,0 +1,2 @@
+** আপনি নথির একটি পুরোনো সংস্করণ লোড করেছেন! ** যদি আপনি এটি সংরক্ষণ করেন, আপনি এই তথ্য দিয়ে একটি নতুন সংস্করণ তৈরি করবে.
+---- \ No newline at end of file
diff --git a/inc/lang/bn/index.txt b/inc/lang/bn/index.txt
new file mode 100644
index 000000000..9f5ad751a
--- /dev/null
+++ b/inc/lang/bn/index.txt
@@ -0,0 +1,3 @@
+====== সাইটম্যাপ ======
+
+এই দ্বারা আদেশ সমস্ত উপলব্ধ পৃষ্ঠাগুলি উপর একটি সাইট ম্যাপ হল [[Doku> নামব্যবধান | নামব্যবধান]]. \ No newline at end of file
diff --git a/inc/lang/bn/lang.php b/inc/lang/bn/lang.php
new file mode 100644
index 000000000..5d9ee59a0
--- /dev/null
+++ b/inc/lang/bn/lang.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Foysol <ragebot1125@gmail.com>
+ * @author ninetailz <ninetailz1125@gmail.com>
+ */
+$lang['encoding'] = 'utf-8';
+$lang['direction'] = 'itr';
+$lang['doublequoteopening'] = '"';
+$lang['doublequoteclosing'] = '"';
+$lang['singlequoteopening'] = '\'';
+$lang['singlequoteclosing'] = '\'';
+$lang['apostrophe'] = '\'';
+$lang['btn_edit'] = 'এই পৃষ্ঠা সম্পাদনা করুন';
+$lang['btn_source'] = 'দেখান পাতা উৎস';
+$lang['btn_show'] = 'দেখান পৃষ্ঠা';
+$lang['btn_create'] = 'এই পৃষ্ঠা তৈরি করুন';
+$lang['btn_search'] = 'অনুসন্ধান';
+$lang['btn_save'] = 'Save';
+$lang['btn_preview'] = 'পূর্বরূপ';
+$lang['btn_top'] = 'উপরে ফিরে যান ';
+$lang['btn_newer'] = '<< আরো সাম্প্রতিক';
+$lang['btn_older'] = 'কম সাম্প্রতিক >>';
+$lang['btn_revs'] = 'প্রাচীন সংশোধন';
+$lang['btn_recent'] = 'সাধিত পরিবর্তনসমূহ';
+$lang['btn_upload'] = 'আপলোড করুন';
+$lang['btn_cancel'] = 'বাতিল করা';
+$lang['btn_index'] = 'সাইট ম্যাপ';
+$lang['btn_secedit'] = 'সম্পাদন করা';
+$lang['btn_login'] = 'লগইন';
+$lang['btn_logout'] = 'লগ আউট';
+$lang['btn_admin'] = 'অ্যাডমিন';
+$lang['btn_update'] = 'আধুনিক করা';
+$lang['btn_delete'] = 'মুছে ফেলা';
+$lang['btn_back'] = 'পিছনে';
+$lang['btn_backlink'] = 'ব্যাকলিঙ্কগুলি';
+$lang['btn_backtomedia'] = 'পিছনে Mediafile নির্বাচনে যান';
+$lang['btn_subscribe'] = 'সাবস্ক্রিপশন পরিচালনা করুন';
+$lang['btn_profile'] = 'প্রোফাইল আপডেট করুন';
+$lang['btn_reset'] = 'রিসেট করুন';
+$lang['btn_resendpwd'] = 'সেট করুন নতুন পাসওয়ার্ড';
+$lang['btn_draft'] = 'সম্পাদনা খসড়া';
+$lang['btn_recover'] = 'খসড়া উদ্ধার';
+$lang['btn_draftdel'] = 'খসড়া মুছে দিন';
+$lang['btn_revert'] = 'পুনরূদ্ধার করা';
+$lang['btn_register'] = 'খাতা';
+$lang['btn_apply'] = 'প্রয়োগ করা';
+$lang['btn_media'] = 'মিডিয়া ম্যানেজার';
+$lang['btn_deleteuser'] = 'আমার অ্যাকাউন্ট অপসারণ করুন';
+$lang['loggedinas'] = 'লগ ইন';
+$lang['user'] = 'ইউজারনেম';
+$lang['pass'] = 'পাসওয়ার্ড';
+$lang['newpass'] = 'নতুন পাসওয়ার্ড';
+$lang['oldpass'] = 'বর্তমান পাসওয়ার্ড নিশ্চিত করুন';
+$lang['passchk'] = 'আরো একবার';
+$lang['remember'] = 'আমাকে মনে রেখো';
+$lang['fullname'] = 'আমাকে মনে রেখো';
+$lang['email'] = 'ই মেইল';
+$lang['profile'] = 'ব্যবহারকারী প্রোফাইল';
+$lang['badlogin'] = 'দুঃখিত, ব্যবহারকারীর নাম বা পাসওয়ার্ড ভুল ছিল.';
+$lang['badpassconfirm'] = 'দুঃখিত, পাসওয়ার্ড ভুল ছিল';
+$lang['minoredit'] = 'ক্ষুদ্র পরিবর্তনসমূহ';
+$lang['draftdate'] = 'খসড়া উপর স্বতঃসংরক্ষণ';
+$lang['nosecedit'] = 'পাতা ইতিমধ্যে পরিবর্তিত হয়েছিল, অধ্যায় তথ্যের পরিবর্তে পুরো পাতা লোড তারিখ সীমার বাইরে ছিল.
+';
+$lang['regmissing'] = 'দুঃখিত, আপনি সমস্ত ক্ষেত্রগুলি পূরণ করা আবশ্যক.';
+$lang['reguexists'] = 'দুঃখিত, এই লগইন সঙ্গে একটি ব্যবহারকারী ইতিমধ্যেই বিদ্যমান.';
+$lang['regsuccess'] = 'ব্যবহারকারী তৈরি করা হয়েছে এবং পাসওয়ার্ড ইমেইল করে পাঠানো হয়েছিল.';
+$lang['regsuccess2'] = 'ব্যবহারকারী তৈরি করা হয়েছে.';
+$lang['regmailfail'] = 'একটি ত্রুটি পাসওয়ার্ড মেইল পাঠানোর নেভিগেশন ছিল মনে হচ্ছে. অ্যাডমিন যোগাযোগ করুন!';
+$lang['regbadmail'] = 'প্রদত্ত ইমেইল ঠিকানা সঠিক মনে হচ্ছে - আপনি এই একটি ত্রুটি মনে হলে, অ্যাডমিন যোগাযোগ';
+$lang['regbadpass'] = 'দুটি প্রদত্ত পাসওয়ার্ড অভিন্ন নয়, আবার চেষ্টা করুন.';
+$lang['regpwmail'] = 'আপনার DokuWiki পাসওয়ার্ড';
+$lang['reghere'] = 'যদিও তোমার কোনো একাউন্ট নেই? শুধু একটি পেতে';
+$lang['profna'] = 'এই উইকি প্রোফাইল পরিবর্তন সমর্থন করে না';
+$lang['profnochange'] = 'এমন কোন পরিবর্তন, না কিছুই.';
+$lang['profnoempty'] = 'একটি খালি নাম অথবা ইমেইল ঠিকানা অনুমোদিত নয়.';
+$lang['profchanged'] = 'ইউজার প্রোফাইল সফলভাবে আপডেট.';
+$lang['profnodelete'] = 'এই উইকি ব্যবহারকারী মুছে ফেলার সমর্থন করে না';
+$lang['profdeleteuser'] = 'একাউন্ট মুছে দিন';
+$lang['profdeleted'] = 'আপনার অ্যাকাউন্টটি এই উইকি থেকে মুছে ফেলা হয়েছে';
+$lang['profconfdelete'] = 'আমি এই উইকি থেকে আমার অ্যাকাউন্ট অপসারণ করতে ইচ্ছুক. <br/> এই ক্রিয়াটি পূর্বাবস্থায় ফেরানো যায় না.';
+$lang['profconfdeletemissing'] = 'নিশ্চিতকরণ চেক বক্স ticked না';
+$lang['pwdforget'] = 'আপনার পাসওয়ার্ড ভুলে গেছেন? একটি নতুন পান';
+$lang['resendna'] = 'এই উইকি পাসওয়ার্ড পুনরায় প্রেরণ সমর্থন করে না.';
+$lang['resendpwd'] = 'জন্য সেট করুন নতুন পাসওয়ার্ড';
+$lang['resendpwdmissing'] = 'দুঃখিত, আপনি সমস্ত ক্ষেত্রগুলি পূরণ করা আবশ্যক.';
+$lang['resendpwdnouser'] = 'দুঃখিত, আমরা আমাদের ডাটাবেসের মধ্যে ব্যবহারকারীর খুঁজে পাচ্ছি না.';
+$lang['resendpwdbadauth'] = 'দুঃখিত, এই auth কোড বৈধ নয়. আপনি সম্পূর্ণ কনফার্মেশন লিঙ্ক ব্যবহার নিশ্চিত করুন.';
+$lang['resendpwdconfirm'] = 'একটি নিশ্চায়ন লিঙ্ক ইমেলের মাধ্যমে পাঠানো হয়েছে.';
+$lang['resendpwdsuccess'] = 'আপনার নতুন পাসওয়ার্ড ইমেইলের মাধ্যমে পাঠানো হয়েছে.';
+$lang['license'] = 'অন্যথায় নোট যেখানে ছাড়া, এই উইকি নেভিগেশন কন্টেন্ট নিম্নলিখিত লাইসেন্সের আওতায় লাইসেন্সকৃত:';
+$lang['licenseok'] = 'দ্রষ্টব্য: আপনি নিম্নলিখিত লাইসেন্সের অধীনে আপনার বিষয়বস্তু লাইসেন্স সম্মত হন এই পৃষ্ঠার সম্পাদনার দ্বারা:';
+$lang['searchmedia'] = 'অনুসন্ধান ফাইলের নাম:';
+$lang['searchmedia_in'] = 'অনুসন্ধান %s -এ';
+$lang['txt_upload'] = 'আপলোড করার জন্য নির্বাচন করুন ফাইল';
+$lang['txt_filename'] = 'হিসাবে আপলোড করুন (ঐচ্ছিক)';
+$lang['txt_overwrt'] = 'বিদ্যমান ফাইল মুছে যাবে';
+$lang['maxuploadsize'] = 'সর্বোচ্চ আপলোড করুন. %s-ফাইলের প্রতি.';
+$lang['lockedby'] = 'বর্তমানে দ্বারা লক';
+$lang['lockexpire'] = 'তালা এ মেয়াদ শেষ';
+$lang['js']['willexpire'] = 'এই পৃষ্ঠার সম্পাদনার জন্য আপনার লক এক মিনিটের মধ্যে মেয়াদ শেষ সম্পর্কে. \ দ্বন্দ্ব লক টাইমার রিসেট প্রিভিউ বাটন ব্যবহার এড়াতে.';
+$lang['js']['notsavedyet'] = 'অসংরক্ষিত পরিবর্তন হারিয়ে যাবে.';
+$lang['js']['searchmedia'] = 'ফাইলের জন্য অনুসন্ধান';
+$lang['js']['keepopen'] = 'নির্বাচনের উপর উইন্ডো খোলা রাখুন';
+$lang['js']['hidedetails'] = 'বিশদ আড়াল করুন';
+$lang['js']['mediatitle'] = 'লিংক সেটিংস';
+$lang['js']['mediadisplay'] = 'লিংক টাইপ';
+$lang['js']['mediaalign'] = 'শ্রেণীবিন্যাস';
+$lang['js']['mediasize'] = 'চিত্র আকার';
+$lang['js']['mediatarget'] = 'লিংক টার্গেট';
+$lang['js']['mediaclose'] = 'বন্ধ করা';
+$lang['js']['mediainsert'] = 'ঢোকান';
+$lang['js']['mediadisplayimg'] = 'ছবিটি দেখান';
+$lang['js']['mediadisplaylnk'] = 'শুধুমাত্র লিঙ্ক দেখান';
+$lang['js']['mediasmall'] = 'ক্ষুদ্র সংস্করণ';
+$lang['js']['mediamedium'] = 'মাধ্যম সংস্করণ';
diff --git a/inc/lang/da/lang.php b/inc/lang/da/lang.php
index 0da7e4761..eb50bb240 100644
--- a/inc/lang/da/lang.php
+++ b/inc/lang/da/lang.php
@@ -16,6 +16,7 @@
* @author Mikael Lyngvig <mikael@lyngvig.org>
* @author Soren Birk <soer9648@hotmail.com>
* @author Jens Hyllegaard <jens.hyllegaard@gmail.com>
+ * @author soer9648 <soer9648@eucl.dk>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -91,6 +92,7 @@ $lang['profchanged'] = 'Brugerprofil opdateret korrekt.';
$lang['profnodelete'] = 'Denne wiki supporterer ikke sletning af brugere';
$lang['profdeleteuser'] = 'Slet Konto';
$lang['profdeleted'] = 'Din brugerkonto er blevet slettet fra denne wiki';
+$lang['profconfdelete'] = 'Jeg ønsker at slette min konto fra denne wiki. <br/> Denne handling kan ikke fortrydes.';
$lang['pwdforget'] = 'Har du glemt dit adgangskode? Få et nyt';
$lang['resendna'] = 'Denne wiki understøtter ikke udsendelse af nyt adgangskode.';
$lang['resendpwd'] = 'Vælg ny adgangskode for';
diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php
index 02ff85fad..be3f14a18 100644
--- a/inc/lang/de-informal/lang.php
+++ b/inc/lang/de-informal/lang.php
@@ -2,7 +2,7 @@
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- *
+ *
* @author Andreas Gohr <andi@splitbrain.org>
* @author Christof <gagi@fin.de>
* @author Anika Henke <anika@selfthinker.org>
@@ -21,6 +21,7 @@
* @author Pierre Corell <info@joomla-praxis.de>
* @author Frank Loizzi <contact@software.bacal.de>
* @author Volker Bödker <volker@boedker.de>
+ * @author Janosch <janosch@moinzen.de>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -302,6 +303,7 @@ $lang['i_policy'] = 'Anfangseinstellungen der Zugangskontrolle (ACL
$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_allowreg'] = 'Benutzer können sich selbst registrieren';
$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';
@@ -339,3 +341,5 @@ $lang['media_perm_read'] = 'Du besitzt nicht die notwendigen Berechtigunge
$lang['media_perm_upload'] = 'Du besitzt nicht die notwendigen Berechtigungen um Dateien hochzuladen.';
$lang['media_update'] = 'Neue Version hochladen';
$lang['media_restore'] = 'Diese Version wiederherstellen';
+$lang['currentns'] = 'Aktueller Namensraum';
+$lang['searchresult'] = 'Suchergebnis';
diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php
index 685e668c4..9df1035f7 100644
--- a/inc/lang/de/lang.php
+++ b/inc/lang/de/lang.php
@@ -2,7 +2,7 @@
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- *
+ *
* @author Andreas Gohr <andi@splitbrain.org>
* @author Christof <gagi@fin.de>
* @author Anika Henke <anika@selfthinker.org>
@@ -22,6 +22,7 @@
* @author Paul Lachewsky <kaeptn.haddock@gmail.com>
* @author Pierre Corell <info@joomla-praxis.de>
* @author Mateng Schimmerlos <mateng@firemail.de>
+ * @author Benedikt Fey <spam@lifeisgoooood.de>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -303,6 +304,7 @@ $lang['i_policy'] = 'Anfangseinstellungen der Zugangskontrolle (ACL
$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_allowreg'] = 'Benutzer dürfen sich registrieren';
$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';
@@ -340,3 +342,6 @@ $lang['media_perm_read'] = 'Sie besitzen nicht die notwendigen Berechtigun
$lang['media_perm_upload'] = 'Sie besitzen nicht die notwendigen Berechtigungen um Dateien hochzuladen.';
$lang['media_update'] = 'Neue Version hochladen';
$lang['media_restore'] = 'Diese Version wiederherstellen';
+$lang['currentns'] = 'Aktueller Namensraum';
+$lang['searchresult'] = 'Suchergebnisse';
+$lang['plainhtml'] = 'HTML Klartext';
diff --git a/inc/lang/el/lang.php b/inc/lang/el/lang.php
index 61b2fda9d..8007f2b23 100644
--- a/inc/lang/el/lang.php
+++ b/inc/lang/el/lang.php
@@ -2,7 +2,7 @@
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- *
+ *
* @author Thanos Massias <tm@thriasio.gr>
* @author Αθανάσιος Νταής <homunculus@wana.gr>
* @author Konstantinos Koryllos <koryllos@gmail.com>
@@ -10,6 +10,7 @@
* @author Petros Vidalis <pvidalis@gmail.com>
* @author Vasileios Karavasilis vasileioskaravasilis@gmail.com
* @author Constantinos Xanthopoulos <conx@xanthopoulos.info>
+ * @author chris taklis <ctaklis@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -85,6 +86,7 @@ $lang['profchanged'] = 'Το προφίλ χρήστη τροποπο
$lang['profnodelete'] = 'Το wiki δεν υποστηρίζει την διαγραφή χρηστών';
$lang['profdeleteuser'] = 'Διαγραφή λογαριασμού';
$lang['profdeleted'] = 'Ο λογαριασμός διαγράφηκε από αυτό το wiki';
+$lang['profconfdelete'] = 'Επιθυμώ να διαγράψω τον λογαριασμό μου από αυτό το wiki. <br/> Αυτή η επιλογή δεν μπορεί να αναιρεθεί.';
$lang['pwdforget'] = 'Ξεχάσατε το κωδικό σας; Αποκτήστε νέο.';
$lang['resendna'] = 'Αυτό το wiki δεν υποστηρίζει την εκ\' νέου αποστολή κωδικών.';
$lang['resendpwd'] = 'Εισαγωγή νέου ωδικού για';
@@ -291,6 +293,7 @@ $lang['i_policy'] = 'Αρχική πολιτική Λίστας Δ
$lang['i_pol0'] = 'Ανοιχτό Wiki (όλοι μπορούν να διαβάσουν ή να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)';
$lang['i_pol1'] = 'Δημόσιο Wiki (όλοι μπορούν να διαβάσουν σελίδες αλλά μόνο οι εγγεγραμμένοι χρήστες μπορούν να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)';
$lang['i_pol2'] = 'Κλειστό Wiki (μόνο οι εγγεγραμμένοι χρήστες μπορούν να διαβάσουν ή να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)';
+$lang['i_allowreg'] = 'Οι χρήστες επιτρέπεται να εγγραφούν μόνοι τους';
$lang['i_retry'] = 'Νέα προσπάθεια';
$lang['i_license'] = 'Παρακαλώ επιλέξτε την άδεια που θα χρησιμοποιήσετε για την διάθεση του περιεχομένου σας:';
$lang['recent_global'] = 'Βλέπετε τις αλλαγές εντός του φακέλου <b>%s</b>. Μπορείτε επίσης να <a href="%s">δείτε τις πρόσφατες αλλαγές σε όλο το wiki</a>.';
@@ -319,8 +322,10 @@ $lang['media_search'] = 'Αναζήτηση στο <strong>%s</strong>
$lang['media_view'] = '%s';
$lang['media_viewold'] = '%s στα %s';
$lang['media_edit'] = 'Επεξεργασία %s';
+$lang['media_history'] = 'Ιστορικό των %s';
$lang['media_meta_edited'] = 'τα μεταδεδομένα επεξεργάστηκαν';
$lang['media_perm_read'] = 'Συγνώμη, δεν έχετε επαρκή διακαιώματα για να διαβάσετε αυτά τα αρχεία.';
$lang['media_perm_upload'] = 'Συγνώμη, δεν έχετε επαρκή διακαιώματα για να φορτώσετε αυτά τα αρχεία.';
$lang['media_update'] = 'Φόρτωση νέας έκδοσης';
$lang['media_restore'] = 'Επαναφορά αυτή της έκδοσης';
+$lang['searchresult'] = 'Αποτέλεσμα έρευνας';
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index ab84c67f3..17a75803f 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -315,6 +315,7 @@ $lang['i_policy'] = 'Initial ACL policy';
$lang['i_pol0'] = 'Open Wiki (read, write, upload for everyone)';
$lang['i_pol1'] = 'Public Wiki (read for everyone, write and upload for registered users)';
$lang['i_pol2'] = 'Closed Wiki (read, write, upload for registered users only)';
+$lang['i_allowreg'] = 'Allow users to register themselves';
$lang['i_retry'] = 'Retry';
$lang['i_license'] = 'Please choose the license you want to put your content under:';
$lang['i_license_none'] = 'Do not show any license information';
diff --git a/inc/lang/eo/lang.php b/inc/lang/eo/lang.php
index 4ed03244e..a543b2571 100644
--- a/inc/lang/eo/lang.php
+++ b/inc/lang/eo/lang.php
@@ -330,3 +330,7 @@ $lang['media_perm_read'] = 'Bedaûrinde viaj rajtoj ne sufiĉas por legi d
$lang['media_perm_upload'] = 'Bedaûrinde viaj rajtoj ne sufiĉas por alŝuti dosierojn.';
$lang['media_update'] = 'Alŝuti novan version';
$lang['media_restore'] = 'Restarigi ĉi tiun version';
+$lang['currentns'] = 'Aktuala nomspaco';
+$lang['searchresult'] = 'Serĉrezulto';
+$lang['plainhtml'] = 'Plena HTML';
+$lang['wikimarkup'] = 'Vikiteksto';
diff --git a/inc/lang/es/lang.php b/inc/lang/es/lang.php
index 0764621b0..216093f6c 100644
--- a/inc/lang/es/lang.php
+++ b/inc/lang/es/lang.php
@@ -30,6 +30,7 @@
* @author Mercè López mercelz@gmail.com
* @author r0sk <r0sk10@gmail.com>
* @author monica <may.dorado@gmail.com>
+ * @author Antonio Bueno <atnbueno@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -313,6 +314,7 @@ $lang['i_policy'] = 'Política de ACL inicial';
$lang['i_pol0'] = 'Wiki abierto (leer, escribir y subir archivos para todos)';
$lang['i_pol1'] = 'Wiki público (leer para todos, escribir y subir archivos para usuarios registrados únicamente)';
$lang['i_pol2'] = 'Wiki cerrado (leer, escribir y subir archivos para usuarios registrados únicamente)';
+$lang['i_allowreg'] = 'Permitir que los usuarios se registren a sí mismos';
$lang['i_retry'] = 'Reintentar';
$lang['i_license'] = 'Por favor escoja una licencia bajo la que publicar su contenido:';
$lang['i_license_none'] = 'No mostrar ninguna información sobre licencias';
@@ -350,3 +352,7 @@ $lang['media_perm_read'] = 'Disculpa, no tienes los permisos necesarios pa
$lang['media_perm_upload'] = 'Disculpa, no tienes los permisos necesarios para cargar ficheros.';
$lang['media_update'] = 'Actualizar nueva versión';
$lang['media_restore'] = 'Restaurar esta versión';
+$lang['currentns'] = 'Espacio de nombres actual';
+$lang['searchresult'] = 'Resultado de la búsqueda';
+$lang['plainhtml'] = 'HTML sencillo';
+$lang['wikimarkup'] = 'Etiquetado Wiki';
diff --git a/inc/lang/fa/lang.php b/inc/lang/fa/lang.php
index 6cb5164d8..dbad62890 100644
--- a/inc/lang/fa/lang.php
+++ b/inc/lang/fa/lang.php
@@ -10,6 +10,7 @@
* @author Milad DZand <M.DastanZand@gmail.com>
* @author AmirH Hassaneini <mytechmix@gmail.com>
* @author mehrdad <mehrdad.jafari.bojd@gmail.com>
+ * @author reza_khn <reza_khn@yahoo.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'rtl';
@@ -84,6 +85,7 @@ $lang['profnoempty'] = 'نام و آدرس ایمیل باید پر ش
$lang['profchanged'] = 'پروفایل کاربر با موفقیت به روز شد';
$lang['profnodelete'] = 'ویکی توانایی پشتیبانی از حذف کاربران را ندارد';
$lang['profdeleteuser'] = 'حذف حساب کاربری';
+$lang['profdeleted'] = 'حساب کاربری شما حذف گردیده است.';
$lang['pwdforget'] = 'گذرواژه‌ی خود را فراموش کرده‌اید؟ جدید دریافت کنید';
$lang['resendna'] = 'این ویکی ارسال مجدد گذرواژه را پشتیبانی نمی‌کند';
$lang['resendpwd'] = 'تعیین کلمه عبور جدید برای ';
diff --git a/inc/lang/fi/lang.php b/inc/lang/fi/lang.php
index 4a0a88ac8..feefc3da8 100644
--- a/inc/lang/fi/lang.php
+++ b/inc/lang/fi/lang.php
@@ -1,13 +1,14 @@
<?php
+
/**
- * Finnish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Petteri <petteri@gmail.com>
* @author Matti Pöllä <mpo@iki.fi>
* @author Otto Vainio <otto@valjakko.net>
* @author Teemu Mattila <ghcsystems@gmail.com>
* @author Sami Olmari <sami@olmari.fi>
+ * @author Rami Lehti <rammer@ipi.fi>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -51,6 +52,7 @@ $lang['btn_revert'] = 'palauta';
$lang['btn_register'] = 'Rekisteröidy';
$lang['btn_apply'] = 'Toteuta';
$lang['btn_media'] = 'Media manager';
+$lang['btn_deleteuser'] = 'Poista tilini';
$lang['loggedinas'] = 'Kirjautunut nimellä';
$lang['user'] = 'Käyttäjänimi';
$lang['pass'] = 'Salasana';
@@ -62,6 +64,7 @@ $lang['fullname'] = 'Koko nimi';
$lang['email'] = 'Sähköposti';
$lang['profile'] = 'Käyttäjän profiili';
$lang['badlogin'] = 'Käyttäjänimi tai salasana oli väärä.';
+$lang['badpassconfirm'] = 'Valitan. Salasana oli väärin';
$lang['minoredit'] = 'Pieni muutos';
$lang['draftdate'] = 'Luonnos tallennettu automaattisesti';
$lang['nosecedit'] = 'Sivu on muuttunut välillä ja kappaleen tiedot olivat vanhentuneet. Koko sivu ladattu.';
@@ -78,6 +81,11 @@ $lang['profna'] = 'Tässä wikissä profiilien muokkaaminen ei ol
$lang['profnochange'] = 'Ei muutoksia.';
$lang['profnoempty'] = 'Tyhjä nimi tai sähköpostiosoite ei ole sallittu.';
$lang['profchanged'] = 'Käyttäjän profiilin päivitys onnistui.';
+$lang['profnodelete'] = 'Tässä wikissä ei voi poistaa käyttäjiä';
+$lang['profdeleteuser'] = 'Poista tili';
+$lang['profdeleted'] = 'Käyttäjätilisi on postettu tästä wikistä';
+$lang['profconfdelete'] = 'Haluan poistaa käyttäjätilini tästä wikistä. <br/> Tätä toimintoa ei voi myöhemmin peruuttaa.';
+$lang['profconfdeletemissing'] = 'Vahvistus rastia ei valittu';
$lang['pwdforget'] = 'Unohtuiko salasana? Hanki uusi';
$lang['resendna'] = 'Tämä wiki ei tue salasanan uudelleenlähettämistä.';
$lang['resendpwd'] = 'Aseta uusisalasana';
@@ -284,6 +292,7 @@ $lang['i_policy'] = 'Käyttöoikeuksien oletusmenettelytapa';
$lang['i_pol0'] = 'Avoin Wiki (luku, kirjoitus, tiedostojen lähetys on sallittu kaikille)';
$lang['i_pol1'] = 'Julkinen Wiki (luku kaikilla, kirjoitus ja tiedostojen lähetys rekisteröidyillä käyttäjillä)';
$lang['i_pol2'] = 'Suljettu Wiki (luku, kirjoitus ja tiedostojen lähetys vain rekisteröityneillä käyttäjillä)';
+$lang['i_allowreg'] = 'Salli käyttäjien rekisteröityminen';
$lang['i_retry'] = 'Yritä uudelleen';
$lang['i_license'] = 'Valitse lisenssi, jonka alle haluat sisältösi laittaa:';
$lang['i_license_none'] = 'Älä näytä mitään lisenssitietoja';
@@ -321,3 +330,7 @@ $lang['media_perm_read'] = 'Anteeksi. Sinulla ei ole riittävästi oikeuks
$lang['media_perm_upload'] = 'Anteeksi. Sinulla ei ole riittävästi oikeuksia lähettääksesi tiedostoja.';
$lang['media_update'] = 'Lähetä uusi versio';
$lang['media_restore'] = 'Palauta tämä versio';
+$lang['currentns'] = 'Nykyinen nimiavaruus';
+$lang['searchresult'] = 'Haun tulokset';
+$lang['plainhtml'] = 'pelkkä HTML';
+$lang['wikimarkup'] = 'Wiki markup';
diff --git a/inc/lang/fr/lang.php b/inc/lang/fr/lang.php
index 44bc0f859..49f617323 100644
--- a/inc/lang/fr/lang.php
+++ b/inc/lang/fr/lang.php
@@ -28,6 +28,7 @@
* @author Anael Mobilia <contrib@anael.eu>
* @author Bruno Veilleux <bruno.vey@gmail.com>
* @author Emmanuel <seedfloyd@gmail.com>
+ * @author Jérôme Brandt <jeromebrandt@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -309,6 +310,7 @@ $lang['i_policy'] = 'Politique de contrôle d\'accès initiale';
$lang['i_pol0'] = 'Wiki ouvert (lecture, écriture, envoi de fichiers pour tout le monde)';
$lang['i_pol1'] = 'Wiki public (lecture pour tout le monde, écriture et envoi de fichiers pour les utilisateurs enregistrés)';
$lang['i_pol2'] = 'Wiki fermé (lecture, écriture, envoi de fichiers pour les utilisateurs enregistrés uniquement)';
+$lang['i_allowreg'] = 'Permettre aux utilisateurs de s\'enregistrer eux-mêmes.';
$lang['i_retry'] = 'Réessayer';
$lang['i_license'] = 'Veuillez choisir la licence sous laquelle vous souhaitez placer votre contenu :';
$lang['i_license_none'] = 'Ne pas afficher d\'information de licence.';
@@ -346,3 +348,7 @@ $lang['media_perm_read'] = 'Désolé, vous n\'avez pas l\'autorisation de
$lang['media_perm_upload'] = 'Désolé, vous n\'avez pas l\'autorisation d\'envoyer des fichiers.';
$lang['media_update'] = 'Envoyer une nouvelle version';
$lang['media_restore'] = 'Restaurer cette version';
+$lang['currentns'] = 'Namespace actuel';
+$lang['searchresult'] = 'Résultat de la recherche';
+$lang['plainhtml'] = 'HTML brut';
+$lang['wikimarkup'] = 'Wiki balise';
diff --git a/inc/lang/he/lang.php b/inc/lang/he/lang.php
index 4ddc3a019..8efe0da17 100644
--- a/inc/lang/he/lang.php
+++ b/inc/lang/he/lang.php
@@ -10,6 +10,9 @@
* @author Yaron Yogev <yaronyogev@gmail.com>
* @author Yaron Shahrabani <sh.yaron@gmail.com>
* @author Roy Zahor <roy.zahor@gmail.com>
+ * @author alex <ralexay@gmail.com>
+ * @author matt carroll <matt.carroll@gmail.com>
+ * @author tomer <tomercarolldergicz@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'rtl';
@@ -51,7 +54,9 @@ $lang['btn_recover'] = 'שחזור טיוטה';
$lang['btn_draftdel'] = 'מחיקת טיוטה';
$lang['btn_revert'] = 'שחזור';
$lang['btn_register'] = 'הרשמה';
+$lang['btn_apply'] = 'ליישם';
$lang['btn_media'] = 'מנהל המדיה';
+$lang['btn_deleteuser'] = 'להסיר את החשבון שלי';
$lang['loggedinas'] = 'נכנסת בשם';
$lang['user'] = 'שם משתמש';
$lang['pass'] = 'ססמה';
@@ -80,6 +85,11 @@ $lang['profna'] = 'בוויקי הזה לא ניתן לשנות
$lang['profnochange'] = 'אין שינויים, הפרופיל לא עודכן';
$lang['profnoempty'] = 'השם וכתובת הדוא״ל לא יכולים להיות ריקים';
$lang['profchanged'] = 'הפרופיל עודכן בהצלחה';
+$lang['profnodelete'] = 'ויקי אינה תומכת במחיקת משתמשים';
+$lang['profdeleteuser'] = 'הסר חשבון';
+$lang['profdeleted'] = 'חשבון המשתמש שלך נמחק מויקי זה';
+$lang['profconfdelete'] = 'ברצוני להסיר את החשבון שלי מוויקי זה. <br/> לא ניתן לבטל פעולה זו.';
+$lang['profconfdeletemissing'] = 'תיבת אישור אינו מסומן';
$lang['pwdforget'] = 'שכחת את הססמה שלך? ניתן לקבל חדשה';
$lang['resendna'] = 'הוויקי הזה אינו תומך בחידוש ססמה';
$lang['resendpwd'] = 'הגדר סיסמא חדשה בעבור';
@@ -95,6 +105,7 @@ $lang['searchmedia_in'] = 'חיפוש תחת %s';
$lang['txt_upload'] = 'בחירת קובץ להעלות';
$lang['txt_filename'] = 'העלאה בשם (נתון לבחירה)';
$lang['txt_overwrt'] = 'שכתוב על קובץ קיים';
+$lang['maxuploadsize'] = 'העלה מקסימום. s% לכל קובץ.';
$lang['lockedby'] = 'נעול על ידי';
$lang['lockexpire'] = 'הנעילה פגה';
$lang['js']['willexpire'] = 'הנעילה תחלוף עוד זמן קצר. \nלמניעת התנגשויות יש להשתמש בכפתור הרענון מטה כדי לאפס את מד משך הנעילה.';
@@ -128,11 +139,17 @@ $lang['js']['nosmblinks'] = 'קישור לכונני שיתוף של Window
$lang['js']['linkwiz'] = 'אשף הקישורים';
$lang['js']['linkto'] = 'קישור אל:';
$lang['js']['del_confirm'] = 'באמת למחוק?';
+$lang['js']['restore_confirm'] = 'באמת לשחזר את הגירסא הזאת?';
$lang['js']['media_diff'] = 'הצגת הבדלים:';
$lang['js']['media_diff_both'] = 'זה לצד זה';
+$lang['js']['media_diff_opacity'] = 'ניקוי דרך';
+$lang['js']['media_diff_portions'] = 'לחבוט';
$lang['js']['media_select'] = 'בחר קבצים...';
$lang['js']['media_upload_btn'] = 'העלאה';
+$lang['js']['media_done_btn'] = 'בוצע';
$lang['js']['media_drop'] = 'גרור לכאן קבצים בכדי להעלותם';
+$lang['js']['media_cancel'] = 'הסר';
+$lang['js']['media_overwrt'] = 'שכתב קבצים קיימים';
$lang['rssfailed'] = 'אירע כשל בעת קבלת הזנה זו:';
$lang['nothingfound'] = 'לא נמצאו תוצאות.';
$lang['mediaselect'] = 'קובצי מדיה';
@@ -183,13 +200,20 @@ $lang['summary'] = 'תקציר העריכה';
$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">תוסף פלאש לדפדפן</a> נדרש כדי להציג תוכן זה.';
$lang['download'] = 'הורדת מקטע';
$lang['tools'] = 'כלים';
+$lang['user_tools'] = 'כלים של משתמש';
+$lang['site_tools'] = 'כלים של אתר';
+$lang['page_tools'] = 'כלים של דף';
+$lang['skip_to_content'] = 'עבור לתוכן';
+$lang['sidebar'] = 'הסרגל הצידי';
$lang['mail_newpage'] = 'דף נוסף:';
$lang['mail_changed'] = 'דף שונה:';
$lang['mail_subscribe_list'] = 'דפים שהשתנו במרחב השם:';
$lang['mail_new_user'] = 'משתמש חדש:';
$lang['mail_upload'] = 'קובץ הועלה:';
+$lang['changes_type'] = 'צפו בשינויים של';
$lang['pages_changes'] = 'דפים';
$lang['media_changes'] = 'קבצי מדיה';
+$lang['both_changes'] = 'קבצי מדיה ודפים ';
$lang['qb_bold'] = 'טקסט מודגש';
$lang['qb_italic'] = 'טקסט נטוי';
$lang['qb_underl'] = 'טקסט עם קו תחתון';
@@ -232,6 +256,7 @@ $lang['img_camera'] = 'מצלמה';
$lang['img_keywords'] = 'מילות מפתח';
$lang['img_width'] = 'רוחב';
$lang['img_height'] = 'גובה';
+$lang['img_manager'] = 'צפה במנהל מדיה';
$lang['subscr_subscribe_success'] = '%s נוסף לרשימת המינויים לדף %s';
$lang['subscr_subscribe_error'] = 'אירעה שגיאה בהוספת %s לרשימת המינויים לדף %s';
$lang['subscr_subscribe_noaddress'] = 'אין כתובת המשויכת עם הכניסה שלך, נא ניתן להוסיף אותך לרשימת המינויים';
@@ -249,6 +274,7 @@ $lang['subscr_style_every'] = 'דוא״ל עם כל שינוי';
$lang['subscr_style_digest'] = 'הודעת דוא״ל המציגה את כל השינויים בכל עמוד (בכל %.2f ימים)';
$lang['subscr_style_list'] = 'רשימת השינויים בדפים מאז הודעת הדוא״ל האחרונה (בכל %.2f ימים)';
$lang['authtempfail'] = 'אימות משתמשים אינו זמין כרגע. אם מצב זה נמשך נא ליידע את מנהל הוויקי.';
+$lang['authpwdexpire'] = 'הסיסמה שלך תפוג ב% d ימים, אתה צריך לשנות את זה בקרוב.';
$lang['i_chooselang'] = 'נא לבחור שפה';
$lang['i_installer'] = 'תכנית ההתקנה של DokuWiki';
$lang['i_wikiname'] = 'שם הוויקי';
@@ -259,6 +285,7 @@ $lang['i_modified'] = 'משיקולי אבטחה סקריפט זה י
עליך לחלץ שנית את הקבצים מהחבילה שהורדה או להיעזר בדף
<a href="http://dokuwiki.org/install">Dokuwiki installation instructions</a>';
$lang['i_funcna'] = 'פונקציית ה-PHP&rlm; <code>%s</code> אינה זמינה. יתכן כי מארח האתר חסם אותה מסיבה כלשהי?';
+$lang['i_phpver'] = 'גרסת PHP שלך <code>%s</code> נמוכה מ <code>%s</ code> הצורך. אתה צריך לשדרג PHP שלך להתקין.';
$lang['i_permfail'] = '<code>%s</code> אינה ניתנת לכתיבה על ידי DokuWiki. עליך לשנות הרשאות תיקייה זו!';
$lang['i_confexists'] = '<code>%s</code> כבר קיים';
$lang['i_writeerr'] = 'אין אפשרות ליצור את <code>%s</code>. נא לבדוק את הרשאות הקובץ/תיקייה וליצור את הקובץ ידנית.';
@@ -270,8 +297,12 @@ $lang['i_policy'] = 'מדיניות ACL התחלתית';
$lang['i_pol0'] = 'ויקי פתוח (קריאה, כתיבה והעלאה לכולם)';
$lang['i_pol1'] = ' ויקי ציבורי (קריאה לכולם, כתיבה והעלאה למשתמשים רשומים)';
$lang['i_pol2'] = 'ויקי סגור (קריאה, כתיבה והעלאה למשתמשים רשומים בלבד)';
+$lang['i_allowreg'] = 'אפשר למשתמשים לרשום את עצמם';
$lang['i_retry'] = 'ניסיון נוסף';
$lang['i_license'] = 'נא לבחור את הרישיון שיחול על התוכן שבוויקי שלך:';
+$lang['i_license_none'] = 'אל תציג כל מידע רישיון';
+$lang['i_pop_field'] = 'אנא, עזרו לנו לשפר את חווית ה DokuWiki:';
+$lang['i_pop_label'] = 'פעם בחודש, לשלוח את נתוני שימוש אנונימיים למפתחי DokuWiki';
$lang['recent_global'] = 'נכון לעכשיו מתנהל על ידיך מעקב אחר מרחב השם <b>%s</b>. כמו כן, באפשרותך <a href="%s">לצפות בשינויים האחרונים בוויקי כולו</a>.';
$lang['years'] = 'לפני %d שנים';
$lang['months'] = 'לפני %d חודשים';
@@ -281,12 +312,16 @@ $lang['hours'] = 'לפני %d שעות';
$lang['minutes'] = 'לפני %d דקות';
$lang['seconds'] = 'לפני %d שניות';
$lang['wordblock'] = 'השינויים שלך לא נשמרו כיוון שהם מכילים טקסט חסום (ספאם).';
+$lang['media_uploadtab'] = 'להעלות';
$lang['media_searchtab'] = 'חיפוש';
$lang['media_file'] = 'קובץ';
$lang['media_viewtab'] = 'תצוגה';
$lang['media_edittab'] = 'עריכה';
$lang['media_historytab'] = 'היסטוריה';
+$lang['media_list_thumbs'] = 'תמונות ממוזערות';
$lang['media_list_rows'] = 'שורות';
$lang['media_sort_name'] = 'שם';
$lang['media_sort_date'] = 'תאריך';
$lang['media_namespaces'] = 'בחר מרחב שמות';
+$lang['media_files'] = 'קבצים ב s%';
+$lang['media_upload'] = 'להעלות s%';
diff --git a/inc/lang/hu/lang.php b/inc/lang/hu/lang.php
index 2622934c2..5113e1cc8 100644
--- a/inc/lang/hu/lang.php
+++ b/inc/lang/hu/lang.php
@@ -12,6 +12,7 @@
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
* @author Marton Sebok <sebokmarton@gmail.com>
* @author Serenity87HUN <anikototh87@gmail.com>
+ * @author Marina Vladi <deldadam@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -295,6 +296,7 @@ $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_allowreg'] = 'A felhasználók saját maguk is regisztrálhatnak';
$lang['i_retry'] = 'Újra';
$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';
@@ -332,3 +334,7 @@ $lang['media_perm_read'] = 'Sajnáljuk, nincs jogod a fájlok olvasásáho
$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';
+$lang['currentns'] = 'Aktuális névtér';
+$lang['searchresult'] = 'Keresés eredménye';
+$lang['plainhtml'] = 'Sima HTML';
+$lang['wikimarkup'] = 'Wiki-jelölő nyelv';
diff --git a/inc/lang/id/lang.php b/inc/lang/id/lang.php
index 1c8610923..3d99c9a22 100644
--- a/inc/lang/id/lang.php
+++ b/inc/lang/id/lang.php
@@ -1,11 +1,12 @@
<?php
+
/**
- * Indonesian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author mubaidillah <mubaidillah@gmail.com>
* @author Irwan Butar Butar <irwansah.putra@gmail.com>
* @author Yustinus Waruwu <juswaruwu@gmail.com>
+ * @author zamroni <therons@ymail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -82,8 +83,13 @@ $lang['txt_filename'] = 'Masukkan nama wiki (opsional)';
$lang['txt_overwrt'] = 'File yang telah ada akan ditindih';
$lang['lockedby'] = 'Sedang dikunci oleh';
$lang['lockexpire'] = 'Penguncian artikel sampai dengan';
-$lang['js']['willexpire'] = 'Halaman yang sedang Anda kunci akan berakhir dalam waktu kurang lebih satu menit.\nUntuk menghindari konflik, gunakan tombol Preview untuk me-reset timer pengunci.';
+$lang['js']['willexpire'] = 'Halaman yang sedang Anda kunci akan berakhir dalam waktu kurang lebih satu menit.\nUntuk menghindari konflik, gunakan tombol Preview untuk me-reset timer pengunci.';
$lang['js']['notsavedyet'] = 'Perubahan yang belum disimpan akan hilang.\nYakin akan dilanjutkan?';
+$lang['js']['keepopen'] = 'Biarkan window terbuka dalam pemilihan';
+$lang['js']['hidedetails'] = 'Sembunyikan detil';
+$lang['js']['nosmblinks'] = 'Link ke share Windows hanya bekerja di Microsoft Internet Explorer.
+Anda masih dapat mengcopy and paste linknya.';
+$lang['js']['del_confirm'] = 'Hapus tulisan ini?';
$lang['rssfailed'] = 'Error terjadi saat mengambil feed: ';
$lang['nothingfound'] = 'Tidak menemukan samasekali.';
$lang['mediaselect'] = 'Pilihan Mediafile';
@@ -100,8 +106,6 @@ $lang['deletefail'] = '"%s" tidak dapat dihapus - cek hak aksesnya.';
$lang['mediainuse'] = 'File "%s" belum dihapus - file ini sedang digunakan.';
$lang['namespaces'] = 'Namespaces';
$lang['mediafiles'] = 'File tersedia didalam';
-$lang['js']['keepopen'] = 'Biarkan window terbuka dalam pemilihan';
-$lang['js']['hidedetails'] = 'Sembunyikan detil';
$lang['mediausage'] = 'Gunakan sintaks berikut untuk me-refer ke file ini';
$lang['mediaview'] = 'Tampilkan file asli';
$lang['mediaroot'] = 'root';
@@ -131,7 +135,6 @@ $lang['mail_newpage'] = 'Halaman ditambahkan:';
$lang['mail_changed'] = 'Halaman diubah:';
$lang['mail_new_user'] = 'User baru:';
$lang['mail_upload'] = 'Berkas di-upload:';
-$lang['js']['nosmblinks'] = "Link ke share Windows hanya bekerja di Microsoft Internet Explorer.\nAnda masih dapat mengcopy and paste linknya.";
$lang['qb_bold'] = 'Tebal';
$lang['qb_italic'] = 'Miring';
$lang['qb_underl'] = 'Garis Bawah';
@@ -151,7 +154,6 @@ $lang['qb_media'] = 'Tambahkan gambar atau file lain';
$lang['qb_sig'] = 'Sisipkan tanda tangan';
$lang['qb_smileys'] = 'Smileys';
$lang['qb_chars'] = 'Karakter Khusus';
-$lang['js']['del_confirm'] = 'Hapus tulisan ini?';
$lang['admin_register'] = 'Tambah user baru';
$lang['metaedit'] = 'Edit Metadata';
$lang['metasaveerr'] = 'Gagal menulis metadata';
diff --git a/inc/lang/it/lang.php b/inc/lang/it/lang.php
index 5300dfd2a..a2bde3b60 100644
--- a/inc/lang/it/lang.php
+++ b/inc/lang/it/lang.php
@@ -2,7 +2,7 @@
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- *
+ *
* @author Giorgio Vecchiocattivi <giorgio@vecchio.it>
* @author Roberto Bolli [http://www.rbnet.it/]
* @author Silvia Sargentoni <polinnia@tin.it>
@@ -16,6 +16,7 @@
* @author Matteo Pasotti <matteo@xquiet.eu>
* @author snarchio@gmail.com
* @author Edmondo Di Tucci <snarchio@gmail.com>
+ * @author Claudio Lanconelli <lancos@libero.it>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -298,6 +299,7 @@ $lang['i_policy'] = 'Regole di accesso iniziali';
$lang['i_pol0'] = 'Wiki Aperto (lettura, scrittura, caricamento file per tutti)';
$lang['i_pol1'] = 'Wiki Pubblico (lettura per tutti, scrittura e caricamento file per gli utenti registrati)';
$lang['i_pol2'] = 'Wiki Chiuso (lettura, scrittura, caricamento file solamente per gli utenti registrati)';
+$lang['i_allowreg'] = 'Permetti agli utenti di registrarsi';
$lang['i_retry'] = 'Riprova';
$lang['i_license'] = 'Per favore scegli la licenza sotto cui vuoi rilasciare il contenuto:';
$lang['i_license_none'] = 'Non mostrare informazioni sulla licenza';
@@ -335,3 +337,4 @@ $lang['media_perm_read'] = 'Spiacente, non hai abbastanza privilegi per le
$lang['media_perm_upload'] = 'Spiacente, non hai abbastanza privilegi per caricare files.';
$lang['media_update'] = 'Carica nuova versione';
$lang['media_restore'] = 'Ripristina questa versione';
+$lang['searchresult'] = 'Risultati della ricerca';
diff --git a/inc/lang/ja/lang.php b/inc/lang/ja/lang.php
index b032e1ce5..1f53b0a90 100644
--- a/inc/lang/ja/lang.php
+++ b/inc/lang/ja/lang.php
@@ -294,6 +294,7 @@ $lang['i_policy'] = 'ACL初期設定';
$lang['i_pol0'] = 'オープン Wiki(全ての人に、閲覧・書き込み・アップロードを許可)';
$lang['i_pol1'] = 'パブリック Wiki(閲覧は全ての人が可能、書き込み・アップロードは登録ユーザーのみ)';
$lang['i_pol2'] = 'クローズド Wiki (登録ユーザーにのみ使用を許可)';
+$lang['i_allowreg'] = 'ユーザ自身で登録可能';
$lang['i_retry'] = '再試行';
$lang['i_license'] = 'あなたが作成したコンテンツが属するライセンスを選択してください:';
$lang['i_license_none'] = 'ライセンス情報を表示しません。';
@@ -331,3 +332,7 @@ $lang['media_perm_read'] = 'ファイルを閲覧する権限がありま
$lang['media_perm_upload'] = 'ファイルをアップロードする権限がありません。';
$lang['media_update'] = '新しいバージョンをアップロード';
$lang['media_restore'] = 'このバージョンを復元';
+$lang['currentns'] = '現在の名前空間';
+$lang['searchresult'] = '検索結果';
+$lang['plainhtml'] = 'プレーンHTML';
+$lang['wikimarkup'] = 'Wikiマークアップ';
diff --git a/inc/lang/ja/subscr_digest.txt b/inc/lang/ja/subscr_digest.txt
index ff5fc8d47..b6c91a3a6 100644
--- a/inc/lang/ja/subscr_digest.txt
+++ b/inc/lang/ja/subscr_digest.txt
@@ -16,6 +16,6 @@
@SUBSCRIBE@
ページと名前空間の変更に対する購読を解除してください。
---
+--
このメールは次の DokuWiki によって生成されました:
@DOKUWIKIURL@ \ No newline at end of file
diff --git a/inc/lang/ja/subscr_list.txt b/inc/lang/ja/subscr_list.txt
index 0d225af58..9869fb811 100644
--- a/inc/lang/ja/subscr_list.txt
+++ b/inc/lang/ja/subscr_list.txt
@@ -14,6 +14,6 @@
@SUBSCRIBE@
ページと名前空間の変更に対する購読を解除してください。
---
+--
このメールは次の DokuWiki によって生成されました:
@DOKUWIKIURL@ \ No newline at end of file
diff --git a/inc/lang/ja/subscr_single.txt b/inc/lang/ja/subscr_single.txt
index b02352238..4620f73d6 100644
--- a/inc/lang/ja/subscr_single.txt
+++ b/inc/lang/ja/subscr_single.txt
@@ -19,6 +19,6 @@
@SUBSCRIBE@
ページと名前空間の変更に対する購読を解除してください。
---
+--
このメールは次の DokuWiki によって生成されました:
@DOKUWIKIURL@ \ No newline at end of file
diff --git a/inc/lang/ko/denied.txt b/inc/lang/ko/denied.txt
index cff844bf4..cf0b294a4 100644
--- a/inc/lang/ko/denied.txt
+++ b/inc/lang/ko/denied.txt
@@ -1,3 +1,3 @@
====== 권한 거절 ======
-죄송하지만 계속할 수 있는 권한이 없습니다. 로그인하세요. \ No newline at end of file
+죄송하지만 계속할 수 있는 권한이 없습니다. 로그인을 잊으셨나요? \ No newline at end of file
diff --git a/inc/lang/ko/editrev.txt b/inc/lang/ko/editrev.txt
index 8d3aeb813..530b38d25 100644
--- a/inc/lang/ko/editrev.txt
+++ b/inc/lang/ko/editrev.txt
@@ -1,2 +1,2 @@
-**문서의 이전 판을 선택했습니다!** 저장하면 이 데이터로 새 판을 만듭니다.
+**문서의 이전 판을 선택했습니다!** 저장하면 이 자료로 새 판을 만듭니다.
---- \ No newline at end of file
diff --git a/inc/lang/ko/lang.php b/inc/lang/ko/lang.php
index e6cae3db0..266ff01e5 100644
--- a/inc/lang/ko/lang.php
+++ b/inc/lang/ko/lang.php
@@ -11,6 +11,7 @@
* @author erial2@gmail.com
* @author Myeongjin <aranet100@gmail.com>
* @author Gerrit Uitslag <klapinklapin@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -23,7 +24,7 @@ $lang['btn_edit'] = '문서 편집';
$lang['btn_source'] = '원본 보기';
$lang['btn_show'] = '문서 보기';
$lang['btn_create'] = '문서 만들기';
-$lang['btn_search'] = '찾기';
+$lang['btn_search'] = '검색';
$lang['btn_save'] = '저장';
$lang['btn_preview'] = '미리 보기';
$lang['btn_top'] = '맨 위로';
@@ -69,13 +70,13 @@ $lang['badlogin'] = '죄송하지만 사용자 이름이나 비밀
$lang['badpassconfirm'] = '죄송하지만 비밀번호가 잘못되었습니다';
$lang['minoredit'] = '사소한 바뀜';
$lang['draftdate'] = '초안 자동 저장 시간';
-$lang['nosecedit'] = '한동안 문서가 바뀌었으며, 문단 정보가 오래되어 문서 전체를 대신 열었습니다.';
+$lang['nosecedit'] = '한 동안 문서가 바뀌었으며, 문단 정보가 오래되어 문서 전체를 대신 열었습니다.';
$lang['regmissing'] = '죄송하지만 모든 필드를 채워야 합니다.';
$lang['reguexists'] = '죄송하지만 같은 이름을 사용하는 사용자가 있습니다.';
$lang['regsuccess'] = '사용자를 만들었으며 비밀번호는 이메일로 보냈습니다.';
$lang['regsuccess2'] = '사용자를 만들었습니다.';
-$lang['regmailfail'] = '비밀번호를 이메일로 보낼 때 오류가 발생했습니다. 관리자에게 문의하세요!';
-$lang['regbadmail'] = '이메일 주소가 잘못됐습니다 - 오류라고 생각하면 관리자에게 문의하세요';
+$lang['regmailfail'] = '비밀번호를 이메일로 보내는 동안 오류가 발생했습니다. 관리자에게 문의하세요!';
+$lang['regbadmail'] = '주어진 이메일 주소가 잘못되었습니다 - 오류라고 생각하면 관리자에게 문의하세요';
$lang['regbadpass'] = '새 비밀번호가 같지 않습니다. 다시 입력하세요.';
$lang['regpwmail'] = '도쿠위키 비밀번호';
$lang['reghere'] = '계정이 없나요? 계정을 등록할 수 있습니다';
@@ -85,7 +86,7 @@ $lang['profnoempty'] = '이름이나 이메일 주소가 비었습니
$lang['profchanged'] = '개인 정보가 성공적으로 바뀌었습니다.';
$lang['profnodelete'] = '이 위키는 사용자 삭제를 지원하지 않습니다';
$lang['profdeleteuser'] = '계정 삭제';
-$lang['profdeleted'] = '내 사용자 계정이 이 위키에서 삭제되었습니다';
+$lang['profdeleted'] = '당신의 사용자 계정이 이 위키에서 삭제되었습니다';
$lang['profconfdelete'] = '이 위키에서 내 계정을 제거하고 싶습니다. <br/> 이 행동은 되돌릴 수 없습니다.';
$lang['profconfdeletemissing'] = '선택하지 않은 확인 상자를 확인';
$lang['pwdforget'] = '비밀번호를 잊으셨나요? 비밀번호를 재설정할 수 있습니다';
@@ -96,19 +97,19 @@ $lang['resendpwdnouser'] = '죄송하지만 데이터베이스에서 이
$lang['resendpwdbadauth'] = '죄송하지만 인증 코드가 올바르지 않습니다. 잘못된 확인 링크인지 확인하세요.';
$lang['resendpwdconfirm'] = '확인 링크를 이메일로 보냈습니다.';
$lang['resendpwdsuccess'] = '새 비밀번호를 이메일로 보냈습니다.';
-$lang['license'] = '별도로 명시하지 않을 경우, 이 위키의 내용은 다음의 라이선스에 따라 사용할 수 있습니다:';
-$lang['licenseok'] = '참고: 이 문서를 편집하면 내용은 다음 라이선스에 따라 사용 허가에 동의합니다:';
-$lang['searchmedia'] = '파일 이름 찾기:';
-$lang['searchmedia_in'] = '%s에서 찾기';
+$lang['license'] = '별도로 명시하지 않을 경우, 이 위키의 내용은 다음 라이선스에 따라 사용할 수 있습니다:';
+$lang['licenseok'] = '참고: 이 문서를 편집하면 내용은 다음 라이선스에 따라 배포하는 데 동의합니다:';
+$lang['searchmedia'] = '파일 이름 검색:';
+$lang['searchmedia_in'] = '%s에서 검색';
$lang['txt_upload'] = '올릴 파일 선택';
-$lang['txt_filename'] = '올릴 파일 이름 입력 (선택 사항)';
+$lang['txt_filename'] = '올릴 파일 이름 (선택 사항)';
$lang['txt_overwrt'] = '기존 파일에 덮어쓰기';
$lang['maxuploadsize'] = '최대 올리기 용량. 파일당 %s입니다.';
$lang['lockedby'] = '현재 잠겨진 사용자';
$lang['lockexpire'] = '잠금 해제 시간';
$lang['js']['willexpire'] = '잠시 후 편집 잠금이 해제됩니다.\n편집 충돌을 피하려면 미리 보기를 눌러 잠금 시간을 다시 설정하세요.';
$lang['js']['notsavedyet'] = '저장하지 않은 바뀜이 사라집니다.';
-$lang['js']['searchmedia'] = '파일 찾기';
+$lang['js']['searchmedia'] = '파일 검색';
$lang['js']['keepopen'] = '선택할 때 창을 열어 놓기';
$lang['js']['hidedetails'] = '자세한 정보 숨기기';
$lang['js']['mediatitle'] = '링크 설정';
@@ -152,7 +153,7 @@ $lang['nothingfound'] = '아무 것도 없습니다.';
$lang['mediaselect'] = '미디어 파일';
$lang['fileupload'] = '미디어 파일 올리기';
$lang['uploadsucc'] = '올리기 성공';
-$lang['uploadfail'] = '올리기를 실패했습니다. 잘못된 권한 때문일지도 모릅니다.';
+$lang['uploadfail'] = '올리기가 실패되었습니다. 잘못된 권한 때문일지도 모릅니다.';
$lang['uploadwrong'] = '올리기가 거부되었습니다. 금지된 파일 확장자입니다!';
$lang['uploadexist'] = '파일이 이미 존재합니다.';
$lang['uploadbadcontent'] = '올린 파일이 %s 파일 확장자와 일치하지 않습니다.';
@@ -174,7 +175,7 @@ $lang['reference'] = '참고';
$lang['ref_inuse'] = '다음 문서에서 아직 사용 중이므로 파일을 삭제할 수 없습니다:';
$lang['ref_hidden'] = '문서의 일부 참고는 읽을 수 있는 권한이 없습니다';
$lang['hits'] = '조회 수';
-$lang['quickhits'] = '일치하는 문서이름';
+$lang['quickhits'] = '일치하는 문서 이름';
$lang['toc'] = '목차';
$lang['current'] = '현재';
$lang['yours'] = '판';
@@ -182,7 +183,7 @@ $lang['diff'] = '현재 판과의 차이 보기';
$lang['diff2'] = '선택한 판 사이의 차이 보기';
$lang['difflink'] = '차이 보기로 링크';
$lang['diff_type'] = '차이 보기:';
-$lang['diff_inline'] = '인라인 방식';
+$lang['diff_inline'] = '직렬 방식';
$lang['diff_side'] = '다중 창 방식';
$lang['line'] = '줄';
$lang['breadcrumb'] = '추적';
@@ -244,7 +245,7 @@ $lang['img_backto'] = '뒤로';
$lang['img_title'] = '제목';
$lang['img_caption'] = '설명';
$lang['img_date'] = '날짜';
-$lang['img_fname'] = '파일이름';
+$lang['img_fname'] = '파일 이름';
$lang['img_fsize'] = '크기';
$lang['img_artist'] = '촬영자';
$lang['img_copyr'] = '저작권';
@@ -257,7 +258,7 @@ $lang['img_manager'] = '미디어 관리자에서 보기';
$lang['subscr_subscribe_success'] = '%s 사용자가 %s 구독 목록에 추가했습니다';
$lang['subscr_subscribe_error'] = '%s 사용자가 %s 구독 목록에 추가하는데 실패했습니다';
$lang['subscr_subscribe_noaddress'] = '로그인으로 연결된 주소가 없기 때문에 구독 목록에 추가할 수 없습니다';
-$lang['subscr_unsubscribe_success'] = '%s 사용자가 %s 구독 목록에서 삭제했습니다';
+$lang['subscr_unsubscribe_success'] = '%s 사용자가 %s 구독 목록에서 제거했습니다';
$lang['subscr_unsubscribe_error'] = '%s 사용자가 %s 구독 목록에서 삭제하는데 실패했습니다';
$lang['subscr_already_subscribed'] = '%s 사용자가 이미 %s에 구독하고 있습니다';
$lang['subscr_not_subscribed'] = '%s 사용자가 %s에 구독하고 있지 않습니다';
@@ -270,13 +271,13 @@ $lang['subscr_m_receive'] = '받기';
$lang['subscr_style_every'] = '모든 바뀜을 이메일로 받기';
$lang['subscr_style_digest'] = '각 문서의 바뀜을 요약 (매 %.2f일 마다)';
$lang['subscr_style_list'] = '마지막 이메일 이후 바뀐 문서의 목록 (매 %.2f일 마다)';
-$lang['authtempfail'] = '사용자 인증을 일시적으로 사용할 수 없습니다. 만약 계속해서 문제가 발생하면 위키 관리자에게 문의하시기 바랍니다.';
-$lang['authpwdexpire'] = '비밀번호를 바꾼지 %d일이 지났으며, 비민번호를 곧 바꿔야 합니다.';
+$lang['authtempfail'] = '사용자 인증을 일시적으로 사용할 수 없습니다. 만약 계속해서 문제가 발생한다면 위키 관리자에게 문의하시기 바랍니다.';
+$lang['authpwdexpire'] = '비밀번호를 바꾼지 %d일이 지났으며, 비밀번호를 곧 바꿔야 합니다.';
$lang['i_chooselang'] = '사용할 언어를 선택하세요';
-$lang['i_installer'] = 'DokuWiki 설치';
+$lang['i_installer'] = '도쿠위키 설치';
$lang['i_wikiname'] = '위키 이름';
$lang['i_enableacl'] = 'ACL 활성화 (권장)';
-$lang['i_superuser'] = '슈퍼 유저';
+$lang['i_superuser'] = '슈퍼 사용자';
$lang['i_problems'] = '설치하는 동안 아래와 같은 문제가 발생했습니다. 문제를 해결한 후 설치를 계속할 수 있습니다.';
$lang['i_modified'] = '보안 상의 이유로 이 스크립트는 수정되지 않은 새 도쿠위키 설치에서만 동작됩니다.
다운로드한 압축 패키지를 다시 설치하거나 <a href="http://dokuwiki.org/ko:install">도쿠위키 설치 과정</a>을 참고해서 설치하세요.';
@@ -293,6 +294,7 @@ $lang['i_policy'] = '초기 ACL 정책';
$lang['i_pol0'] = '열린 위키 (누구나 읽기, 쓰기, 올리기가 가능합니다)';
$lang['i_pol1'] = '공개 위키 (누구나 읽을 수 있지만, 등록된 사용자만 쓰기와 올리기가 가능합니다)';
$lang['i_pol2'] = '닫힌 위키 (등록된 사용자만 읽기, 쓰기, 올리기가 가능합니다)';
+$lang['i_allowreg'] = '사용자 자신이 등록할 수 있음';
$lang['i_retry'] = '다시 시도';
$lang['i_license'] = '내용을 배포하기 위한 라이선스를 선택하세요:';
$lang['i_license_none'] = '라이선스 정보를 보여주지 않습니다';
@@ -308,7 +310,7 @@ $lang['minutes'] = '%d분 전';
$lang['seconds'] = '%d초 전';
$lang['wordblock'] = '차단 문구(스팸)를 포함하고 있어서 바뀜을 저장하지 않았습니다.';
$lang['media_uploadtab'] = '올리기';
-$lang['media_searchtab'] = '찾기';
+$lang['media_searchtab'] = '검색';
$lang['media_file'] = '파일';
$lang['media_viewtab'] = '보기';
$lang['media_edittab'] = '편집';
@@ -320,13 +322,17 @@ $lang['media_sort_date'] = '날짜';
$lang['media_namespaces'] = '이름공간 선택';
$lang['media_files'] = '%s에 있는 파일';
$lang['media_upload'] = '%s에 올리기';
-$lang['media_search'] = '%s에서 찾기';
+$lang['media_search'] = '%s에서 검색';
$lang['media_view'] = '%s';
-$lang['media_viewold'] = '%2$s (%1$s에 있음)';
+$lang['media_viewold'] = '%s (%s에 있음)';
$lang['media_edit'] = '%s 편집';
-$lang['media_history'] = '%s의 내역';
+$lang['media_history'] = '%s의 역사';
$lang['media_meta_edited'] = '메타데이터 편집됨';
$lang['media_perm_read'] = '죄송하지만 파일을 읽을 권한이 없습니다.';
$lang['media_perm_upload'] = '죄송하지만 파일을 올릴 권한이 없습니다.';
$lang['media_update'] = '새 판 올리기';
$lang['media_restore'] = '이 판으로 되돌리기';
+$lang['currentns'] = '현재 이름공간';
+$lang['searchresult'] = '검색 결과';
+$lang['plainhtml'] = '일반 HTML';
+$lang['wikimarkup'] = '위키 문법';
diff --git a/inc/lang/ko/mailtext.txt b/inc/lang/ko/mailtext.txt
index e9e9c25e1..c97f446e2 100644
--- a/inc/lang/ko/mailtext.txt
+++ b/inc/lang/ko/mailtext.txt
@@ -1,13 +1,13 @@
도쿠위키 문서가 추가되거나 바뀌었습니다. 자세한 내용은 다음과 같습니다:
-날짜 : @DATE@
-브라우저 : @BROWSER@
-IP 주소 : @IPADDRESS@
-호스트 이름 : @HOSTNAME@
-이전 판 : @OLDPAGE@
-새 판 : @NEWPAGE@
-편집 요약 : @SUMMARY@
-사용자 : @USER@
+날짜: @DATE@
+브라우저: @BROWSER@
+IP 주소: @IPADDRESS@
+호스트 이름: @HOSTNAME@
+이전 판: @OLDPAGE@
+새 판: @NEWPAGE@
+편집 요약: @SUMMARY@
+사용자: @USER@
@DIFF@
diff --git a/inc/lang/ko/password.txt b/inc/lang/ko/password.txt
index 790f6b479..a60801ae1 100644
--- a/inc/lang/ko/password.txt
+++ b/inc/lang/ko/password.txt
@@ -2,8 +2,8 @@
여기에 @DOKUWIKIURL@에서 @TITLE@의 사용자 정보가 있습니다.
-로그인 : @LOGIN@
-비밀번호 : @PASSWORD@
+로그인: @LOGIN@
+비밀번호: @PASSWORD@
--
이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다 \ No newline at end of file
diff --git a/inc/lang/ko/register.txt b/inc/lang/ko/register.txt
index 4df968896..4d3df298e 100644
--- a/inc/lang/ko/register.txt
+++ b/inc/lang/ko/register.txt
@@ -1,3 +1,3 @@
====== 새 사용자 등록 ======
-이 위키에 새 계정을 만드려면 아래의 모든 내용을 입력하세요. **올바른 이메일 주소**를 사용하세요. 비밀번호를 입력하는 곳이 없다면 비밀번호는 이 이메일로 보내집니다. 사용자 이름은 올바른 [[doku>ko:pagename|문서이름]]이어야 합니다. \ No newline at end of file
+이 위키에 새 계정을 만드려면 아래의 모든 내용을 입력하세요. **올바른 이메일 주소**를 사용하세요. 비밀번호를 입력하는 곳이 없다면, 새 비밀번호는 해당 주소로 보내집니다. 사용자 이름은 올바른 [[doku>ko:pagename|문서 이름]]이어야 합니다. \ No newline at end of file
diff --git a/inc/lang/ko/registermail.txt b/inc/lang/ko/registermail.txt
index e7c808047..afa66686a 100644
--- a/inc/lang/ko/registermail.txt
+++ b/inc/lang/ko/registermail.txt
@@ -1,13 +1,13 @@
새 사용자가 등록되었습니다. 자세한 내용은 다음과 같습니다:
-사용자 이름 : @NEWUSER@
-실제 이름 : @NEWNAME@
-이메일 : @NEWEMAIL@
+사용자 이름: @NEWUSER@
+실명: @NEWNAME@
+이메일: @NEWEMAIL@
-날짜 : @DATE@
-브라우저 : @BROWSER@
-IP 주소 : @IPADDRESS@
-호스트 이름 : @HOSTNAME@
+날짜: @DATE@
+브라우저: @BROWSER@
+IP 주소: @IPADDRESS@
+호스트 이름: @HOSTNAME@
--
이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다 \ No newline at end of file
diff --git a/inc/lang/ko/searchpage.txt b/inc/lang/ko/searchpage.txt
index cb9bae2e0..2313f0bb0 100644
--- a/inc/lang/ko/searchpage.txt
+++ b/inc/lang/ko/searchpage.txt
@@ -1,5 +1,5 @@
-====== 찾기 ======
+====== 검색 ======
-아래에서 찾기 결과를 볼 수 있습니다. 만일 원하는 문서를 찾지 못하였다면, "문서 만들기"나 "문서 편집"을 사용해 쿼리 내용과 같은 이름의 문서를 만들거나 편집할 수 있습니다.
+아래에서 검색 결과를 찾을 수 있습니다. 만약 원하는 문서를 찾지 못했다면, "문서 만들기"나 "문서 편집"을 사용해 검색어와 같은 이름의 문서를 만들거나 편집할 수 있습니다.
===== 결과 ===== \ No newline at end of file
diff --git a/inc/lang/ko/subscr_digest.txt b/inc/lang/ko/subscr_digest.txt
index 7a044736a..0f03e51a3 100644
--- a/inc/lang/ko/subscr_digest.txt
+++ b/inc/lang/ko/subscr_digest.txt
@@ -7,12 +7,12 @@
@DIFF@
--------------------------------------------------------
-이전 판 : @OLDPAGE@
-새 판 : @NEWPAGE@
+이전 판: @OLDPAGE@
+새 판: @NEWPAGE@
문서의 알림을 취소하려면, @DOKUWIKIURL@에 로그인한 뒤
@SUBSCRIBE@ 문서를 방문해 문서나 이름공간의 구독을 취소하세요.
---
+--
이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다 \ No newline at end of file
diff --git a/inc/lang/ko/subscr_list.txt b/inc/lang/ko/subscr_list.txt
index 57aa78cf7..95133bbc7 100644
--- a/inc/lang/ko/subscr_list.txt
+++ b/inc/lang/ko/subscr_list.txt
@@ -10,5 +10,5 @@
문서의 알림을 취소하려면, @DOKUWIKIURL@에 로그인한 뒤
@SUBSCRIBE@ 문서를 방문해 문서나 이름공간의 구독을 취소하세요.
---
-이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다. \ No newline at end of file
+--
+이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다 \ No newline at end of file
diff --git a/inc/lang/ko/subscr_single.txt b/inc/lang/ko/subscr_single.txt
index ed5478441..1c7e551f0 100644
--- a/inc/lang/ko/subscr_single.txt
+++ b/inc/lang/ko/subscr_single.txt
@@ -7,14 +7,14 @@
@DIFF@
--------------------------------------------------------
-날짜 : @DATE@
-사용자 : @USER@
-편집 요약 : @SUMMARY@
-이전 판 : @OLDPAGE@
-새 판 : @NEWPAGE@
+날짜: @DATE@
+사용자: @USER@
+편집 요약: @SUMMARY@
+이전 판: @OLDPAGE@
+새 판: @NEWPAGE@
문서의 알림을 취소하려면, @DOKUWIKIURL@에 로그인한 뒤
@SUBSCRIBE@ 문서를 방문해 문서나 이름공간의 구독을 취소하세요.
---
+--
이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다 \ No newline at end of file
diff --git a/inc/lang/ko/uploadmail.txt b/inc/lang/ko/uploadmail.txt
index 1304ee331..430a843b2 100644
--- a/inc/lang/ko/uploadmail.txt
+++ b/inc/lang/ko/uploadmail.txt
@@ -1,14 +1,14 @@
도쿠위키가 파일을 올렸습니다. 자세한 정보는 다음과 같습니다:
-파일 : @MEDIA@
-이전 판 : @OLD@
-날짜 : @DATE@
-브라우저 : @BROWSER@
-IP 주소 : @IPADDRESS@
-호스트 이름 : @HOSTNAME@
-크기 : @SIZE@
-MIME 종류 : @MIME@
-사용자 : @USER@
+파일: @MEDIA@
+이전 판: @OLD@
+날짜: @DATE@
+브라우저: @BROWSER@
+IP 주소: @IPADDRESS@
+호스트 이름: @HOSTNAME@
+크기: @SIZE@
+MIME 유형: @MIME@
+사용자: @USER@
--
이 메일은 @DOKUWIKIURL@에서 도쿠위키가 생성했습니다 \ No newline at end of file
diff --git a/inc/lang/nl/edit.txt b/inc/lang/nl/edit.txt
index 9718d0900..88a15cfe4 100644
--- a/inc/lang/nl/edit.txt
+++ b/inc/lang/nl/edit.txt
@@ -1 +1 @@
-Pas de pagina aan en klik op ''Opslaan''. Zie [[wiki:syntax]] voor de Wiki-syntax. Pas de pagina allen aan als hij **verbeterd** kan worden. Als je iets wilt uitproberen kun je spelen in de [[playground:playground|zandbak]].
+Pas de pagina aan en klik op ''Opslaan''. Zie [[wiki:syntax]] voor de Wiki-syntax. Pas de pagina alleen aan als hij **verbeterd** kan worden. Als je iets wilt uitproberen kun je spelen in de [[playground:playground|zandbak]].
diff --git a/inc/lang/nl/lang.php b/inc/lang/nl/lang.php
index 5f95a99bf..e5e3e3c76 100644
--- a/inc/lang/nl/lang.php
+++ b/inc/lang/nl/lang.php
@@ -21,6 +21,7 @@
* @author Gerrit Uitslag <klapinklapin@gmail.com>
* @author Klap-in <klapinklapin@gmail.com>
* @author Remon <no@email.local>
+ * @author gicalle <gicalle@hotmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -304,6 +305,7 @@ $lang['i_policy'] = 'Initieel ACL-beleid';
$lang['i_pol0'] = 'Open wiki (lezen, schrijven, uploaden voor iedereen)';
$lang['i_pol1'] = 'Publieke wiki (lezen voor iedereen, schrijven en uploaden voor geregistreerde gebruikers)';
$lang['i_pol2'] = 'Besloten wiki (lezen, schrijven en uploaden alleen voor geregistreerde gebruikers)';
+$lang['i_allowreg'] = 'Toestaan dat gebruikers zichzelf registeren';
$lang['i_retry'] = 'Opnieuw';
$lang['i_license'] = 'Kies a.u.b. een licentie die u voor uw inhoud wilt gebruiken:';
$lang['i_license_none'] = 'Toon geen licentie informatie';
diff --git a/inc/lang/no/lang.php b/inc/lang/no/lang.php
index 254d3c56b..3f31f6c73 100644
--- a/inc/lang/no/lang.php
+++ b/inc/lang/no/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * Norwegian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Reidar Mosvold <Reidar.Mosvold@hit.no>
* @author Jorge Barrera Grandon <jorge@digitalwolves.org>
* @author Rune Rasmussen [http://www.syntaxerror.no/]
@@ -11,13 +11,15 @@
* @author Torkill Bruland <torkar-b@online.no>
* @author Rune M. Andersen <rune.andersen@gmail.com>
* @author Jakob Vad Nielsen <me@jakobnielsen.net>
- * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
+ * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
* @author Knut Staring <knutst@gmail.com>
* @author Lisa Ditlefsen <lisa@vervesearch.com>
* @author Erik Pedersen <erik.pedersen@shaw.ca>
* @author Rune Rasmussen syntaxerror.no@gmail.com
* @author Jon Bøe <jonmagneboe@hotmail.com>
* @author Egil Hansen <egil@rosetta.no>
+ * @author Thomas Juberg <Thomas.Juberg@Gmail.com>
+ * @author Boris <boris@newton-media.no>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -53,6 +55,7 @@ $lang['btn_backtomedia'] = 'Tilbake til valg av mediafil';
$lang['btn_subscribe'] = 'Abonnér på endringer';
$lang['btn_profile'] = 'Oppdater profil';
$lang['btn_reset'] = 'Tilbakestill';
+$lang['btn_resendpwd'] = 'Sett nytt passord';
$lang['btn_draft'] = 'Rediger kladd';
$lang['btn_recover'] = 'Gjennvinn kladd';
$lang['btn_draftdel'] = 'Slett kladd';
@@ -60,6 +63,7 @@ $lang['btn_revert'] = 'Gjenopprette';
$lang['btn_register'] = 'Registrer deg';
$lang['btn_apply'] = 'Bruk';
$lang['btn_media'] = 'Mediefiler';
+$lang['btn_deleteuser'] = 'Fjern min konto';
$lang['loggedinas'] = 'Innlogget som';
$lang['user'] = 'Brukernavn';
$lang['pass'] = 'Passord';
@@ -71,6 +75,7 @@ $lang['fullname'] = 'Fullt navn';
$lang['email'] = 'E-post';
$lang['profile'] = 'Brukerprofil';
$lang['badlogin'] = 'Ugyldig brukernavn og/eller passord.';
+$lang['badpassconfirm'] = 'Beklager, passordet var feil';
$lang['minoredit'] = 'Mindre endringer';
$lang['draftdate'] = 'Kladd autolagret';
$lang['nosecedit'] = 'Siden ble endret i mellomtiden, seksjonsinfo har blitt foreldet - lastet full side istedet.';
@@ -87,8 +92,14 @@ $lang['profna'] = 'Denne wikien støtter ikke profilendringer';
$lang['profnochange'] = 'Ingen endringer, ingenting å gjøre.';
$lang['profnoempty'] = 'Tomt navn- eller e-postfelt er ikke tillatt.';
$lang['profchanged'] = 'Brukerprofilen ble vellykket oppdatert.';
+$lang['profnodelete'] = 'Denne wikien støtter ikke sletting av brukere';
+$lang['profdeleteuser'] = 'Slett konto';
+$lang['profdeleted'] = 'Din brukerkonto har blitt slettet fra denne wikien';
+$lang['profconfdelete'] = 'Jeg ønsker å fjerne min konto fra denne wikien. <br/> Denne handlingen kan ikke omgjøres.';
+$lang['profconfdeletemissing'] = 'Boks for bekreftelse ikke avkrysset';
$lang['pwdforget'] = 'Glemt passordet ditt? Få deg et nytt';
$lang['resendna'] = 'Denne wikien støtter ikke nyutsending av passord.';
+$lang['resendpwd'] = 'Sett nytt passord for';
$lang['resendpwdmissing'] = 'Beklager, du må fylle inn alle felt.';
$lang['resendpwdnouser'] = 'Beklager, vi kan ikke finne denne brukeren i vår database.';
$lang['resendpwdbadauth'] = 'Beklager, denne autorisasjonskoden er ikke gyldig. Sjekk at du brukte hele bekreftelseslenken.';
@@ -101,6 +112,7 @@ $lang['searchmedia_in'] = 'Søk i %s';
$lang['txt_upload'] = 'Velg fil som skal lastes opp';
$lang['txt_filename'] = 'Skriv inn wikinavn (alternativt)';
$lang['txt_overwrt'] = 'Overskriv eksisterende fil';
+$lang['maxuploadsize'] = 'Opplast maks % per fil.';
$lang['lockedby'] = 'Låst av';
$lang['lockexpire'] = 'Låsingen utløper';
$lang['js']['willexpire'] = 'Din redigeringslås for dette dokumentet kommer snart til å utløpe.\nFor å unngå versjonskonflikter bør du forhåndsvise dokumentet ditt for å forlenge redigeringslåsen.';
@@ -195,6 +207,12 @@ $lang['external_edit'] = 'ekstern redigering';
$lang['summary'] = 'Redigeringskommentar';
$lang['noflash'] = 'For at dette innholdet skal vises må du ha <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.';
$lang['download'] = 'Last ned utdraget';
+$lang['tools'] = 'Verktøy';
+$lang['user_tools'] = 'Brukerverktøy';
+$lang['site_tools'] = 'Nettstedverktøy';
+$lang['page_tools'] = 'Sideverktøy';
+$lang['skip_to_content'] = 'Hopp til innhold';
+$lang['sidebar'] = 'Sidefelt';
$lang['mail_newpage'] = 'side lagt til:';
$lang['mail_changed'] = 'side endret:';
$lang['mail_subscribe_list'] = 'side endret i \'namespace\':';
@@ -264,6 +282,7 @@ $lang['subscr_style_every'] = 'e-post for alle endringer';
$lang['subscr_style_digest'] = 'e-post med sammendrag av endringer for hver side (%.2f dager mellom hver)';
$lang['subscr_style_list'] = 'liste med sider som er endra siden forrige e-post (%.2f dager mellom hver)';
$lang['authtempfail'] = 'Brukerautorisasjon er midlertidig utilgjengelig. Om dette vedvarer, vennligst informer Wiki-admin.';
+$lang['authpwdexpire'] = 'Ditt passord går ut om %d dager, du bør endre det snarest.';
$lang['i_chooselang'] = 'Velg språk';
$lang['i_installer'] = 'DokuWiki-installasjon';
$lang['i_wikiname'] = 'Wikinavn';
@@ -288,8 +307,12 @@ $lang['i_policy'] = 'Innledende ACL-politikk';
$lang['i_pol0'] = 'Åpen Wiki (les, skriv og opplasting for alle)';
$lang['i_pol1'] = 'Offentlig Wiki (les for alle, skriving og opplasting bare for registrerte brukere)';
$lang['i_pol2'] = 'Lukket Wiki (les, skriv og opplasting bare for registrerte brukere)';
+$lang['i_allowreg'] = 'Tillat at brukere registrerer seg selv';
$lang['i_retry'] = 'Prøv igjen';
$lang['i_license'] = 'Velg lisens som du vil legge ut innholdet under:';
+$lang['i_license_none'] = 'Ikke vis noen lisensinformasjon';
+$lang['i_pop_field'] = 'Venligst hejlp oss å forbedre Dokuwiki-opplevelsen:';
+$lang['i_pop_label'] = 'Sand annonyme bruksdata til Dokuwiki-utviklerene, en gang i måneden';
$lang['recent_global'] = 'Du ser nå på endringene i navnerommet <b>%s</b>. Du kan også<a href="%s">se på nylig foretatte endringer for hele wikien</a>.';
$lang['years'] = '%d år siden';
$lang['months'] = '%d måneder siden';
@@ -316,8 +339,12 @@ $lang['media_search'] = 'Søk i navnerommet <strong>%s</strong>.';
$lang['media_view'] = '%s';
$lang['media_viewold'] = '%s på %s';
$lang['media_edit'] = 'Rediger %s';
+$lang['media_history'] = '%vis historikk';
$lang['media_meta_edited'] = 'metadata er endra';
$lang['media_perm_read'] = 'Beklager, du har ikke tilgang til å lese filer.';
$lang['media_perm_upload'] = 'Beklager, du har ikke tilgang til å laste opp filer.';
$lang['media_update'] = 'Last opp ny versjon';
$lang['media_restore'] = 'Gjenopprett denne versjonen';
+$lang['currentns'] = 'gjeldende navnemellomrom';
+$lang['searchresult'] = 'Søk i resultat';
+$lang['plainhtml'] = 'Enkel HTML';
diff --git a/inc/lang/pl/lang.php b/inc/lang/pl/lang.php
index 118f0e5ab..142dd3baa 100644
--- a/inc/lang/pl/lang.php
+++ b/inc/lang/pl/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * polish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Grzegorz Żur <grzegorz.zur@gmail.com>
* @author Mariusz Kujawski <marinespl@gmail.com>
* @author Maciej Kurczewski <pipijajko@gmail.com>
@@ -14,6 +14,7 @@
* @author Łukasz Chmaj <teachmeter@gmail.com>
* @author Begina Felicysym <begina.felicysym@wp.eu>
* @author Aoi Karasu <aoikarasu@gmail.com>
+ * @author Tomasz Bosak <bosak.tomasz@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -57,6 +58,7 @@ $lang['btn_revert'] = 'Przywróć';
$lang['btn_register'] = 'Zarejestruj się!';
$lang['btn_apply'] = 'Zastosuj';
$lang['btn_media'] = 'Menadżer multimediów';
+$lang['btn_deleteuser'] = 'Usuń moje konto';
$lang['loggedinas'] = 'Zalogowany jako';
$lang['user'] = 'Użytkownik';
$lang['pass'] = 'Hasło';
@@ -68,6 +70,7 @@ $lang['fullname'] = 'Imię i nazwisko';
$lang['email'] = 'E-mail';
$lang['profile'] = 'Profil użytkownika';
$lang['badlogin'] = 'Nazwa użytkownika lub hasło są nieprawidłowe.';
+$lang['badpassconfirm'] = 'Niestety, hasło jest niepoprawne.';
$lang['minoredit'] = 'Mniejsze zmiany';
$lang['draftdate'] = 'Czas zachowania szkicu';
$lang['nosecedit'] = 'Strona została zmodyfikowana, sekcje zostały zmienione. Załadowano całą stronę.';
@@ -84,6 +87,11 @@ $lang['profna'] = 'To wiki nie pozwala na zmianę profilu.';
$lang['profnochange'] = 'Żadnych zmian, nic do zrobienia.';
$lang['profnoempty'] = 'Pusta nazwa lub adres e-mail nie dozwolone.';
$lang['profchanged'] = 'Zaktualizowano profil użytkownika.';
+$lang['profnodelete'] = 'Ta wiki nie umożliwia usuwania użytkowników';
+$lang['profdeleteuser'] = 'Usuń konto';
+$lang['profdeleted'] = 'Twoje konto zostało usunięte z tej wiki';
+$lang['profconfdelete'] = 'Chcę usunąć moje konto z tej wiki. <br/> Decyzja nie może być cofnięta.';
+$lang['profconfdeletemissing'] = 'Pole potwierdzenia nie zostało zaznaczone';
$lang['pwdforget'] = 'Nie pamiętasz hasła? Zdobądź nowe!';
$lang['resendna'] = 'To wiki nie pozwala na powtórne przesyłanie hasła.';
$lang['resendpwd'] = 'Podaj nowe hasło dla';
@@ -199,6 +207,7 @@ $lang['user_tools'] = 'Narzędzia użytkownika';
$lang['site_tools'] = 'Narzędzia witryny';
$lang['page_tools'] = 'Narzędzia strony';
$lang['skip_to_content'] = 'przejście do zawartości';
+$lang['sidebar'] = 'Pasek boczny';
$lang['mail_newpage'] = 'Strona dodana:';
$lang['mail_changed'] = 'Strona zmieniona:';
$lang['mail_subscribe_list'] = 'Zmienione strony w katalogu:';
@@ -265,6 +274,8 @@ $lang['subscr_m_unsubscribe'] = 'Zrezygnuj z subskrypcji';
$lang['subscr_m_subscribe'] = 'Subskrybuj';
$lang['subscr_m_receive'] = 'Otrzymuj';
$lang['subscr_style_every'] = 'email przy każdej zmianie';
+$lang['subscr_style_digest'] = 'e-mailowy wyciąg zmian dla każdej strony (co %.2f dni)';
+$lang['subscr_style_list'] = 'lista zmienionych stron od ostatniego e-maila (co %.2f dni)';
$lang['authtempfail'] = 'Uwierzytelnienie użytkownika jest w tej chwili niemożliwe. Jeśli ta sytuacja się powtórzy, powiadom administratora tego wiki.';
$lang['authpwdexpire'] = 'Twoje hasło wygaśnie za %d dni. Należy je zmienić w krótkim czasie.';
$lang['i_chooselang'] = 'Wybierz język';
@@ -288,8 +299,12 @@ $lang['i_policy'] = 'Wstępna polityka uprawnień ACL';
$lang['i_pol0'] = 'Otwarte Wiki (odczyt, zapis i dodawanie plików dla wszystkich)';
$lang['i_pol1'] = 'Publiczne Wiki (odczyt dla wszystkich, zapis i dodawanie plików tylko dla zarejestrowanych użytkowników)';
$lang['i_pol2'] = 'Zamknięte Wiki (odczyt, zapis i dodawanie plików tylko dla zarejestrowanych użytkowników)';
+$lang['i_allowreg'] = 'Pozwól użytkownikom rejestrować się.';
$lang['i_retry'] = 'Spróbuj ponownie';
$lang['i_license'] = 'Wybierz licencję, na warunkach której chcesz udostępniać treści:';
+$lang['i_license_none'] = 'Nie pokazuj żadnych informacji o licencji.';
+$lang['i_pop_field'] = 'Proszę, pomóż nam ulepszyć doświadczenia z DokuWiki:';
+$lang['i_pop_label'] = 'Raz na miesiąc, wysyłaj anonimowe statystyki do deweloperów DokuWiki';
$lang['recent_global'] = 'W tej chwili przeglądasz zmiany w katalogu <b>%s</b>. Możesz przejrzeć także <a href="%s">zmiany w całym wiki</a>.';
$lang['years'] = '%d lat temu';
$lang['months'] = '%d miesięcy temu';
@@ -322,3 +337,6 @@ $lang['media_perm_read'] = 'Przepraszamy, nie masz wystarczających uprawn
$lang['media_perm_upload'] = 'Przepraszamy, nie masz wystarczających uprawnień do przesyłania plików.';
$lang['media_update'] = 'Prześlij nową wersję';
$lang['media_restore'] = 'Odtwórz tą wersję';
+$lang['currentns'] = 'Obecna przestrzeń nazw.';
+$lang['searchresult'] = 'Wyniki wyszukiwania';
+$lang['plainhtml'] = 'Czysty HTML';
diff --git a/inc/lang/pt-br/editrev.txt b/inc/lang/pt-br/editrev.txt
index c7aa47878..df6413525 100644
--- a/inc/lang/pt-br/editrev.txt
+++ b/inc/lang/pt-br/editrev.txt
@@ -1,4 +1,4 @@
-**Você carregou uma revisão antiga desse documento!** Se você salvá-la, irá criar uma nova versão em esses dados.
+**Você carregou uma revisão antiga desse documento!** Se você salvá-la, irá criar uma nova versão com esses dados.
----
diff --git a/inc/lang/pt-br/index.txt b/inc/lang/pt-br/index.txt
index a7d17a2bc..816a49952 100644
--- a/inc/lang/pt-br/index.txt
+++ b/inc/lang/pt-br/index.txt
@@ -1,3 +1,3 @@
====== Índice ======
-Esse é um índice de todas as páginas disponíveis, ordenadas por [[doku>namespaces|espaços de nomes]]. \ No newline at end of file
+Esse é um índice de todas as páginas disponíveis, ordenadas por [[doku>namespaces|domínios]]. \ No newline at end of file
diff --git a/inc/lang/pt-br/lang.php b/inc/lang/pt-br/lang.php
index 812799f04..6845e792d 100644
--- a/inc/lang/pt-br/lang.php
+++ b/inc/lang/pt-br/lang.php
@@ -22,6 +22,7 @@
* @author Victor Westmann <victor.westmann@gmail.com>
* @author Leone Lisboa Magevski <leone1983@gmail.com>
* @author Dário Estevão <darioems@gmail.com>
+ * @author Juliano Marconi Lanigra <juliano.marconi@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -97,6 +98,8 @@ $lang['profchanged'] = 'O perfil do usuário foi atualizado com sucess
$lang['profnodelete'] = 'Esse wiki não suporta a exclusão de usuários ';
$lang['profdeleteuser'] = 'Excluir a conta';
$lang['profdeleted'] = 'Sua conta de usuário foi excluída desse wiki';
+$lang['profconfdelete'] = 'Eu desejo remover minha conta dessa wiki. <br/> Essa ação não pode ser desfeita.';
+$lang['profconfdeletemissing'] = 'Caixa de confirmação não marcada';
$lang['pwdforget'] = 'Esqueceu sua senha? Solicite outra';
$lang['resendna'] = 'Esse wiki não tem suporte para o reenvio de senhas.';
$lang['resendpwd'] = 'Definir a nova senha para';
@@ -304,6 +307,7 @@ $lang['i_policy'] = 'Política inicial de permissões';
$lang['i_pol0'] = 'Wiki aberto (leitura, escrita e envio de arquivos por todos)';
$lang['i_pol1'] = 'Wiki público (leitura por todos, escrita e envio de arquivos por usuários registrados)';
$lang['i_pol2'] = 'Wiki fechado (leitura, escrita e envio de arquivos somente por usuários registrados)';
+$lang['i_allowreg'] = 'Permite usuários se registrarem';
$lang['i_retry'] = 'Tentar novamente';
$lang['i_license'] = 'Por favor escolha a licença que voce deseja utilizar para seu conteúdo:';
$lang['i_license_none'] = 'Não mostrar nenhuma informação da licença';
@@ -341,3 +345,7 @@ $lang['media_perm_read'] = 'Desculpe, mas você não tem privilégios sufi
$lang['media_perm_upload'] = 'Desculpe, mas você não tem privilégios suficientes para enviar arquivos.';
$lang['media_update'] = 'Enviar uma nova versão';
$lang['media_restore'] = 'Restaurar esta versão';
+$lang['currentns'] = 'Domínio atual';
+$lang['searchresult'] = 'Resultado da Busca';
+$lang['plainhtml'] = 'HTML simples';
+$lang['wikimarkup'] = 'Marcação wiki';
diff --git a/inc/lang/ro/admin.txt b/inc/lang/ro/admin.txt
index b19a4d804..8c7b3d6bd 100644
--- a/inc/lang/ro/admin.txt
+++ b/inc/lang/ro/admin.txt
@@ -1,3 +1,3 @@
====== Administrare ======
-Puteți vedea mai jos o listă cu activitățile administrative disponibile în DokuWiki. \ No newline at end of file
+Poți vedea mai jos o listă cu acțiunile administrative disponibile în DokuWiki.
diff --git a/inc/lang/ro/adminplugins.txt b/inc/lang/ro/adminplugins.txt
index 6712d8225..121a8fdb6 100644
--- a/inc/lang/ro/adminplugins.txt
+++ b/inc/lang/ro/adminplugins.txt
@@ -1 +1 @@
-===== Plugin-uri Adiționale ===== \ No newline at end of file
+===== Plugin-uri suplimentare =====
diff --git a/inc/lang/ro/backlinks.txt b/inc/lang/ro/backlinks.txt
index 3fd5e3415..ae52a105f 100644
--- a/inc/lang/ro/backlinks.txt
+++ b/inc/lang/ro/backlinks.txt
@@ -1,4 +1,3 @@
====== Legături înapoi ======
Aceasta e o listă de pagini care au legături către pagina curentă.
-
diff --git a/inc/lang/ro/conflict.txt b/inc/lang/ro/conflict.txt
index 072f574f4..dcac6774a 100644
--- a/inc/lang/ro/conflict.txt
+++ b/inc/lang/ro/conflict.txt
@@ -1,6 +1,7 @@
====== Există o nouă versiune ======
-Există o versiune nouă a documentului editat. Aceasta se întîmplă cînd un alt utilizator a schimbat documentul în timp ce îl editezi.
-
-Examinează diferențele arătate mai jos, apoi ia decizia care versiune o reții. Dacă alegi ''Salvează'', versiunea documentului va fi salvată. Apăsați ''Renunțare'' pentru a menține versiunea curentă.
+Există o versiune nouă a paginii editate. Aceasta se întâmplă atunci când
+un alt utilizator a modificat pagina în timp ce editai.
+Examinează diferențele indicate mai jos, apoi ia decizia care versiune o vei
+reține. Dacă alegi ''Salvează'', versiunea paginii va fi salvată. Apasă ''Renunțare'' pentru a menține versiunea curentă.
diff --git a/inc/lang/ro/denied.txt b/inc/lang/ro/denied.txt
index 430db7610..8e8126a17 100644
--- a/inc/lang/ro/denied.txt
+++ b/inc/lang/ro/denied.txt
@@ -1,4 +1,4 @@
-====== Acces Interzis ======
-
-Din păcate nu aveți destule drepturi pentru a continua. Poate ați uitat să vă logați?
+====== Acces nepermis ======
+Din păcate nu ai destule drepturi pentru a continua. Poate ai uitat să te
+autentifici?
diff --git a/inc/lang/ro/diff.txt b/inc/lang/ro/diff.txt
index 197244453..4bf6250d9 100644
--- a/inc/lang/ro/diff.txt
+++ b/inc/lang/ro/diff.txt
@@ -1,4 +1,3 @@
====== Diferențe ======
-Aceasta arată diferențele dintre revziile selectate și versiunea curentă a paginii.
-
+Aici sunt prezentate diferențele dintre versiunile selectate și versiunea curentă a paginii.
diff --git a/inc/lang/ro/draft.txt b/inc/lang/ro/draft.txt
index 74badee8e..550db52ff 100644
--- a/inc/lang/ro/draft.txt
+++ b/inc/lang/ro/draft.txt
@@ -1,5 +1,8 @@
====== Fișierul schiță nu a fost găsit ======
-Ultima dvs. sesiune de editare nu s-a finalizat corect. În timpul lucrului, DocuWiki a salvat automat o schiță, pe care o puteți utiliza acum pentru a continua editarea. Mai jos puteți vedea informațiile care s-au salvat de la ultima dvs. sesiune.
+Ultima ta sesiune de editare nu s-a finalizat corect. În vreme ce lucrai,
+DokuWiki a salvat automat o schiță, pe care o poți utiliza acum pentru a
+continua editarea. Mai jos poți vedea informațiile care s-au salvat de la ultima sesiune.
-Decideți dacă vreți să //recuperați// sesiunea de editare pierdută, //ștergeți// schița salvată automat sau să //anulați// procesul de editare. \ No newline at end of file
+Decide dacă vrei să //recuperezi// sesiunea de editare pierdută, să //ștergi//
+schița salvată automat sau să //anulezi// procesul de editare.
diff --git a/inc/lang/ro/edit.txt b/inc/lang/ro/edit.txt
index 78761b9c4..cd5aa2e50 100644
--- a/inc/lang/ro/edit.txt
+++ b/inc/lang/ro/edit.txt
@@ -1,2 +1 @@
-Editează pagina și apasă ''Salvează''. Vezi [[wiki:syntax]] pentru sintaxă. Te rog editează pagina doar pentru a o **îmbunătați**. Dacă vrei să testezi cîteva lucruri, învață sa faci primii pași în [[playground:playground]].
-
+Editează pagina și apasă ''Salvează''. Vezi [[wiki:syntax]] pentru sintaxă. Te rog editează pagina doar pentru a o **îmbunătați**. Dacă vrei să testezi câteva lucruri, învață sa faci primii pași în [[playground:playground]].
diff --git a/inc/lang/ro/editrev.txt b/inc/lang/ro/editrev.txt
index 290dca496..983cd657d 100644
--- a/inc/lang/ro/editrev.txt
+++ b/inc/lang/ro/editrev.txt
@@ -1,2 +1,3 @@
-**Ai încărcat o versuine veche a documentului!** Dacă ai salvat-o, vei crea o versiune nouă cu această dată.
+**Ai încărcat o versiune anterioră a paginii.** Dacă ai salvat-o, vei crea o
+versiune nouă cu aceast conținut.
----
diff --git a/inc/lang/ro/index.txt b/inc/lang/ro/index.txt
index 5b88cc03b..1ae5b9ca5 100644
--- a/inc/lang/ro/index.txt
+++ b/inc/lang/ro/index.txt
@@ -1,4 +1,4 @@
====== Index ======
-Acesta e un index al tuturor paginilor ordonat după [[doku>namespaces|namespaces]].
-
+Acesta e un index al tuturor paginilor ordonat după [[doku>namespaces|spații
+de nume]].
diff --git a/inc/lang/ro/install.html b/inc/lang/ro/install.html
index 7fdc8fc21..222b86e54 100644
--- a/inc/lang/ro/install.html
+++ b/inc/lang/ro/install.html
@@ -1,10 +1,10 @@
-<p>Această pagină oferă asistență la instalarea pentru prima dată a <a href="http://dokuwiki.org">Dokuwiki</a>. Mai multe informații privind această instalare găsiți pe <a href="http://dokuwiki.org/installer">pagina de documentație</a>.</p>
+<p>Această pagină oferă asistență la instalarea pentru prima dată a <a href="http://dokuwiki.org">Dokuwiki</a>. Mai multe informații privind această instalare găsești în <a href="http://dokuwiki.org/installer">pagina de documentație</a>.</p>
-<p>DokuWiki folosește fișiere obișnuite pentru stocarea paginilor wiki și a informaților asociate acestor pagini (de ex. imagini, indecși de căutare, versiuni vechi, etc). Pentru a lucra cu succes, DokuWiki <strong>trebuie</strong> să aibă drepturi de scriere în directoarele ce conțin aceste fișiere.
-Acest script de instalare nu poate seta drepturile directoarelor. De regulă, aceasta se face direct, în linie de comandă, sau în cazul găzduirii, prin FTP sau prin panoul de control al gazdei (de ex. cPanel).</p>
+<p>DokuWiki folosește fișiere obișnuite pentru stocarea paginilor wiki și a informaților asociate acestor pagini (de ex. imagini, indecși de căutare, versiuni vechi etc.). Pentru a putea fi folosit, DokuWiki <strong>trebuie</strong> să aibă drepturi de scriere în directoarele ce conțin aceste fișiere.
+Acest script de instalare nu poate configura drepturile directoarelor. De regulă, aceasta se face direct, în linie de comandă, sau în cazul unoi soluții de hosting, prin FTP sau prin panoul de control al gazdei (de ex. cPanel).</p>
-<p>Acest script de instalare va configura DokuWiki pentru <abbr title="access control list">ACL</abbr>, care permite logarea administratorului și accesul la meniul de administrare pentru instalarea plugin-urilor, gestiunea utilizatorilor, a accesului la paginile wiki și modificarea setărilor de configurare.
-Nu este necesar pentru ca DokuWiki să funcționeze, însă face mai ușoară administrarea DokuWiki.</p>
+<p>Acest script de instalare va configura DokuWiki pentru <abbr title="access control list">ACL</abbr>, care permite autentificarea administratorului și accesul la meniul de administrare pentru instalarea plugin-urilor, gestiunea utilizatorilor, accesului la paginile wiki și modificarea configurației.
+Acest script nu este necesar pentru funcționarea DokuWiki, însă ușurează administrarea.
-<p>Utilizatorii experimentați sau utilizatorii ce au nevoie de setări speciale ar putea folosi această legătură privind<a href="http://dokuwiki.org/install">instrucțiunile de instalare</a> și <a href="http://dokuwiki.org/config">setările de configurare</a>.</p>
+<p>Utilizatorii experimentați sau utilizatorii care au nevoie de o configurație specială pot accesa paginile cu <a href="http://dokuwiki.org/install">instrucțiunile de instalare</a> și <a href="http://dokuwiki.org/config">opțiunile de configurare</a> a DokuWiki.</p>
diff --git a/inc/lang/ro/lang.php b/inc/lang/ro/lang.php
index 028c55a20..491ab58e7 100644
--- a/inc/lang/ro/lang.php
+++ b/inc/lang/ro/lang.php
@@ -28,7 +28,7 @@ $lang['btn_preview'] = 'Previzualizează';
$lang['btn_top'] = 'La început';
$lang['btn_newer'] = '<< mai recent';
$lang['btn_older'] = 'mai vechi>>';
-$lang['btn_revs'] = 'Versiuni vechi';
+$lang['btn_revs'] = 'Versiuni anterioare';
$lang['btn_recent'] = 'Modificări recente';
$lang['btn_upload'] = 'Upload';
$lang['btn_cancel'] = 'Renunțare';
@@ -53,7 +53,7 @@ $lang['btn_revert'] = 'Revenire';
$lang['btn_register'] = 'Înregistrează';
$lang['btn_apply'] = 'Aplică';
$lang['btn_media'] = 'Administrare media';
-$lang['loggedinas'] = 'Logat ca și';
+$lang['loggedinas'] = 'Autentificat ca';
$lang['user'] = 'Utilizator';
$lang['pass'] = 'Parola';
$lang['newpass'] = 'Parola nouă';
@@ -72,15 +72,15 @@ $lang['reguexists'] = 'Ne pare rău, un utilizator cu acest nume este
$lang['regsuccess'] = 'Utilizatorul a fost creat. Parola a fost trimisă prin e-mail.';
$lang['regsuccess2'] = 'Utilizatorul a fost creat.';
$lang['regmailfail'] = 'Se pare că a fost o eroare la trimiterea parolei prin e-mail. Contactează administratorul!';
-$lang['regbadmail'] = 'Adresa de e-mail este nevalidă - dacă sunteți de părere că este o eroare contactează administratorul.';
-$lang['regbadpass'] = 'Cele două parole furnizate nu sunt identice; încercați din nou.';
+$lang['regbadmail'] = 'Adresa de e-mail este nevalidă - dacă ești de părere că este o eroare contactează administratorul.';
+$lang['regbadpass'] = 'Cele două parole furnizate nu sunt identice; încearcă din nou.';
$lang['regpwmail'] = 'Parola ta DokuWiki';
-$lang['reghere'] = 'Înca nu ai un cont? Fă-ți unul!';
+$lang['reghere'] = 'Încă nu ai un cont? Creează unul!';
$lang['profna'] = 'Acest wiki nu permite modificarea profilului';
$lang['profnochange'] = 'Nici o modificare; nimic de făcut.';
-$lang['profnoempty'] = 'Nu sunt admise numele sau adresa de e-mail necompletate.';
+$lang['profnoempty'] = 'Nu sunt permise numele sau adresa de e-mail necompletate.';
$lang['profchanged'] = 'Profilul de utilizator a fost actualizat cu succes.';
-$lang['pwdforget'] = 'Parola uitată? Obține una nouă!';
+$lang['pwdforget'] = 'Parolă uitată? Obține una nouă!';
$lang['resendna'] = 'Acest wiki nu permite retrimiterea parolei.';
$lang['resendpwd'] = 'Configurează o parolă nouă pentru';
$lang['resendpwdmissing'] = 'Ne pare rău, trebuie completate toate câmpurile.';
@@ -103,15 +103,15 @@ Dorești să continui?';
$lang['js']['searchmedia'] = 'Caută fișiere';
$lang['js']['keepopen'] = 'Menține fereastra deschisă la selecție';
$lang['js']['hidedetails'] = 'Ascunde detalii';
-$lang['js']['mediatitle'] = 'Setări link';
-$lang['js']['mediadisplay'] = 'Tip link';
+$lang['js']['mediatitle'] = 'Configurare link';
+$lang['js']['mediadisplay'] = 'Tip de link';
$lang['js']['mediaalign'] = 'Aliniere';
$lang['js']['mediasize'] = 'Mărime imagine';
$lang['js']['mediatarget'] = 'Țintă link';
$lang['js']['mediaclose'] = 'Închide';
$lang['js']['mediainsert'] = 'Inserează';
$lang['js']['mediadisplayimg'] = 'Afișează imaginea';
-$lang['js']['mediadisplaylnk'] = 'Afișează doar linkul';
+$lang['js']['mediadisplaylnk'] = 'Afișează doar link-ul';
$lang['js']['mediasmall'] = 'Versiune mică';
$lang['js']['mediamedium'] = 'Versiune medie';
$lang['js']['medialarge'] = 'Versiune mare';
@@ -133,7 +133,7 @@ $lang['js']['restore_confirm'] = 'Ești sigur de restaurarea acestei versiuni?';
$lang['js']['media_diff'] = 'Arată diferențele:';
$lang['js']['media_diff_both'] = 'Unul lângă altul';
$lang['js']['media_diff_opacity'] = 'Străveziu';
-$lang['js']['media_diff_portions'] = 'Lovește cu putere';
+$lang['js']['media_diff_portions'] = 'Glisează';
$lang['js']['media_select'] = 'Selectează fișierele...';
$lang['js']['media_upload_btn'] = 'Încarcă';
$lang['js']['media_done_btn'] = 'Gata';
@@ -283,7 +283,7 @@ $lang['i_success'] = 'Configurarea a fost finalizată cu succes. Acu
$lang['i_failure'] = 'Au apărut erori la scrierea fișierelor de configurare. Va trebui să le corectezi manual înainte de a putea folosi <a href="doku.php?id=wiki:welcome">noua ta instanță DokuWiki</a>.';
$lang['i_policy'] = 'Politica ACL (liste de control a accesului) inițială';
$lang['i_pol0'] = 'Wiki deschis (oricine poate citi, scrie și încărca fișiere)';
-$lang['i_pol1'] = 'Wiki public (oricine poate citi, utilizatorii înregistrați pot scrie și încărca fișiere';
+$lang['i_pol1'] = 'Wiki public (oricine poate citi, utilizatorii înregistrați pot scrie și încărca fișiere)';
$lang['i_pol2'] = 'Wiki închis (doar utilizatorii înregistrați pot citi, scrie și încărca fișiere)';
$lang['i_retry'] = 'Încearcă din nou';
$lang['i_license'] = 'Te rugăm să alegi licența sub care dorești să publici conținutul:';
diff --git a/inc/lang/ro/locked.txt b/inc/lang/ro/locked.txt
index 8708157ec..d1e80ad40 100644
--- a/inc/lang/ro/locked.txt
+++ b/inc/lang/ro/locked.txt
@@ -1,3 +1,4 @@
====== Pagină blocată ======
-Pagina este momentan blocată de alt utilizator. Trebuie să aștepți pînă cînd acest utilizator termină editarea ori expiră blocarea.
+Pagina este momentan blocată de alt utilizator. Trebuie să aștepți pînă când
+acest utilizator termină editarea sau până când expiră blocarea.
diff --git a/inc/lang/ro/login.txt b/inc/lang/ro/login.txt
index 81bca6298..7de38f621 100644
--- a/inc/lang/ro/login.txt
+++ b/inc/lang/ro/login.txt
@@ -1,4 +1,4 @@
-====== Login ======
-
-Nu sînteți logat! Introduceți datele de autentificare pentru logare. Trebuie să permiteți cookie-uri pentru logare.
+====== Autentificare ======
+Nu ești autentificat! Introdu datele de autentificare. Pentru ca
+autentificarea să funcționeze trebuie să fie permise cookie-urile în browser.
diff --git a/inc/lang/ro/mailtext.txt b/inc/lang/ro/mailtext.txt
index 77aca8c4b..8d20a301d 100644
--- a/inc/lang/ro/mailtext.txt
+++ b/inc/lang/ro/mailtext.txt
@@ -1,16 +1,17 @@
-A fost adăugată sau schimbată o pagină. Aici sînt detaliile:
+Salutare, @FULLNAME@!
-Data : @DATE@
-Navigator : @BROWSER@
-Adresa-IP : @IPADDRESS@
-Nume gazdă : @HOSTNAME@
-Versiune veche : @OLDPAGE@
-Versiune nouă : @NEWPAGE@
-Rezumat editare: @SUMMARY@
+A fost adăugată sau modificată o pagină. Aici sunt detaliile:
-@DIFF@
+Dată : @DATE@
+Browser : @BROWSER@
+Adresă IP : @IPADDRESS@
+Hostname : @HOSTNAME@
+Versiune anterioară : @OLDPAGE@
+Versiune curentă : @NEWPAGE@
+Sumar editare: @SUMMARY@
+@DIFF@
---
-Mailul a fost generat de DokuWiki la
+--
+Acest e-mail a fost generat de DokuWiki la
@DOKUWIKIURL@
diff --git a/inc/lang/ro/newpage.txt b/inc/lang/ro/newpage.txt
index 886258609..2ef35136e 100644
--- a/inc/lang/ro/newpage.txt
+++ b/inc/lang/ro/newpage.txt
@@ -1,3 +1,3 @@
-====== Subiectul nu există încă ======
+====== Pagina nu există încă ======
-Ați urmat o legătură către un subiect care nu există. O puteți crea prin apăsarea butonului ''Editează această pagină''.
+Ai urmat o legătură către o pagină care nu există. O poti crea prin apăsarea butonului ''Editează această pagină''.
diff --git a/inc/lang/ro/norev.txt b/inc/lang/ro/norev.txt
index 4a21abcbf..08bbb74dd 100644
--- a/inc/lang/ro/norev.txt
+++ b/inc/lang/ro/norev.txt
@@ -1,4 +1,4 @@
-====== Nu există versiunea ======
-
-Versiunea specificată nu există. Folosește butonul ''Versiuni vechi'' pentru o listă a versiunilor acestui document.
+====== Nu există versiunea paginii ======
+Versiunea indicată nu există. Folosește butonul ''Versiuni anterioare'' pentru
+o listă a versiunilor acestei pagini.
diff --git a/inc/lang/ro/password.txt b/inc/lang/ro/password.txt
index a7eb12dd9..eb325204b 100644
--- a/inc/lang/ro/password.txt
+++ b/inc/lang/ro/password.txt
@@ -1,10 +1,10 @@
-Salut @FULLNAME@!
+Salutare, @FULLNAME@!
-Aici sînt datele utilizator pentru @TITLE@ la @DOKUWIKIURL@
+Aici se găsesc credențialele de utilizator pentru @TITLE@ la @DOKUWIKIURL@
Login : @LOGIN@
Parola : @PASSWORD@
---
-Mesajul a fost generat de către DokuWiki la
+--
+Acest e-mail a fost generat de DokuWiki la
@DOKUWIKIURL@
diff --git a/inc/lang/ro/preview.txt b/inc/lang/ro/preview.txt
index 1964d7476..c89d19727 100644
--- a/inc/lang/ro/preview.txt
+++ b/inc/lang/ro/preview.txt
@@ -1,4 +1,3 @@
====== Previzualizare ======
-Acesta este modul în care va arăta textul. Nu uita: **Nu** e încă **salvat**!
-
+Acesta este modul în care va arăta textul. Ai în vedere: **Nu** e încă **salvat**!
diff --git a/inc/lang/ro/pwconfirm.txt b/inc/lang/ro/pwconfirm.txt
index ae2d9f963..0728b2ef0 100644
--- a/inc/lang/ro/pwconfirm.txt
+++ b/inc/lang/ro/pwconfirm.txt
@@ -1,13 +1,14 @@
-Salut @FULLNAME@!
+Salutare, @FULLNAME@!
-Cineva a cerut o parolă nouă pentru @TITLE@ pentru conectarea la @DOKUWIKIURL@
+Cineva a cerut o parolă nouă pentru @TITLE@ pentru conectarea la
+@DOKUWIKIURL@.
-Dacă nu ați solicitat o parolă nouă, ignorați acest email.
+Dacă nu ai solicitat o parolă nouă, ignoră acest e-mail.
-Pentru a confirma că cererea a fost într-adevăr trimisă de dumneavoastră, folosiți link-ul de mai jos.
+Pentru a confirma că cererea a fost într-adevăr trimisă de tine, folosește link-ul de mai jos.
@CONFIRM@
--
-Acest mail a fost generat de DocuWiki la
-@DOKUWIKIURL@ \ No newline at end of file
+Acest e-mail a fost generat de DokuWiki la
+@DOKUWIKIURL@
diff --git a/inc/lang/ro/read.txt b/inc/lang/ro/read.txt
index 72c33c0c0..442188f21 100644
--- a/inc/lang/ro/read.txt
+++ b/inc/lang/ro/read.txt
@@ -1,2 +1,2 @@
-Această pagină poate fi doar citită. Poți vedea sursa, dar n-o poți modifica. Consultă administratorul dacă crezi că e ceva în neregulă.
-
+Această pagină poate fi doar citită. Poți vedea sursa, dar nu poți modifica
+pagina. Consultă administratorul dacă ești de părere că ceva este în neregulă.
diff --git a/inc/lang/ro/recent.txt b/inc/lang/ro/recent.txt
index 8d4aa043a..e92ca8fa7 100644
--- a/inc/lang/ro/recent.txt
+++ b/inc/lang/ro/recent.txt
@@ -1,5 +1,3 @@
-====== Schimbări recente ======
-
-Următoarele pagini au fost schimbate recent.
-
+====== Modificări recente ======
+Următoarele pagini au fost modificate recent.
diff --git a/inc/lang/ro/register.txt b/inc/lang/ro/register.txt
index e062a46bc..1a6ef2538 100644
--- a/inc/lang/ro/register.txt
+++ b/inc/lang/ro/register.txt
@@ -1,3 +1,4 @@
====== Înregistrează-te ca utilizator nou ======
-Pentru a crea un wiki nou completează mai jos toate informațiile. Asigură-te că ai introdus o adresă de **e-mail validă** unde va fi trimisă noua parolă. Numele de utilizator trebuie de asemenea să fie valid [[doku>pagename|pagename]].
+Pentru a crea un wiki nou completează mai jos toate informațiile. Asigură-te
+că ai introdus o adresă de e-mail **validă** unde va fi trimisă noua parolă. Numele de utilizator trebuie de asemenea să fie valid [[doku>pagename|pagename]].
diff --git a/inc/lang/ro/registermail.txt b/inc/lang/ro/registermail.txt
index fb754af67..2aab247f7 100644
--- a/inc/lang/ro/registermail.txt
+++ b/inc/lang/ro/registermail.txt
@@ -1,14 +1,15 @@
-Un nou utilizator s-a înregsitrat. Iată detaliile:
+Salutare, @FULLNAME@!
-Nume utilizator : @NEWUSER@
+Un nou utilizator s-a înregistrat. Iată detaliile:
+
+Nume de utilizator : @NEWUSER@
Nume complet : @NEWNAME@
E-mail : @NEWEMAIL@
-
-Data : @DATE@
+Dată : @DATE@
Browser : @BROWSER@
Adresă IP : @IPADDRESS@
Hostname : @HOSTNAME@
---
-Acest mail a fost generat automat de către DokuWiki la
+--
+Acest e-mail a fost generat de DokuWiki la
@DOKUWIKIURL@
diff --git a/inc/lang/ro/resendpwd.txt b/inc/lang/ro/resendpwd.txt
index 4a67f9e80..24d995e89 100644
--- a/inc/lang/ro/resendpwd.txt
+++ b/inc/lang/ro/resendpwd.txt
@@ -1,3 +1,5 @@
====== Trimite parolă nouă ======
-Introduceți numele de utilizator în formularul de mai jos pentru a solicita o nouă parolă pentru această wiki. Un link de confirmare va fi trimis la adresa de email înregistrată. \ No newline at end of file
+Introduc numele de utilizator în formularul de mai jos pentru a solicita o
+nouă parolă pentru aceast wiki. Un link de confirmare va fi trimis la adresa
+de e-mail înregistrată.
diff --git a/inc/lang/ro/resetpwd.txt b/inc/lang/ro/resetpwd.txt
index 2eb8052f1..9cea53c4a 100644
--- a/inc/lang/ro/resetpwd.txt
+++ b/inc/lang/ro/resetpwd.txt
@@ -1,3 +1,3 @@
-====== Setează parolă nouă ======
+====== Configurează o parolă nouă ======
-Vă rugăm să introduceți o nouă parolă pentru contul dvs. pe acest wiki. \ No newline at end of file
+Te rog să introduci o parolă nouă pentru contul tău de pe acest wiki.
diff --git a/inc/lang/ro/revisions.txt b/inc/lang/ro/revisions.txt
index d42134c61..7cafaf046 100644
--- a/inc/lang/ro/revisions.txt
+++ b/inc/lang/ro/revisions.txt
@@ -1,4 +1,5 @@
-====== Versiune veche ======
-
-Acestea sînt versiunile vechi ale documentului curent. Pentru revenirea la o versiune mai veche, selecteaz-o de mai jos, clic pe ''Editează această pagină'' și salveaz-o.
+====== Versiune anterioară ======
+Acestea sunt versiunile anterioare ale paginii curente. Pentru revenirea la o
+versiune anteroară, selectează versiunea de mai jos, clic pe ''Editează
+această pagină'' și salvează versiunea.
diff --git a/inc/lang/ro/searchpage.txt b/inc/lang/ro/searchpage.txt
index 8c78c68c3..53e66adf0 100644
--- a/inc/lang/ro/searchpage.txt
+++ b/inc/lang/ro/searchpage.txt
@@ -1,5 +1,5 @@
====== Căutare ======
-Rezultatele căutării sînt afisate mai jos. Dacă n-ați găsit ce-ați căutat, puteți creea o pagină nouă după căutare prin folosirea butonului ''Editează această pagină''.
+Rezultatele căutării sunt afișate mai jos. Dacă nu ai găsit ce ai căutat, poți crea o pagină nouă prin folosirea butonului ''Editează această pagină''.
===== Rezultate =====
diff --git a/inc/lang/ro/showrev.txt b/inc/lang/ro/showrev.txt
index c1d5e545d..4c76fd402 100644
--- a/inc/lang/ro/showrev.txt
+++ b/inc/lang/ro/showrev.txt
@@ -1,2 +1,2 @@
-**Aceasta e o versiune veche a documentului!**
+**Aceasta e o versiune anterioară a paginii.**
----
diff --git a/inc/lang/ro/stopwords.txt b/inc/lang/ro/stopwords.txt
index 1f0d9536b..adcd7eff1 100644
--- a/inc/lang/ro/stopwords.txt
+++ b/inc/lang/ro/stopwords.txt
@@ -1,6 +1,8 @@
# Aceasta este o listă de cuvinte ignorate la indexare, câte un cuvânt pe linie
-# Când editați acest fișier, asigurați-vă că folosiți sfârșituri de linie UNIX (o singură linie nouă)
-# Nu e nevoie să includeți cuvinte mai scurte de 3 caractere - acestea sunt, oricum, ignorate
+# Când editezi acest fișier, asigură-te că folosești sfârșituri de linie UNIX
+# (o singură linie nouă).
+# Nu e nevoie să incluzi cuvinte mai scurte de 3 caractere - acestea sunt,
+# oricum, ignorate.
# Această listă se bazează pe cele ce pot fi găsite la http://www.ranks.nl/stopwords/
about
are
diff --git a/inc/lang/ro/subscr_digest.txt b/inc/lang/ro/subscr_digest.txt
index ad0a30708..8b0aac5c4 100644
--- a/inc/lang/ro/subscr_digest.txt
+++ b/inc/lang/ro/subscr_digest.txt
@@ -1,20 +1,20 @@
-Buna ziua!
+Salutare, @FULLNAME@!
-Pagina @PAGE@ în @TITLE@ wiki s-a modificat.
+Pagina @PAGE@ în @TITLE@ wiki a fost modificată.
Acestea sunt modificările:
--------------------------------------------------------
@DIFF@
--------------------------------------------------------
-Vechea revizie: @OLDPAGE@
-Noua revizie: @NEWPAGE@
+Versiune anterioară: @OLDPAGE@
+Versiune curentă: @NEWPAGE@
-Pentru a anula notificarea paginii, logați-vă pe wiki la
-@DOKUWIKIURL@ apoi navigați la
+Pentru a anula notificarea paginii, autentifică-te pe wiki la
+@DOKUWIKIURL@ apoi accesează
@SUBSCRIBE@
-și dezabonați-vă de la pagină și/sau modificările numelui de spațiu.
+și dezabonează-te de la pagină și/sau modificările spațiului de nume.
--
-Acest mail a fost generat de DokuWiki la
-@DOKUWIKIURL@ \ No newline at end of file
+Acest e-mail a fost generat de DokuWiki la
+@DOKUWIKIURL@
diff --git a/inc/lang/ro/subscr_form.txt b/inc/lang/ro/subscr_form.txt
index e55dfe6cb..c198cafdc 100644
--- a/inc/lang/ro/subscr_form.txt
+++ b/inc/lang/ro/subscr_form.txt
@@ -1,3 +1,4 @@
====== Administrarea abonărilor ======
-Această pagină vă permite să vă administrați abonările pentru pagina curentă și numele de spațiu. \ No newline at end of file
+Această pagină îți permite să îți administrăzi abonările pentru pagina curentă
+și pentru spațiul de nume.
diff --git a/inc/lang/ro/subscr_list.txt b/inc/lang/ro/subscr_list.txt
index 1b55ea917..c34334268 100644
--- a/inc/lang/ro/subscr_list.txt
+++ b/inc/lang/ro/subscr_list.txt
@@ -1,17 +1,17 @@
-Bună ziua!
+Salutare, @FULLNAME@!
-Paginile din numele de spațiu @PAGE@ al @TITLE@ wiki s-au modificat.
-Acestea sunt modificările:
+Paginile din spațiul de nume @PAGE@ al @TITLE@ wiki au fost modificate.
+Modificările sunt următoarele:
--------------------------------------------------------
@DIFF@
--------------------------------------------------------
-Pentru a anula notificarea paginii, logați-vă pe wiki la
-@DOKUWIKIURL@ apoi navigați la
+Pentru a anula notificarea paginii, autentificcă-te pe wiki la
+@DOKUWIKIURL@ apoi accesează
@SUBSCRIBE@
-și dezabonați-vă de la pagină și/sau modificările numelui de spațiu.
+și dezabonează-te de la pagină și/sau modificările spațiului de nume.
--
-Acest mail a fost generat de DokuWiki la
-@DOKUWIKIURL@ \ No newline at end of file
+Acest e-mail a fost generat de DokuWiki la
+@DOKUWIKIURL@
diff --git a/inc/lang/ro/subscr_single.txt b/inc/lang/ro/subscr_single.txt
index 006db741d..0fee1a831 100644
--- a/inc/lang/ro/subscr_single.txt
+++ b/inc/lang/ro/subscr_single.txt
@@ -1,23 +1,23 @@
-Bună ziua!
+Salutare, @FULLNAME@!
-Pagina @PAGE@ în @TITLE@ wiki s-a modificat.
-Acestea sunt modificările:
+Pagina @PAGE@ în @TITLE@ wiki a fost modificată.
+Modificările sunt următoarele:
--------------------------------------------------------
@DIFF@
--------------------------------------------------------
-Data: @DATE@
+Dată: @DATE@
Utilizator: @USER@
Sumarul editării: @SUMMARY@
-Vechea revizie: @OLDPAGE@
-Noua revizie: @NEWPAGE@
+Versiune anterioară: @OLDPAGE@
+Versiune curentă: @NEWPAGE@
-Pentru a anula notificarea paginii, logați-vă pe wiki la
-@DOKUWIKIURL@ apoi navigați la
+Pentru a anula notificarea paginii, autentificcă-te pe wiki la
+@DOKUWIKIURL@ apoi accesează
@SUBSCRIBE@
-și dezabonați-vă de la pagină și/sau modificările numelui de spațiu.
+și dezabonează-te de la pagină și/sau modificările spațiului de nume.
--
-Acest mail a fost generat de DokuWiki la
-@DOKUWIKIURL@ \ No newline at end of file
+Acest e-mail a fost generat de DokuWiki la
+@DOKUWIKIURL@
diff --git a/inc/lang/ro/updateprofile.txt b/inc/lang/ro/updateprofile.txt
index f3985a1c6..de43c69cb 100644
--- a/inc/lang/ro/updateprofile.txt
+++ b/inc/lang/ro/updateprofile.txt
@@ -1,3 +1,4 @@
====== Actualizare profil utilizator ======
-Trebuie să completați doar câmpurile pe care doriți să le modificați. Nu puteți modifica numele de utilizator. \ No newline at end of file
+Trebuie să completezi doar câmpurile pe care dorești să le modifici. Nu poți
+modifica numele de utilizator.
diff --git a/inc/lang/ro/uploadmail.txt b/inc/lang/ro/uploadmail.txt
index c1e5736e2..81c2828e8 100644
--- a/inc/lang/ro/uploadmail.txt
+++ b/inc/lang/ro/uploadmail.txt
@@ -1,7 +1,9 @@
-Un fișier a fost încărcat în DocuWiki. Iată detaliile:
+Salutare, @FULLNAME@!
+
+Un fișier a fost încărcat în DokuWiki. Iată detaliile:
Fișier : @MEDIA@
-Data : @DATE@
+Dată : @DATE@
Browser : @BROWSER@
Adresă IP : @IPADDRESS@
Hostname : @HOSTNAME@
@@ -10,5 +12,5 @@ MIME Type : @MIME@
Utilizator : @USER@
--
-Acest mail a fost generat automat de către DokuWiki la
+Acest e-mail a fost generat de DokuWiki la
@DOKUWIKIURL@
diff --git a/inc/lang/ru/lang.php b/inc/lang/ru/lang.php
index 6a0c4bb6b..208d647a8 100644
--- a/inc/lang/ru/lang.php
+++ b/inc/lang/ru/lang.php
@@ -22,6 +22,8 @@
* @author Johnny Utah <pcpa@cyberpunk.su>
* @author Ivan I. Udovichenko (sendtome@mymailbox.pp.ua)
* @author Pavel <ivanovtsk@mail.ru>
+ * @author Artur <ncuxxx@gmail.com>
+ * @author Erli Moen <evseev.jr@gmail.com>
*/
$lang['encoding'] = ' utf-8';
$lang['direction'] = 'ltr';
@@ -306,6 +308,7 @@ $lang['i_policy'] = 'Исходная политика прав д
$lang['i_pol0'] = 'Открытая вики (чтение, запись, закачка файлов для всех)';
$lang['i_pol1'] = 'Общедоступная вики (чтение для всех, запись и загрузка файлов для зарегистрированных пользователей)';
$lang['i_pol2'] = 'Закрытая вики (чтение, запись и загрузка файлов только для зарегистрированных пользователей)';
+$lang['i_allowreg'] = 'Позволить пользователям самостоятельно регестрироваться';
$lang['i_retry'] = 'Повторить попытку';
$lang['i_license'] = 'Пожалуйста, выберите тип лицензии для своей вики:';
$lang['i_license_none'] = 'Не отображать информацию о лицензионных операциях';
@@ -344,3 +347,6 @@ $lang['media_perm_read'] = 'Извините, у вас недостато
$lang['media_perm_upload'] = 'Извините, у вас недостаточно прав для загрузки файлов.';
$lang['media_update'] = 'Загрузить новую версию';
$lang['media_restore'] = 'Восстановить эту версию';
+$lang['currentns'] = 'Текущее пространство имен';
+$lang['searchresult'] = 'Результаты поиска';
+$lang['plainhtml'] = 'Чистый HTML';
diff --git a/inc/lang/sk/lang.php b/inc/lang/sk/lang.php
index e8c1151d5..a5fc47f5f 100644
--- a/inc/lang/sk/lang.php
+++ b/inc/lang/sk/lang.php
@@ -327,3 +327,7 @@ $lang['media_perm_read'] = 'Prepáčte, ale nemáte dostatočné oprávnen
$lang['media_perm_upload'] = 'Prepáčte, ale nemáte dostatočné oprávnenie na nahrávanie súborov.';
$lang['media_update'] = 'Nahrať novú verziu';
$lang['media_restore'] = 'Obnoviť túto verziu';
+$lang['currentns'] = 'Aktuálny menný priestor';
+$lang['searchresult'] = 'Výsledky hľadania';
+$lang['plainhtml'] = 'Jednoduché HTML';
+$lang['wikimarkup'] = 'Wiki formát';
diff --git a/inc/lang/sl/lang.php b/inc/lang/sl/lang.php
index 2f69163f5..371b6659d 100644
--- a/inc/lang/sl/lang.php
+++ b/inc/lang/sl/lang.php
@@ -2,7 +2,7 @@
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- *
+ *
* @author Jaka Kranjc <lynxlupodian@hotmail.com>
* @author Boštjan Seničar <senicar@gmail.com>
* @author Dejan Levec <webphp@gmail.com>
@@ -195,6 +195,7 @@ $lang['user_tools'] = 'Uporabniška orodja';
$lang['site_tools'] = 'Orodja spletišča';
$lang['page_tools'] = 'Orodja strani';
$lang['skip_to_content'] = 'preskoči na vsebino';
+$lang['sidebar'] = 'Stranska vrstica';
$lang['mail_newpage'] = '[DokuWiki] stran dodana:';
$lang['mail_changed'] = '[DokuWiki] stran spremenjena:';
$lang['mail_subscribe_list'] = 'strani s spremenjenim imenom:';
@@ -284,6 +285,7 @@ $lang['i_policy'] = 'Začetna določila ACL';
$lang['i_pol0'] = 'Odprt Wiki (branje, zapis, nalaganje datotek je javno za vse)';
$lang['i_pol1'] = 'Javni Wiki (branje za vse, zapis in nalaganje datotek za prijavljene uporabnike)';
$lang['i_pol2'] = 'Zaprt Wiki (berejo in urejajo lahko le prijavljeni uporabniki)';
+$lang['i_allowreg'] = 'Dovoli uporabnikom vpis';
$lang['i_retry'] = 'Ponovni poskus';
$lang['i_license'] = 'Izbor dovoljenja objave vsebine:';
$lang['i_license_none'] = 'Ne pokaži podrobnosti dovoljenja.';
@@ -319,3 +321,6 @@ $lang['media_perm_read'] = 'Ni ustreznih dovoljenj za branje datotek.';
$lang['media_perm_upload'] = 'Ni ustreznih dovoljenj za nalaganje datotek.';
$lang['media_update'] = 'Naloži novo različico';
$lang['media_restore'] = 'Obnovi to različico';
+$lang['currentns'] = 'Trenutni imenski prostor';
+$lang['searchresult'] = 'Rezultati iskanja';
+$lang['plainhtml'] = 'Zapis HTML';
diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php
index 7d85f543e..8c8858f61 100644
--- a/inc/lang/sv/lang.php
+++ b/inc/lang/sv/lang.php
@@ -2,7 +2,7 @@
/**
* @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>
@@ -19,6 +19,7 @@
* @author Smorkster Andersson smorkster@gmail.com
* @author Henrik <henrik@idealis.se>
* @author Tor Härnqvist <tor.harnqvist@gmail.com>
+ * @author Hans Iwan Bratt <hibratt@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -148,6 +149,8 @@ $lang['js']['del_confirm'] = 'Vill du verkligen radera?';
$lang['js']['restore_confirm'] = 'Återställa denna version?';
$lang['js']['media_diff'] = 'Se skillnader:';
$lang['js']['media_diff_both'] = 'Sida vid sida';
+$lang['js']['media_diff_opacity'] = 'Genomskinlig';
+$lang['js']['media_diff_portions'] = 'Svep';
$lang['js']['media_select'] = 'Välj filer...';
$lang['js']['media_upload_btn'] = 'Ladda upp';
$lang['js']['media_done_btn'] = 'Färdig';
@@ -204,8 +207,10 @@ $lang['noflash'] = '<a href="http://www.adobe.com/products/flashpl
$lang['download'] = 'Ladda ner kodfragmentet';
$lang['tools'] = 'Verktyg';
$lang['user_tools'] = 'Användarverktyg';
+$lang['site_tools'] = 'Webbverktyg';
$lang['page_tools'] = 'Sidverktyg';
$lang['skip_to_content'] = 'hoppa till innehåll';
+$lang['sidebar'] = 'Sidmeny';
$lang['mail_newpage'] = 'sida tillagd:';
$lang['mail_changed'] = 'sida ändrad:';
$lang['mail_subscribe_list'] = 'sidor ändrade i namnrymd:';
@@ -298,6 +303,7 @@ $lang['i_policy'] = 'Initial ACL-policy';
$lang['i_pol0'] = 'Öppen wiki (alla får läsa, skriva och ladda upp filer)';
$lang['i_pol1'] = 'Publik wiki (alla får läsa, registrerade användare för skriva och ladda upp filer)';
$lang['i_pol2'] = 'Sluten wiki (endast registrerade användare får läsa, skriva och ladda upp filer)';
+$lang['i_allowreg'] = 'Tillåt användare att registrera sig själva';
$lang['i_retry'] = 'Försök igen';
$lang['i_license'] = 'Vänligen välj licens du vill använda för ditt innehåll:';
$lang['i_license_none'] = 'Visa ingen licensinformation';
@@ -335,3 +341,5 @@ $lang['media_perm_read'] = 'Du har tyvärr inte tillräckliga behörighete
$lang['media_perm_upload'] = 'Du har tyvärr inte tillräckliga behörigheter för att ladda upp filer.';
$lang['media_update'] = 'Ladda upp ny version';
$lang['media_restore'] = 'Återställ denna version';
+$lang['searchresult'] = 'Sökresultat';
+$lang['plainhtml'] = 'Ren HTML';
diff --git a/inc/lang/sv/subscr_digest.txt b/inc/lang/sv/subscr_digest.txt
new file mode 100644
index 000000000..6724726ac
--- /dev/null
+++ b/inc/lang/sv/subscr_digest.txt
@@ -0,0 +1,19 @@
+Hej
+
+Sidan @PAGE@ med @TITLE@ har ändrats.
+Här är ändringarna:
+
+-----------------------------
+@DIFF@
+-----------------------------
+
+Äldre versionen: @OLDPAGE@
+Ny version: @NEWPAGE@
+
+För att avbryta meddelanden om sidändringar logga in till wikin @DOKUWIKIURL@, besök sedan
+@SUBSCRIBE@
+och avbeställ ändringar av sidor och/eller namespace.
+
+--
+Detta meddelande har skapats av DokuWiki vid
+@DOKUWIKIURL@ \ No newline at end of file
diff --git a/inc/lang/vi/lang.php b/inc/lang/vi/lang.php
index c6b61da51..d8e40f875 100644
--- a/inc/lang/vi/lang.php
+++ b/inc/lang/vi/lang.php
@@ -1,42 +1,38 @@
<?php
+
/**
- * vietnamese language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- * @author James Do <jdo@myrealbox.com>
+ *
+ * @author James Do <jdo@myrealbox.com>
*/
-
-
-
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
-$lang['doublequoteopening'] = '“'; //&ldquo;
-$lang['doublequoteclosing'] = '”'; //&rdquo;
-$lang['singlequoteopening'] = '‘'; //&lsquo;
-$lang['singlequoteclosing'] = '’'; //&rsquo;
-$lang['apostrophe'] = '’'; //&rsquo;
-
-$lang['btn_edit'] = 'Biên soạn trang này';
-$lang['btn_source'] = 'Xem mã nguồn';
-$lang['btn_show'] = 'Xem trang';
-$lang['btn_create'] = 'Tạo trang này';
-$lang['btn_search'] = 'Tìm';
-$lang['btn_save'] = 'Lưu';
-$lang['btn_preview']= 'Duyệt trước';
-$lang['btn_top'] = 'Trở lên trên';
+$lang['doublequoteopening'] = '“';
+$lang['doublequoteclosing'] = '”';
+$lang['singlequoteopening'] = '‘';
+$lang['singlequoteclosing'] = '’';
+$lang['apostrophe'] = '’';
+$lang['btn_edit'] = 'Biên soạn trang này';
+$lang['btn_source'] = 'Xem mã nguồn';
+$lang['btn_show'] = 'Xem trang';
+$lang['btn_create'] = 'Tạo trang này';
+$lang['btn_search'] = 'Tìm';
+$lang['btn_save'] = 'Lưu';
+$lang['btn_preview'] = 'Duyệt trước';
+$lang['btn_top'] = 'Trở lên trên';
$lang['btn_newer'] = '<< mới hơn';
$lang['btn_older'] = 'cũ hơn >>';
-$lang['btn_revs'] = 'Các phiên bản cũ';
-$lang['btn_recent'] = 'Thay đổi gần đây';
-$lang['btn_upload'] = 'Tải lên';
-$lang['btn_cancel'] = 'Huỷ bỏ';
-$lang['btn_index'] = 'Mục lục';
-$lang['btn_secedit']= 'Biên soạn';
-$lang['btn_login'] = 'Đăng nhập';
-$lang['btn_logout'] = 'Thoát';
-$lang['btn_admin'] = 'Quản lý';
-$lang['btn_update'] = 'Cập nhật';
-$lang['btn_delete'] = 'Xoá';
+$lang['btn_revs'] = 'Các phiên bản cũ';
+$lang['btn_recent'] = 'Thay đổi gần đây';
+$lang['btn_upload'] = 'Tải lên';
+$lang['btn_cancel'] = 'Huỷ bỏ';
+$lang['btn_index'] = 'Mục lục';
+$lang['btn_secedit'] = 'Biên soạn';
+$lang['btn_login'] = 'Đăng nhập';
+$lang['btn_logout'] = 'Thoát';
+$lang['btn_admin'] = 'Quản lý';
+$lang['btn_update'] = 'Cập nhật';
+$lang['btn_delete'] = 'Xoá';
$lang['btn_back'] = 'Quay lại';
$lang['btn_backlink'] = 'Liên kết tới đây';
$lang['btn_profile'] = 'Cập nhật hồ sơ';
@@ -46,40 +42,36 @@ $lang['btn_draft'] = 'Sửa bản nháp';
$lang['btn_recover'] = 'Phục hồi bản nháp';
$lang['btn_draftdel'] = 'Xóa bản nháp';
$lang['btn_revert'] = 'Phục hồi';
-$lang['btn_register'] = 'Đăng ký';
+$lang['btn_register'] = 'Đăng ký';
$lang['btn_apply'] = 'Chấp nhận';
$lang['btn_media'] = 'Quản lý tệp tin';
-
-$lang['loggedinas'] = 'Username đang dùng';
-$lang['user'] = 'Username';
-$lang['pass'] = 'Mật khẩu';
+$lang['loggedinas'] = 'Username đang dùng';
+$lang['user'] = 'Username';
+$lang['pass'] = 'Mật khẩu';
$lang['newpass'] = 'Mật khẩu mới';
$lang['oldpass'] = 'Nhập lại mật khẩu hiện tại';
$lang['passchk'] = 'lần nữa';
-$lang['remember'] = 'Lưu username/password lại';
-$lang['fullname'] = 'Họ và tên';
-$lang['email'] = 'E-Mail';
+$lang['remember'] = 'Lưu username/password lại';
+$lang['fullname'] = 'Họ và tên';
+$lang['email'] = 'E-Mail';
$lang['profile'] = 'Hồ sơ thành viên';
-$lang['badlogin'] = 'Username hoặc password không đúng.';
+$lang['badlogin'] = 'Username hoặc password không đúng.';
$lang['minoredit'] = 'Minor Changes';
-$lang['draftdate'] = 'Bản nháp được tự động lưu lúc'; // full dformat date will be added
+$lang['draftdate'] = 'Bản nháp được tự động lưu lúc';
$lang['nosecedit'] = 'Các trang web đã được thay đổi trong khi chờ đợi, phần thông tin quá hạn đã được thay thế bằng trang đầy đủ.';
-
-$lang['regmissing'] = 'Bạn cần điền vào tất cả các trường';
-$lang['reguexists'] = 'Bạn khác đã dùng username này rồi.';
-$lang['regsuccess'] = 'Đã tạo username, và đã gởi password.';
+$lang['regmissing'] = 'Bạn cần điền vào tất cả các trường';
+$lang['reguexists'] = 'Bạn khác đã dùng username này rồi.';
+$lang['regsuccess'] = 'Đã tạo username, và đã gởi password.';
$lang['regsuccess2'] = 'Thành viên vừa được tạo.';
-$lang['regmailfail']= 'Không gởi password được. Xin bạn liên hệ với người quản lý.';
-$lang['regbadmail'] = 'Email hình như không đúng. Xin bạn liên hệ với người quản lý.';
+$lang['regmailfail'] = 'Không gởi password được. Xin bạn liên hệ với người quản lý.';
+$lang['regbadmail'] = 'Email hình như không đúng. Xin bạn liên hệ với người quản lý.';
$lang['regbadpass'] = 'Hai mật khẩu đưa ra là không giống nhau, xin vui lòng thử lại.';
-$lang['regpwmail'] = 'Password DokuWiki của bạn là';
-$lang['reghere'] = 'Xin bạn đăng ký username nếu chưa có';
-
+$lang['regpwmail'] = 'Password DokuWiki của bạn là';
+$lang['reghere'] = 'Xin bạn đăng ký username nếu chưa có';
$lang['profna'] = 'Wiki này không hỗ trợ sửa đổi hồ sơ cá nhân';
$lang['profnochange'] = 'Không có thay đổi, không có gì để làm.';
$lang['profnoempty'] = 'Không được để trống tên hoặc địa chỉ email.';
$lang['profchanged'] = 'Cập nhật hồ sơ thành viên thành công.';
-
$lang['pwdforget'] = 'Bạn quên mật khẩu? Tạo lại mật khẩu mới';
$lang['resendna'] = 'Wiki này không hỗ trợ gửi lại mật khẩu.';
$lang['resendpwd'] = 'Gửi mật khẩu mới cho';
@@ -88,20 +80,17 @@ $lang['resendpwdnouser'] = 'Xin lỗi, chúng tôi không thể tìm thấ
$lang['resendpwdbadauth'] = 'Xin lỗi, mã này xác thực không hợp lệ. Hãy chắc chắn rằng bạn sử dụng liên kết xác nhận đầy đủ.';
$lang['resendpwdconfirm'] = 'Một liên kết xác nhận đã được gửi bằng email.';
$lang['resendpwdsuccess'] = 'Mật khẩu mới của bạn đã được gửi bằng email.';
-
$lang['license'] = 'Trừ khi có ghi chú khác, nội dung trên wiki này được cấp phép theo giấy phép sau đây:';
$lang['licenseok'] = 'Lưu ý: Bằng cách chỉnh sửa trang này, bạn đồng ý cấp giấy phép nội dung của bạn theo giấy phép sau:';
-
$lang['searchmedia'] = 'Tìm tên file:';
$lang['searchmedia_in'] = 'Tìm ở %s';
-$lang['txt_upload'] = 'Chọn tệp để tải lên';
-$lang['txt_filename'] = 'Điền wikiname (tuỳ ý)';
+$lang['txt_upload'] = 'Chọn tệp để tải lên';
+$lang['txt_filename'] = 'Điền wikiname (tuỳ ý)';
$lang['txt_overwrt'] = 'Ghi đè file trùng';
-$lang['lockedby'] = 'Đang khoá bởi';
-$lang['lockexpire'] = 'Sẽ được mở khóa vào lúc';
-
-$lang['js']['willexpire'] = 'Trong một phút nữa bài viết sẽ được mở khóa để cho phép người khác chỉnh sửa.\nĐể tránh xung đột, bạn nên bấm nút Duyệt trước để lập lại thời gian khoá bài';
-$lang['js']['notsavedyet'] = 'Hiện có những thay đổi chưa được bảo lưu, và sẽ mất.\nBạn thật sự muốn tiếp tục?';
+$lang['lockedby'] = 'Đang khoá bởi';
+$lang['lockexpire'] = 'Sẽ được mở khóa vào lúc';
+$lang['js']['willexpire'] = 'Trong một phút nữa bài viết sẽ được mở khóa để cho phép người khác chỉnh sửa.\nĐể tránh xung đột, bạn nên bấm nút Duyệt trước để lập lại thời gian khoá bài';
+$lang['js']['notsavedyet'] = 'Hiện có những thay đổi chưa được bảo lưu, và sẽ mất.\nBạn thật sự muốn tiếp tục?';
$lang['js']['searchmedia'] = 'Tìm kiếm tập tin';
$lang['js']['keepopen'] = 'Giữ cửa sổ đang mở trên lựa chọn';
$lang['js']['hidedetails'] = 'Ẩn thông tin chi tiết';
@@ -126,29 +115,27 @@ $lang['js']['medialeft'] = 'Căn ảnh sang trái.';
$lang['js']['mediaright'] = 'Căn ảnh sang phải.';
$lang['js']['mediacenter'] = 'Cản ảnh ra giữa.';
$lang['js']['medianoalign'] = 'Không căn.';
-$lang['js']['nosmblinks'] = 'Nối với các Windows shares chỉ có hiệu lực với Microsoft Internet Explorer.\nBạn vẫn có thể sao và chép các mốc nối.';
+$lang['js']['nosmblinks'] = 'Nối với các Windows shares chỉ có hiệu lực với Microsoft Internet Explorer.\nBạn vẫn có thể sao và chép các mốc nối.';
$lang['js']['linkwiz'] = 'Hộp thoại liên kết';
$lang['js']['linkto'] = 'Liên kết tới:';
-$lang['js']['del_confirm']= 'Xoá mục này?';
+$lang['js']['del_confirm'] = 'Xoá mục này?';
$lang['js']['restore_confirm'] = 'Sẵn sàng phục hồi phiên bản này?';
-$lang['js']['media_diff'] = 'So sánh:';
-$lang['js']['media_select'] = 'Chọn nhiều file…';
-$lang['js']['media_upload_btn'] = 'Tải lên';
-$lang['js']['media_done_btn'] = 'Xong';
-$lang['js']['media_drop'] = 'Kéo các file vào đây để tải lên';
-$lang['js']['media_overwrt'] = 'Ghi đè các file trùng';
-
-$lang['rssfailed'] = 'Nguồn này gặp phải lỗi';
-$lang['nothingfound']= 'Không tìm được gì';
-
-$lang['mediaselect'] = 'Xem';
-$lang['fileupload'] = 'Tải lên tệp media';
-$lang['uploadsucc'] = 'Tải lên thành công';
-$lang['uploadfail'] = 'Tải lên thất bại. Có thể vì không đủ quyền?';
-$lang['uploadwrong'] = 'Tải lên bị từ chối. Cấm tải loại tệp này';
+$lang['js']['media_diff'] = 'So sánh:';
+$lang['js']['media_select'] = 'Chọn nhiều file…';
+$lang['js']['media_upload_btn'] = 'Tải lên';
+$lang['js']['media_done_btn'] = 'Xong';
+$lang['js']['media_drop'] = 'Kéo các file vào đây để tải lên';
+$lang['js']['media_overwrt'] = 'Ghi đè các file trùng';
+$lang['rssfailed'] = 'Nguồn này gặp phải lỗi';
+$lang['nothingfound'] = 'Không tìm được gì';
+$lang['mediaselect'] = 'Xem';
+$lang['fileupload'] = 'Tải lên tệp media';
+$lang['uploadsucc'] = 'Tải lên thành công';
+$lang['uploadfail'] = 'Tải lên thất bại. Có thể vì không đủ quyền?';
+$lang['uploadwrong'] = 'Tải lên bị từ chối. Cấm tải loại tệp này';
$lang['uploadexist'] = 'Tệp tin bị trùng. Chưa có gì xảy ra.';
-$lang['namespaces'] = 'Thư mục';
-$lang['mediafiles'] = 'Tệp có sẵn ở';
+$lang['namespaces'] = 'Thư mục';
+$lang['mediafiles'] = 'Tệp có sẵn ở';
$lang['accessdenied'] = 'Bạn không được phép xem trang này.';
$lang['mediausage'] = 'Sử dụng cú pháp sau đây để dẫn đến tập tin này:';
$lang['mediaview'] = 'Xem tệp gốc';
@@ -157,56 +144,51 @@ $lang['mediaupload'] = 'Tải một tập tin lên thư mục hiện t
$lang['mediaextchange'] = 'Phần mở rộng thay đổi từ .%s thành .%s!';
$lang['ref_inuse'] = 'Không thể xóa tập tin vì nó đang được sử dụng cho các trang sau:';
$lang['ref_hidden'] = 'Một số tài liệu sử dụng cho trang này bạn không được cấp phép truy cập.';
-
-$lang['hits'] = 'Trùng';
-$lang['quickhits'] = 'Trang trùng hợp';
-$lang['toc'] = 'Nội dung';
-$lang['current'] = 'hiện tại';
-$lang['yours'] = 'Phiên bản hiện tại';
-$lang['diff'] = 'cho xem khác biệt với phiên bản hiện tại';
+$lang['hits'] = 'Trùng';
+$lang['quickhits'] = 'Trang trùng hợp';
+$lang['toc'] = 'Nội dung';
+$lang['current'] = 'hiện tại';
+$lang['yours'] = 'Phiên bản hiện tại';
+$lang['diff'] = 'cho xem khác biệt với phiên bản hiện tại';
$lang['diff2'] = 'Sự khác biệt giữa các bản được lựa chọn';
$lang['difflink'] = 'Liên kết để xem bản so sánh này';
$lang['diff_type'] = 'Xem sự khác biệt:';
$lang['diff_inline'] = 'Nội tuyến';
$lang['diff_side'] = 'Xếp cạnh nhau';
-$lang['line'] = 'Dòng';
-$lang['breadcrumb'] = 'Trang đã xem';
+$lang['line'] = 'Dòng';
+$lang['breadcrumb'] = 'Trang đã xem';
$lang['youarehere'] = 'Bạn đang ở đây';
-$lang['lastmod'] = 'Thời điểm thay đổi';
-$lang['by'] = 'do';
-$lang['deleted'] = 'bị xoá';
-$lang['created'] = 'được tạo ra';
-$lang['restored'] = 'phiên bản cũ đã được khôi phục (%s)';
+$lang['lastmod'] = 'Thời điểm thay đổi';
+$lang['by'] = 'do';
+$lang['deleted'] = 'bị xoá';
+$lang['created'] = 'được tạo ra';
+$lang['restored'] = 'phiên bản cũ đã được khôi phục (%s)';
$lang['external_edit'] = 'external edit';
-$lang['summary'] = 'Tóm tắt biên soạn';
+$lang['summary'] = 'Tóm tắt biên soạn';
$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> cần được cài để có thể xem nội dung này.';
-
-$lang['mail_newpage'] = 'Trang được thêm:';
-$lang['mail_changed'] = 'Trang thay đổi:';
-
+$lang['mail_newpage'] = 'Trang được thêm:';
+$lang['mail_changed'] = 'Trang thay đổi:';
$lang['changes_type'] = 'Xem thay đổi của';
$lang['pages_changes'] = 'Trang';
$lang['media_changes'] = 'Tệp media';
$lang['both_changes'] = 'Cả trang và các tập tin media';
-
-$lang['qb_bold'] = 'Chữ đậm';
-$lang['qb_italic'] = 'Chữ nghiêng';
-$lang['qb_underl'] = 'Chữ gạch dưới';
-$lang['qb_code'] = 'Chữ mã nguồn';
+$lang['qb_bold'] = 'Chữ đậm';
+$lang['qb_italic'] = 'Chữ nghiêng';
+$lang['qb_underl'] = 'Chữ gạch dưới';
+$lang['qb_code'] = 'Chữ mã nguồn';
$lang['qb_strike'] = 'Strike-through Text';
-$lang['qb_h1'] = 'Đầu đề cấp 1';
-$lang['qb_h2'] = 'Đầu đề cấp 2';
-$lang['qb_h3'] = 'Đầu đề cấp 3';
-$lang['qb_h4'] = 'Đầu đề cấp 4';
-$lang['qb_h5'] = 'Đầu đề cấp 5';
-$lang['qb_link'] = 'Mốc nối nội tại';
-$lang['qb_extlink'] = 'Mốc nối ra ngoài';
-$lang['qb_hr'] = 'Gạch ngang';
-$lang['qb_ol'] = 'Điểm trong danh sách có thứ tự';
-$lang['qb_ul'] = 'Điểm trong danh sách không đánh số';
-$lang['qb_media'] = 'Thêm ảnh và tệp khác';
-$lang['qb_sig'] = 'Đặt chữ ký';
-
+$lang['qb_h1'] = 'Đầu đề cấp 1';
+$lang['qb_h2'] = 'Đầu đề cấp 2';
+$lang['qb_h3'] = 'Đầu đề cấp 3';
+$lang['qb_h4'] = 'Đầu đề cấp 4';
+$lang['qb_h5'] = 'Đầu đề cấp 5';
+$lang['qb_link'] = 'Mốc nối nội tại';
+$lang['qb_extlink'] = 'Mốc nối ra ngoài';
+$lang['qb_hr'] = 'Gạch ngang';
+$lang['qb_ol'] = 'Điểm trong danh sách có thứ tự';
+$lang['qb_ul'] = 'Điểm trong danh sách không đánh số';
+$lang['qb_media'] = 'Thêm ảnh và tệp khác';
+$lang['qb_sig'] = 'Đặt chữ ký';
$lang['metaedit'] = 'Sửa Metadata';
$lang['metasaveerr'] = 'Thất bại khi viết metadata';
$lang['metasaveok'] = 'Metadata đã được lưu';
@@ -224,11 +206,8 @@ $lang['img_keywords'] = 'Từ khóa';
$lang['img_width'] = 'Rộng';
$lang['img_height'] = 'Cao';
$lang['img_manager'] = 'Xem trong trình quản lý tệp media';
-
-/* installer strings */
$lang['i_chooselang'] = 'Chọn ngôn ngữ';
$lang['i_retry'] = 'Thử lại';
-
$lang['years'] = 'cách đây %d năm';
$lang['months'] = 'cách đây %d tháng';
$lang['weeks'] = 'cách đây %d tuần';
@@ -236,9 +215,7 @@ $lang['days'] = 'cách đây %d ngày';
$lang['hours'] = 'cách đây %d giờ';
$lang['minutes'] = 'cách đây %d phút';
$lang['seconds'] = 'cách đây %d giây';
-
$lang['wordblock'] = 'Thay đổi của bạn đã không được lưu lại bởi vì nó có chứa văn bản bị chặn (spam).';
-
$lang['media_uploadtab'] = 'Tải lên';
$lang['media_searchtab'] = 'Tìm';
$lang['media_file'] = 'Tệp';
@@ -262,5 +239,3 @@ $lang['media_perm_read'] = 'Sorry, bạn không đủ quyền truy cập.'
$lang['media_perm_upload'] = 'Xin lỗi, bạn không đủ quyền để upload file lên.';
$lang['media_update'] = 'Tải lên phiên bản mới';
$lang['media_restore'] = 'Phục hồi phiên bản này';
-
-//Setup VIM: ex: et ts=2 :
diff --git a/inc/lang/zh-tw/lang.php b/inc/lang/zh-tw/lang.php
index 176121881..456377810 100644
--- a/inc/lang/zh-tw/lang.php
+++ b/inc/lang/zh-tw/lang.php
@@ -8,11 +8,11 @@
* @author http://www.chinese-tools.com/tools/converter-simptrad.html
* @author Wayne San <waynesan@zerozone.tw>
* @author Cheng-Wei Chien <e.cwchien@gmail.com>
- * @author Danny Lin
* @author Shuo-Ting Jian <shoting@gmail.com>
* @author syaoranhinata@gmail.com
* @author Ichirou Uchiki <syaoranhinata@gmail.com>
* @author tsangho <ou4222@gmail.com>
+ * @author Danny Lin <danny0838@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -81,15 +81,17 @@ $lang['regbadmail'] = '您輸入的電郵地址似乎不正確。若
$lang['regbadpass'] = '兩次輸入的密碼不一致,請再試一次。';
$lang['regpwmail'] = '您的 DokuWiki 帳號密碼';
$lang['reghere'] = '您還沒有帳號嗎?註冊一個吧。';
-$lang['profna'] = '在本 wiki 上,不能修改個人資料。';
+$lang['profna'] = '本 wiki 不支援修改個人資料。';
$lang['profnochange'] = '並未作任何變更。';
$lang['profnoempty'] = '帳號或電郵地址不可空白!';
$lang['profchanged'] = '個人資料已更新。';
-$lang['profnodelete'] = '這一wiki不支援刪除用戶';
+$lang['profnodelete'] = '本 wiki 不支援刪除使用者';
$lang['profdeleteuser'] = '刪除帳號';
-$lang['profdeleted'] = '您在這wiki中的用戶帳號已經被刪除';
+$lang['profdeleted'] = '您的使用者帳號已從本 wiki 刪除';
+$lang['profconfdelete'] = '我想把帳號從本 wiki 刪除(不能復原)';
+$lang['profconfdeletemissing'] = '未勾選確認方塊';
$lang['pwdforget'] = '忘記密碼了?索取新密碼!';
-$lang['resendna'] = '本 wiki 並不支援重寄密碼。';
+$lang['resendna'] = '本 wiki 不支援重寄密碼。';
$lang['resendpwd'] = '設定新密碼供';
$lang['resendpwdmissing'] = '抱歉,您必須填寫所有欄位。';
$lang['resendpwdnouser'] = '抱歉,資料庫內找不到這個使用者。';
@@ -97,7 +99,7 @@ $lang['resendpwdbadauth'] = '抱歉,認證碼無效。請確認您使用
$lang['resendpwdconfirm'] = '確認連結已通過郵件發送給您了。';
$lang['resendpwdsuccess'] = '您的新密碼已寄出。';
$lang['license'] = '若無特別註明,本 wiki 上的內容都是採用以下授權方式:';
-$lang['licenseok'] = '注意:編輯此頁面表示您已同意以下的授權方式:';
+$lang['licenseok'] = '注意:編輯此頁面表示您同意用以下授權方式發布您撰寫的內容:';
$lang['searchmedia'] = '搜尋檔名:';
$lang['searchmedia_in'] = '在 %s 裏搜尋';
$lang['txt_upload'] = '請選擇要上傳的檔案';
@@ -232,7 +234,7 @@ $lang['qb_extlink'] = '外部連結';
$lang['qb_hr'] = '水平線';
$lang['qb_ol'] = '有序列表項目';
$lang['qb_ul'] = '無序列表項目';
-$lang['qb_media'] = '加入圖片或檔案';
+$lang['qb_media'] = '加入圖片或檔案 (開新視窗)';
$lang['qb_sig'] = '插入簽名';
$lang['qb_smileys'] = '表情符號';
$lang['qb_chars'] = '特殊字元';
@@ -271,6 +273,8 @@ $lang['subscr_m_receive'] = '接收';
$lang['subscr_style_every'] = '每次更改都發送信件';
$lang['subscr_style_digest'] = '對每個頁面發送更改的摘要信件 (每 %.2f 天)';
$lang['subscr_style_list'] = '自上次發信以來更改的頁面的列表 (每 %.2f 天)';
+
+/* auth.class language support */
$lang['authtempfail'] = '暫不提供帳號認證。若本狀況持續,請通知本 wiki 管理員。';
$lang['authpwdexpire'] = '您的密碼將在 %d 天內到期,請馬上更換新密碼。';
$lang['i_chooselang'] = '選擇您的語系';
@@ -332,3 +336,8 @@ $lang['media_perm_read'] = '抱歉,您沒有足夠權限讀取檔案。'
$lang['media_perm_upload'] = '抱歉,您沒有足夠權限上傳檔案。';
$lang['media_update'] = '上傳新的版本';
$lang['media_restore'] = '還原這個版本';
+
+$lang['currentns'] = '目前的命名空間';
+$lang['searchresult'] = '搜尋結果';
+$lang['plainhtml'] = '純 HTML';
+$lang['wikimarkup'] = 'Wiki 語法標記';
diff --git a/inc/lang/zh/lang.php b/inc/lang/zh/lang.php
index a125e11e7..004997d6e 100644
--- a/inc/lang/zh/lang.php
+++ b/inc/lang/zh/lang.php
@@ -18,6 +18,8 @@
* @author Rachel <rzhang0802@gmail.com>
* @author Donald <donaldtcong@gmail.com>
* @author Yangyu Huang <yangyu.huang@gmail.com>
+ * @author anjianshi <anjianshi@gmail.com>
+ * @author oott123 <ip.192.168.1.1@qq.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@@ -33,7 +35,7 @@ $lang['btn_create'] = '创建该页面';
$lang['btn_search'] = '搜索';
$lang['btn_save'] = '保存';
$lang['btn_preview'] = '预览';
-$lang['btn_top'] = '到顶部';
+$lang['btn_top'] = '回到顶部';
$lang['btn_newer'] = '<< 较新的';
$lang['btn_older'] = '较旧的 >>';
$lang['btn_revs'] = '修订记录';
@@ -77,7 +79,7 @@ $lang['badpassconfirm'] = '对不起,密码错误';
$lang['minoredit'] = '细微修改';
$lang['draftdate'] = '草稿自动保存于';
$lang['nosecedit'] = '在您编辑期间本页刚被他人修改过,局部信息已过期,故载入全页。';
-$lang['regmissing'] = '对不起,您必须填写所有的区域。';
+$lang['regmissing'] = '对不起,您必须填写所有的字段。';
$lang['reguexists'] = '对不起,该用户名已经存在。';
$lang['regsuccess'] = '新用户已建立,密码将通过电子邮件发送给您。';
$lang['regsuccess2'] = '新用户已建立';
@@ -86,7 +88,7 @@ $lang['regbadmail'] = '您输入的邮件地址有问题——如果
$lang['regbadpass'] = '您输入的密码与系统产生的不符,请重试。';
$lang['regpwmail'] = '您的 DokuWiki 密码';
$lang['reghere'] = '还没有账号?立即注册';
-$lang['profna'] = '本维基不支持修改个人信息';
+$lang['profna'] = '本维基不允许修改个人信息';
$lang['profnochange'] = '没有改动,不进行操作。';
$lang['profnoempty'] = '不允许使用空的用户名或邮件地址。';
$lang['profchanged'] = '用户信息更新成功。';
@@ -305,6 +307,7 @@ $lang['i_policy'] = '初始的 ACL 政策';
$lang['i_pol0'] = '开放的维基(任何人都有读、写、上传的权限)';
$lang['i_pol1'] = '公共的维基(任何人都有读的权限,只有注册用户才有写和上传的权限)';
$lang['i_pol2'] = '关闭的维基(只有注册用户才有读、写、上传的权限)';
+$lang['i_allowreg'] = '允许用户自行注册';
$lang['i_retry'] = '重试';
$lang['i_license'] = '请选择您希望的内容发布许可协议:';
$lang['i_license_none'] = '不要显示任何许可协议信息';
@@ -342,3 +345,7 @@ $lang['media_perm_read'] = '抱歉,您没有足够权限读取这些文
$lang['media_perm_upload'] = '抱歉,您没有足够权限来上传文件。';
$lang['media_update'] = '上传新版本';
$lang['media_restore'] = '恢复这个版本';
+$lang['currentns'] = '当前命名空间';
+$lang['searchresult'] = '搜索结果';
+$lang['plainhtml'] = '纯HTML';
+$lang['wikimarkup'] = 'Wiki Markup 语言';
diff --git a/inc/media.php b/inc/media.php
index d45b2a91d..2943e8274 100644
--- a/inc/media.php
+++ b/inc/media.php
@@ -90,7 +90,7 @@ function media_metasave($id,$auth,$data){
* @return bool
*/
function media_isexternal($id){
- if (preg_match('#^(https?|ftp)://#i', $id)) return true;
+ if (preg_match('#^(?:https?|ftp)://#i', $id)) return true;
return false;
}
@@ -115,7 +115,7 @@ function media_ispublic($id){
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function media_metaform($id,$auth){
- global $lang, $config_cascade;
+ global $lang;
if($auth < AUTH_UPLOAD) {
echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.NL;
@@ -167,6 +167,8 @@ function media_metaform($id,$auth){
$form->addElement(form_makeButton('submit', '', $lang['btn_save'], array('accesskey' => 's', 'name' => 'mediado[save]')));
$form->addElement('</div>'.NL);
$form->printForm();
+
+ return true;
}
/**
@@ -176,7 +178,7 @@ function media_metaform($id,$auth){
*/
function media_inuse($id) {
global $conf;
- $mediareferences = array();
+
if($conf['refcheck']){
$mediareferences = ft_mediause($id,true);
if(!count($mediareferences)) {
@@ -199,7 +201,9 @@ define('DOKU_MEDIA_EMPTY_NS', 8);
*
* If configured, checks for media references before deletion
*
- * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $id media id
+ * @param int $auth current auth check result
* @return int One of: 0,
* DOKU_MEDIA_DELETED,
* DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS,
@@ -248,6 +252,8 @@ function media_delete($id,$auth){
/**
* Handle file uploads via XMLHttpRequest
*
+ * @param string $ns target namespace
+ * @param int $auth current auth check result
* @return mixed false on error, id of the new file on success
*/
function media_upload_xhr($ns,$auth){
@@ -255,7 +261,7 @@ function media_upload_xhr($ns,$auth){
global $INPUT;
$id = $INPUT->get->str('qqfile');
- list($ext,$mime,$dl) = mimetype($id);
+ list($ext,$mime) = mimetype($id);
$input = fopen("php://input", "r");
if (!($tmp = io_mktmpdir())) return false;
$path = $tmp.'/'.md5($id);
@@ -291,6 +297,9 @@ function media_upload_xhr($ns,$auth){
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michael Klier <chi@chimeric.de>
+ * @param string $ns target namespace
+ * @param int $auth current auth check result
+ * @param bool|array $file $_FILES member, $_FILES['upload'] if false
* @return mixed false on error, id of the new file on success
*/
function media_upload($ns,$auth,$file=false){
@@ -307,8 +316,8 @@ function media_upload($ns,$auth,$file=false){
if($file['error']) return false;
// check extensions
- list($fext,$fmime,$dl) = mimetype($file['name']);
- list($iext,$imime,$dl) = mimetype($id);
+ list($fext,$fmime) = mimetype($file['name']);
+ list($iext,$imime) = mimetype($id);
if($fext && !$iext){
// no extension specified in id - read original one
$id .= '.'.$fext;
@@ -563,10 +572,10 @@ function media_contentcheck($file,$mime){
*/
function media_notify($id,$file,$mime,$old_rev=false){
global $conf;
- if(empty($conf['notify'])) return; //notify enabled?
+ if(empty($conf['notify'])) return false; //notify enabled?
$subscription = new Subscription();
- return $subscription->send_media_diff($conf['notify'], 'uploadmail', $id, $old_rev, '');
+ return $subscription->send_media_diff($conf['notify'], 'uploadmail', $id, $old_rev);
}
/**
@@ -640,7 +649,8 @@ function media_tabs_files($selected_tab = ''){
* Prints tabs for files details actions
*
* @author Kate Arzamastseva <pshns@ukr.net>
- * @param string $selected_tab - opened tab
+ * @param string $image filename of the current image
+ * @param string $selected_tab opened tab
*/
function media_tabs_details($image, $selected_tab = ''){
global $lang, $conf;
@@ -649,7 +659,7 @@ function media_tabs_details($image, $selected_tab = ''){
$tabs['view'] = array('href' => media_managerURL(array('tab_details' => 'view'), '&'),
'caption' => $lang['media_viewtab']);
- list($ext, $mime) = mimetype($image);
+ list(, $mime) = mimetype($image);
if ($mime == 'image/jpeg' && @file_exists(mediaFN($image))) {
$tabs['edit'] = array('href' => media_managerURL(array('tab_details' => 'edit'), '&'),
'caption' => $lang['media_edittab']);
@@ -669,7 +679,6 @@ function media_tabs_details($image, $selected_tab = ''){
*/
function media_tab_files_options(){
global $lang;
- global $NS;
global $INPUT;
global $ID;
$form = new Doku_Form(array('class' => 'options', 'method' => 'get',
@@ -776,7 +785,6 @@ function media_tab_upload($ns,$auth=null,$jump='') {
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function media_tab_search($ns,$auth=null) {
- global $lang;
global $INPUT;
$do = $INPUT->str('mediado');
@@ -796,7 +804,7 @@ function media_tab_search($ns,$auth=null) {
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function media_tab_view($image, $ns, $auth=null, $rev=false) {
- global $lang, $conf;
+ global $lang;
if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
if ($image && $auth >= AUTH_READ) {
@@ -816,11 +824,10 @@ function media_tab_view($image, $ns, $auth=null, $rev=false) {
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function media_tab_edit($image, $ns, $auth=null) {
- global $lang;
if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
if ($image) {
- list($ext, $mime) = mimetype($image);
+ list(, $mime) = mimetype($image);
if ($mime == 'image/jpeg') media_metaform($image,$auth);
}
}
@@ -935,9 +942,10 @@ function media_preview_buttons($image, $auth, $rev=false) {
* Returns image width and height for mediamanager preview panel
*
* @author Kate Arzamastseva <pshns@ukr.net>
- * @param string $image
- * @param int $rev
+ * @param string $image
+ * @param int $rev
* @param JpegMeta $meta
+ * @param int $size
* @return array
*/
function media_image_preview_size($image, $rev, $meta, $size = 500) {
@@ -979,8 +987,6 @@ function media_getTag($tags,$meta,$alt=''){
* @return array
*/
function media_file_tags($meta) {
- global $config_cascade;
-
// load the field descriptions
static $fields = null;
if(is_null($fields)){
@@ -1107,13 +1113,12 @@ function _media_file_diff($data) {
*/
function media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax){
global $lang;
- global $config_cascade;
global $INPUT;
$l_meta = new JpegMeta(mediaFN($image, $l_rev));
$r_meta = new JpegMeta(mediaFN($image, $r_rev));
- $is_img = preg_match("/\.(jpe?g|gif|png)$/", $image);
+ $is_img = preg_match('/\.(jpe?g|gif|png)$/', $image);
if ($is_img) {
$l_size = media_image_preview_size($image, $l_rev, $l_meta);
$r_size = media_image_preview_size($image, $r_rev, $r_meta);
@@ -1140,7 +1145,7 @@ function media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax){
if ($difftype == 'opacity' || $difftype == 'portions') {
media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $difftype);
if (!$fromajax) echo '</div>';
- return '';
+ return;
}
}
@@ -1274,7 +1279,7 @@ function media_restore($image, $rev, $auth){
$removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes')));
if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false;
if (!$rev || !file_exists(mediaFN($image, $rev))) return false;
- list($iext,$imime,$dl) = mimetype($image);
+ list(,$imime,) = mimetype($image);
$res = media_upload_finish(mediaFN($image, $rev),
mediaFN($image),
$image,
@@ -1364,7 +1369,7 @@ function media_printfile($item,$auth,$jump,$display_namespace=false){
}
// Prepare fileicons
- list($ext,$mime,$dl) = mimetype($item['file'],false);
+ list($ext) = mimetype($item['file'],false);
$class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext);
$class = 'select mediafile mf_'.$class;
@@ -1420,7 +1425,7 @@ function media_printfile($item,$auth,$jump,$display_namespace=false){
}
function media_printicon($filename){
- list($ext,$mime,$dl) = mimetype(mediaFN($filename),false);
+ list($ext) = mimetype(mediaFN($filename),false);
if (@file_exists(DOKU_INC.'lib/images/fileicons/'.$ext.'.png')) {
$icon = DOKU_BASE.'lib/images/fileicons/'.$ext.'.png';
@@ -1438,8 +1443,6 @@ function media_printicon($filename){
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function media_printfile_thumbs($item,$auth,$jump=false,$display_namespace=false){
- global $lang;
- global $conf;
// Prepare filename
$file = utf8_decodeFN($item['file']);
@@ -1484,7 +1487,7 @@ function media_printfile_thumbs($item,$auth,$jump=false,$display_namespace=false
}
/**
- * Prints a thumbnail and metainfos
+ * Prints a thumbnail and metainfo
*/
function media_printimgdetail($item, $fullscreen=false){
// prepare thumbnail
@@ -1552,12 +1555,13 @@ function media_printimgdetail($item, $fullscreen=false){
* parameters
*
* @author Kate Arzamastseva <pshns@ukr.net>
- * @param array $params
- * @param string $amp - separator
+ * @param array|bool $params
+ * @param string $amp - separator
+ * @param bool $abs
+ * @param bool $params_array
* @return string - link
*/
function media_managerURL($params=false, $amp='&amp;', $abs=false, $params_array=false) {
- global $conf;
global $ID;
global $INPUT;
diff --git a/inc/pageutils.php b/inc/pageutils.php
index 60f326e04..c8d3cf4bb 100644
--- a/inc/pageutils.php
+++ b/inc/pageutils.php
@@ -94,9 +94,8 @@ function getID($param='id',$clean=true){
* @author Andreas Gohr <andi@splitbrain.org>
* @param string $raw_id The pageid to clean
* @param boolean $ascii Force ASCII
- * @param boolean $media DEPRECATED
*/
-function cleanID($raw_id,$ascii=false,$media=false){
+function cleanID($raw_id,$ascii=false){
global $conf;
static $sepcharpat = null;
diff --git a/inc/parser/parser.php b/inc/parser/parser.php
index e39a4daf5..1f14b98a3 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('\s*\n\^',$mode,'table');
- $this->Lexer->addEntryPattern('\s*\n\|',$mode,'table');
+ $this->Lexer->addEntryPattern('[\t ]*\n\^',$mode,'table');
+ $this->Lexer->addEntryPattern('[\t ]*\n\|',$mode,'table');
}
function postConnect() {
diff --git a/inc/parser/renderer.php b/inc/parser/renderer.php
index c697e990c..e3401fd48 100644
--- a/inc/parser/renderer.php
+++ b/inc/parser/renderer.php
@@ -59,9 +59,15 @@ class Doku_Renderer extends DokuWiki_Plugin {
return false;
}
-
- //handle plugin rendering
- function plugin($name,$data){
+ /**
+ * handle plugin rendering
+ *
+ * @param string $name Plugin name
+ * @param mixed $data custom data set by handler
+ * @param string $state matched state if any
+ * @param string $match raw matched syntax
+ */
+ function plugin($name,$data,$state='',$match=''){
$plugin = plugin_load('syntax',$name);
if($plugin != null){
$plugin->render($this->getFormat(),$this,$data);
diff --git a/inc/parserutils.php b/inc/parserutils.php
index b67daaabb..4df273f11 100644
--- a/inc/parserutils.php
+++ b/inc/parserutils.php
@@ -158,6 +158,8 @@ function p_cached_instructions($file,$cacheonly=false,$id='') {
*
* @author Harry Fuecks <hfuecks@gmail.com>
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $text raw wiki syntax text
+ * @return array a list of instruction arrays
*/
function p_get_instructions($text){
diff --git a/inc/template.php b/inc/template.php
index 41f398016..60e178d1a 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -1694,18 +1694,6 @@ function tpl_includeFile($file) {
}
/**
- * Returns icon from data/media root directory if it exists, otherwise
- * the one in the template's image directory.
- *
- * @deprecated Use tpl_getMediaFile() instead
- * @author Anika Henke <anika@selfthinker.org>
- */
-function tpl_getFavicon($abs = false, $fileName = 'favicon.ico') {
- $look = array(":wiki:$fileName", ":$fileName", "images/$fileName");
- return tpl_getMediaFile($look, $abs);
-}
-
-/**
* Returns <link> tag for various icon types (favicon|mobile|generic)
*
* @author Anika Henke <anika@selfthinker.org>
diff --git a/install.php b/install.php
index 82a47b037..779084cfa 100644
--- a/install.php
+++ b/install.php
@@ -56,7 +56,7 @@ $dokuwiki_hash = array(
'2012-01-25' => '72c083c73608fc43c586901fd5dabb74',
'2012-09-10' => 'eb0b3fc90056fbc12bac6f49f7764df3',
'2013-05-10' => '7b62b75245f57f122d3e0f8ed7989623',
- '2013-10-28' => '263c76af309fbf083867c18a34ff5214',
+ '2013-12-08' => '263c76af309fbf083867c18a34ff5214',
);
@@ -207,6 +207,10 @@ function print_form($d){
<option value="2" <?php echo ($d['policy'] == 2)?'selected="selected"':'' ?>><?php echo $lang['i_pol2']?></option>
</select>
+ <label for="allowreg">
+ <input type="checkbox" name="d[allowreg]" id="allowreg" <?php echo(($d['allowreg'] ? ' checked="checked"' : ''));?> />
+ <?php echo $lang['i_allowreg']?>
+ </label>
</fieldset>
</fieldset>
@@ -270,6 +274,7 @@ function check_data(&$d){
'password' => '',
'confirm' => '',
'policy' => '0',
+ 'allowreg' => '0',
'license' => 'cc-by-sa'
);
global $lang;
@@ -351,6 +356,9 @@ EOT;
$output .= '$conf[\'useacl\'] = 1'.";\n";
$output .= "\$conf['superuser'] = '@admin';\n";
}
+ if(!$d['allowreg']){
+ $output .= '$conf[\'disableactions\'] = \'register\''.";\n";
+ }
$ok = $ok && fileWrite(DOKU_LOCAL.'local.php',$output);
if ($d['acl']) {
diff --git a/lib/exe/css.php b/lib/exe/css.php
index 6dfdf06e8..c96dedd37 100644
--- a/lib/exe/css.php
+++ b/lib/exe/css.php
@@ -84,16 +84,6 @@ function css_out(){
if(isset($config_cascade['userstyle'][$mediatype])){
$files[$mediatype][$config_cascade['userstyle'][$mediatype]] = DOKU_BASE;
}
- // load rtl styles
- // note: this adds the rtl styles only to the 'screen' media type
- // @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
- if ($mediatype=='screen') {
- if($lang['direction'] == 'rtl'){
- if (isset($styleini['stylesheets']['rtl'])) $files[$mediatype] = array_merge($files[$mediatype], $styleini['stylesheets']['rtl']);
- if (isset($config_cascade['userstyle']['rtl'])) $files[$mediatype][$config_cascade['userstyle']['rtl']] = DOKU_BASE;
- }
- }
$cache_files = array_merge($cache_files, array_keys($files[$mediatype]));
}
@@ -173,6 +163,12 @@ function css_out(){
*/
function css_parseless($css) {
$less = new lessc();
+ $less->importDir[] = DOKU_INC;
+
+ if (defined('DOKU_UNITTEST')){
+ $less->importDir[] = TMP_DIR;
+ }
+
try {
return $less->compile($css);
} catch(Exception $e) {
@@ -271,7 +267,7 @@ function css_styleini($tpl) {
// replacements
if(is_array($data['replacements'])){
- $replacements = array_merge($replacements, $data['replacements']);
+ $replacements = array_merge($replacements, css_fixreplacementurls($data['replacements'],$webbase));
}
}
@@ -288,7 +284,7 @@ function css_styleini($tpl) {
// replacements
if(is_array($data['replacements'])){
- $replacements = array_merge($replacements, $data['replacements']);
+ $replacements = array_merge($replacements, css_fixreplacementurls($data['replacements'],$webbase));
}
}
@@ -306,7 +302,7 @@ function css_styleini($tpl) {
// replacements
if(is_array($data['replacements'])){
- $replacements = array_merge($replacements, $data['replacements']);
+ $replacements = array_merge($replacements, css_fixreplacementurls($data['replacements'],$webbase));
}
}
@@ -317,6 +313,18 @@ function css_styleini($tpl) {
}
/**
+ * Amend paths used in replacement relative urls, refer FS#2879
+ *
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+function css_fixreplacementurls($replacements, $location) {
+ foreach($replacements as $key => $value) {
+ $replacements[$key] = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$value);
+ }
+ return $replacements;
+}
+
+/**
* Prints classes for interwikilinks
*
* Interwiki links have two classes: 'interwiki' and 'iw_$name>' where
@@ -393,18 +401,99 @@ function css_filetypes(){
* given location prefix
*/
function css_loadfile($file,$location=''){
- if(!@file_exists($file)) return '';
- $css = io_readFile($file);
- if(!$location) return $css;
+ $css_file = new DokuCssFile($file);
+ return $css_file->load($location);
+}
+
+/**
+ * Helper class to abstract loading of css/less files
+ *
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+class DokuCssFile {
- $css = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$css);
- $css = preg_replace('#(@import\s+[\'"])(?!/|data:|http://|https://)#', '\\1'.$location, $css);
+ protected $filepath; // file system path to the CSS/Less file
+ protected $location; // base url location of the CSS/Less file
+ private $relative_path = null;
- return $css;
+ public function __construct($file) {
+ $this->filepath = $file;
+ }
+
+ /**
+ * Load the contents of the css/less file and adjust any relative paths/urls (relative to this file) to be
+ * relative to the dokuwiki root: the web root (DOKU_BASE) for most files; the file system root (DOKU_INC)
+ * for less files.
+ *
+ * @param string $location base url for this file
+ * @return string the CSS/Less contents of the file
+ */
+ public function load($location='') {
+ if (!@file_exists($this->filepath)) return '';
+
+ $css = io_readFile($this->filepath);
+ if (!$location) return $css;
+
+ $this->location = $location;
+
+ $css = preg_replace_callback('#(url\( *)([\'"]?)(.*?)(\2)( *\))#',array($this,'replacements'),$css);
+ $css = preg_replace_callback('#(@import\s+)([\'"])(.*?)(\2)#',array($this,'replacements'),$css);
+
+ return $css;
+ }
+
+ /**
+ * Get the relative file system path of this file, relative to dokuwiki's root folder, DOKU_INC
+ *
+ * @return string relative file system path
+ */
+ private function getRelativePath(){
+
+ if (is_null($this->relative_path)) {
+ $basedir = array(DOKU_INC);
+
+ // during testing, files may be found relative to a second base dir, TMP_DIR
+ if (defined('DOKU_UNITTEST')) {
+ $basedir[] = realpath(TMP_DIR);
+ }
+ $regex = '#^('.join('|',$basedir).')#';
+
+ $this->relative_path = preg_replace($regex, '', dirname($this->filepath));
+ }
+
+ return $this->relative_path;
+ }
+
+ /**
+ * preg_replace callback to adjust relative urls from relative to this file to relative
+ * to the appropriate dokuwiki root location as described in the code
+ *
+ * @param array see http://php.net/preg_replace_callback
+ * @return string see http://php.net/preg_replace_callback
+ */
+ public function replacements($match) {
+
+ // not a relative url? - no adjustment required
+ if (preg_match('#^(/|data:|https?://)#',$match[3])) {
+ return $match[0];
+ }
+ // a less file import? - requires a file system location
+ else if (substr($match[3],-5) == '.less') {
+ if ($match[3]{0} != '/') {
+ $match[3] = $this->getRelativePath() . '/' . $match[3];
+ }
+ }
+ // everything else requires a url adjustment
+ else {
+ $match[3] = $this->location . $match[3];
+ }
+
+ return join('',array_slice($match,1));
+ }
}
/**
- * Converte local image URLs to data URLs if the filesize is small
+ * Convert local image URLs to data URLs if the filesize is small
*
* Callback for preg_replace_callback
*/
@@ -422,7 +511,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;
}
@@ -447,11 +536,6 @@ function css_pluginstyles($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
- if($lang['direction'] == 'rtl'){
- $list[DOKU_PLUGIN."$p/rtl.css"] = DOKU_BASE."lib/plugins/$p/";
- }
}
return $list;
}
diff --git a/lib/exe/detail.php b/lib/exe/detail.php
index e3c81d877..cd3f362ad 100644
--- a/lib/exe/detail.php
+++ b/lib/exe/detail.php
@@ -6,7 +6,7 @@ require_once(DOKU_INC.'inc/init.php');
$IMG = getID('media');
$ID = cleanID($INPUT->str('id'));
-// this makes some general infos available as well as the info about the
+// this makes some general info available as well as the info about the
// "parent" page
$INFO = array_merge(pageinfo(),mediainfo());
diff --git a/lib/images/_deprecated.txt b/lib/images/_deprecated.txt
index bccea2049..a347f8b3c 100644
--- a/lib/images/_deprecated.txt
+++ b/lib/images/_deprecated.txt
@@ -1,12 +1,2 @@
-== @deprecated 2012-10-06 ==
-
-arrow_down.gif
-arrow_up.gif
-at.gif
-close.png
-del.png
-edit.gif
-list-minus.gif
-list-plus.gif
-pencil.png
+(none)
diff --git a/lib/images/arrow_down.gif b/lib/images/arrow_down.gif
deleted file mode 100644
index ff13b9585..000000000
--- a/lib/images/arrow_down.gif
+++ /dev/null
Binary files differ
diff --git a/lib/images/arrow_up.gif b/lib/images/arrow_up.gif
deleted file mode 100644
index d491c18db..000000000
--- a/lib/images/arrow_up.gif
+++ /dev/null
Binary files differ
diff --git a/lib/images/at.gif b/lib/images/at.gif
deleted file mode 100644
index 8bdf40d54..000000000
--- a/lib/images/at.gif
+++ /dev/null
Binary files differ
diff --git a/lib/images/close.png b/lib/images/close.png
deleted file mode 100644
index 4ccef0603..000000000
--- a/lib/images/close.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/del.png b/lib/images/del.png
deleted file mode 100644
index e59ded55f..000000000
--- a/lib/images/del.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/edit.gif b/lib/images/edit.gif
deleted file mode 100644
index a2a23de7b..000000000
--- a/lib/images/edit.gif
+++ /dev/null
Binary files differ
diff --git a/lib/images/list-minus.gif b/lib/images/list-minus.gif
deleted file mode 100644
index 36902f159..000000000
--- a/lib/images/list-minus.gif
+++ /dev/null
Binary files differ
diff --git a/lib/images/list-plus.gif b/lib/images/list-plus.gif
deleted file mode 100644
index adc3fac8a..000000000
--- a/lib/images/list-plus.gif
+++ /dev/null
Binary files differ
diff --git a/lib/images/pencil.png b/lib/images/pencil.png
deleted file mode 100644
index 78142b61e..000000000
--- a/lib/images/pencil.png
+++ /dev/null
Binary files differ
diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php
index b24981d91..6c7c28ff6 100644
--- a/lib/plugins/acl/admin.php
+++ b/lib/plugins/acl/admin.php
@@ -345,7 +345,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin {
}
/**
- * Print infos and editor
+ * Print info and editor
*/
function _html_info(){
global $ID;
diff --git a/lib/plugins/acl/lang/bg/lang.php b/lib/plugins/acl/lang/bg/lang.php
index 95201750e..14e7d311c 100644
--- a/lib/plugins/acl/lang/bg/lang.php
+++ b/lib/plugins/acl/lang/bg/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * bulgarian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Nikolay Vladimirov <nikolay@vladimiroff.com>
* @author Viktor Usunov <usun0v@mail.bg>
* @author Kiril <neohidra@gmail.com>
diff --git a/lib/plugins/acl/lang/fi/lang.php b/lib/plugins/acl/lang/fi/lang.php
index 4f145e0f6..50224dfb4 100644
--- a/lib/plugins/acl/lang/fi/lang.php
+++ b/lib/plugins/acl/lang/fi/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author otto@valjakko.net
* @author Otto Vainio <otto@valjakko.net>
* @author Teemu Mattila <ghcsystems@gmail.com>
diff --git a/lib/plugins/acl/lang/id/lang.php b/lib/plugins/acl/lang/id/lang.php
index 650637635..6f619c5ec 100644
--- a/lib/plugins/acl/lang/id/lang.php
+++ b/lib/plugins/acl/lang/id/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * Indonesian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author mubaidillah <mubaidillah@gmail.com>
* @author Yustinus Waruwu <juswaruwu@gmail.com>
*/
diff --git a/lib/plugins/acl/lang/ko/lang.php b/lib/plugins/acl/lang/ko/lang.php
index 2f1ba2311..34b93a9f4 100644
--- a/lib/plugins/acl/lang/ko/lang.php
+++ b/lib/plugins/acl/lang/ko/lang.php
@@ -12,6 +12,7 @@
* @author Seung-Chul Yoo <dryoo@live.com>
* @author erial2@gmail.com
* @author Myeongjin <aranet100@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['admin_acl'] = '접근 제어 목록 관리';
$lang['acl_group'] = '그룹';
@@ -27,7 +28,7 @@ $lang['p_group_ns'] = '<b class="aclgroup">%s</b> 그룹 구성원은
$lang['p_choose_id'] = '<b class="aclpage">%s</b> 문서 접근 권한을 보거나 바꾸려면 <b>사용자</b>나 <b>그룹</b>을 위 양식에 입력하세요.';
$lang['p_choose_ns'] = '<b class="aclns">%s</b> 이름공간 접근 권한을 보거나 바꾸려면 <b>사용자</b>나 <b>그룹</b>을 위 양식에 입력하세요.';
$lang['p_inherited'] = '참고: 권한이 명시적으로 설정되지 않았으므로 다른 그룹이나 상위 이름공간으로부터 가져왔습니다.';
-$lang['p_isadmin'] = '참고: 슈퍼유저로 설정되어 있으므로 선택된 그룹이나 사용자는 언제나 모든 접근 권한을 가집니다.';
+$lang['p_isadmin'] = '참고: 슈퍼 사용자로 설정되어 있으므로 선택된 그룹이나 사용자는 언제나 모든 접근 권한을 가집니다.';
$lang['p_include'] = '더 높은 접근 권한은 하위를 포함합니다. 문서가 아닌 이름공간에는 만들기, 올리기, 삭제 권한만 적용됩니다.';
$lang['current'] = '현재 ACL 규칙';
$lang['where'] = '문서/이름공간';
diff --git a/lib/plugins/acl/lang/no/lang.php b/lib/plugins/acl/lang/no/lang.php
index 09d71937a..82cdd5eef 100644
--- a/lib/plugins/acl/lang/no/lang.php
+++ b/lib/plugins/acl/lang/no/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * Norwegian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Reidar Mosvold <Reidar.Mosvold@hit.no>
* @author Jorge Barrera Grandon <jorge@digitalwolves.org>
* @author Thomas Nygreen <nygreen@gmail.com>
@@ -10,7 +10,7 @@
* @author Torkill Bruland <torkar-b@online.no>
* @author Rune M. Andersen <rune.andersen@gmail.com>
* @author Jakob Vad Nielsen (me@jakobnielsen.net)
- * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
+ * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
* @author Knut Staring <knutst@gmail.com>
* @author Lisa Ditlefsen <lisa@vervesearch.com>
* @author Erik Pedersen <erik.pedersen@shaw.ca>
diff --git a/lib/plugins/acl/lang/pl/lang.php b/lib/plugins/acl/lang/pl/lang.php
index bef2d2615..42ce7fdaf 100644
--- a/lib/plugins/acl/lang/pl/lang.php
+++ b/lib/plugins/acl/lang/pl/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * polish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Grzegorz Żur <grzegorz.zur@gmail.com>
* @author Mariusz Kujawski <marinespl@gmail.com>
* @author Maciej Kurczewski <pipijajko@gmail.com>
diff --git a/lib/plugins/acl/lang/vi/lang.php b/lib/plugins/acl/lang/vi/lang.php
index ddf764dca..4fc3388ff 100644
--- a/lib/plugins/acl/lang/vi/lang.php
+++ b/lib/plugins/acl/lang/vi/lang.php
@@ -1,44 +1,35 @@
<?php
+
/**
- * vietnamese language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- * @author NukeViet <admin@nukeviet.vn>
+ *
+ * @author NukeViet <admin@nukeviet.vn>
*/
-
-$lang['admin_acl'] = 'Quản lý danh sách quyền truy cập';
-$lang['acl_group'] = 'Nhóm';
-$lang['acl_user'] = 'Thành viên';
-$lang['acl_perms'] = 'Cấp phép cho';
-$lang['page'] = 'Trang';
-$lang['namespace'] = 'Thư mục';
-
-$lang['btn_select'] = 'Chọn';
-
-$lang['p_user_id'] = 'Thành viên <b class="acluser">%s</b> hiện tại được cấp phép cho trang <b class="aclpage">%s</b>: <i>%s</i>.';
-$lang['p_user_ns'] = 'Thành viên <b class="acluser">%s</b> hiện tại được cấp phép cho thư mục <b class="aclns">%s</b>: <i>%s</i>.';
-$lang['p_group_id'] = 'Thành viên trong nhóm <b class="aclgroup">%s</b> hiện tại được cấp phép cho trang <b class="aclpage">%s</b>: <i>%s</i>.';
-$lang['p_group_ns'] = 'Thành viên trong nhóm <b class="aclgroup">%s</b> hiện tại được cấp phép cho thư mục <b class="aclns">%s</b>: <i>%s</i>.';
-
-$lang['p_choose_id'] = 'Hãy <b>nhập tên thành viên hoặc nhóm</b> vào ô trên đây để xem hoặc sửa quyền đã thiết đặt cho trang <b class="aclpage">%s</b>.';
-$lang['p_choose_ns'] = 'Hãy <b>nhập tên thành viên hoặc nhóm</b> vào ô trên đây để xem hoặc sửa quyền đã thiết đặt cho thư mục <b class="aclns">%s</b>.';
-
-
-$lang['p_inherited'] = 'Ghi chú: Có những quyền không được thể hiện ở đây nhưng nó được cấp phép từ những nhóm hoặc thư mục cấp cao.';
-$lang['p_isadmin'] = 'Ghi chú: Nhóm hoặc thành viên này luôn được cấp đủ quyền vì họ là Quản trị tối cao';
-$lang['p_include'] = 'Một số quyền thấp được thể hiện ở mức cao hơn. Quyền tạo, tải lên và xóa chỉ dành cho thư mục, không dành cho trang.';
-
-$lang['current'] = 'Danh sách quyền truy cập hiện tại';
-$lang['where'] = 'Trang/Thư mục';
-$lang['who'] = 'Thành viên/Nhóm';
-$lang['perm'] = 'Quyền';
-
-$lang['acl_perm0'] = 'Không';
-$lang['acl_perm1'] = 'Đọc';
-$lang['acl_perm2'] = 'Sửa';
-$lang['acl_perm4'] = 'Tạo';
-$lang['acl_perm8'] = 'Tải lên';
-$lang['acl_perm16'] = 'Xóa';
-$lang['acl_new'] = 'Thêm mục mới';
-$lang['acl_mod'] = 'Sửa';
-//Setup VIM: ex: et ts=2 :
+$lang['admin_acl'] = 'Quản lý danh sách quyền truy cập';
+$lang['acl_group'] = 'Nhóm';
+$lang['acl_user'] = 'Thành viên';
+$lang['acl_perms'] = 'Cấp phép cho';
+$lang['page'] = 'Trang';
+$lang['namespace'] = 'Thư mục';
+$lang['btn_select'] = 'Chọn';
+$lang['p_user_id'] = 'Thành viên <b class="acluser">%s</b> hiện tại được cấp phép cho trang <b class="aclpage">%s</b>: <i>%s</i>.';
+$lang['p_user_ns'] = 'Thành viên <b class="acluser">%s</b> hiện tại được cấp phép cho thư mục <b class="aclns">%s</b>: <i>%s</i>.';
+$lang['p_group_id'] = 'Thành viên trong nhóm <b class="aclgroup">%s</b> hiện tại được cấp phép cho trang <b class="aclpage">%s</b>: <i>%s</i>.';
+$lang['p_group_ns'] = 'Thành viên trong nhóm <b class="aclgroup">%s</b> hiện tại được cấp phép cho thư mục <b class="aclns">%s</b>: <i>%s</i>.';
+$lang['p_choose_id'] = 'Hãy <b>nhập tên thành viên hoặc nhóm</b> vào ô trên đây để xem hoặc sửa quyền đã thiết đặt cho trang <b class="aclpage">%s</b>.';
+$lang['p_choose_ns'] = 'Hãy <b>nhập tên thành viên hoặc nhóm</b> vào ô trên đây để xem hoặc sửa quyền đã thiết đặt cho thư mục <b class="aclns">%s</b>.';
+$lang['p_inherited'] = 'Ghi chú: Có những quyền không được thể hiện ở đây nhưng nó được cấp phép từ những nhóm hoặc thư mục cấp cao.';
+$lang['p_isadmin'] = 'Ghi chú: Nhóm hoặc thành viên này luôn được cấp đủ quyền vì họ là Quản trị tối cao';
+$lang['p_include'] = 'Một số quyền thấp được thể hiện ở mức cao hơn. Quyền tạo, tải lên và xóa chỉ dành cho thư mục, không dành cho trang.';
+$lang['current'] = 'Danh sách quyền truy cập hiện tại';
+$lang['where'] = 'Trang/Thư mục';
+$lang['who'] = 'Thành viên/Nhóm';
+$lang['perm'] = 'Quyền';
+$lang['acl_perm0'] = 'Không';
+$lang['acl_perm1'] = 'Đọc';
+$lang['acl_perm2'] = 'Sửa';
+$lang['acl_perm4'] = 'Tạo';
+$lang['acl_perm8'] = 'Tải lên';
+$lang['acl_perm16'] = 'Xóa';
+$lang['acl_new'] = 'Thêm mục mới';
+$lang['acl_mod'] = 'Sửa';
diff --git a/lib/plugins/authad/adLDAP/adLDAP.php b/lib/plugins/authad/adLDAP/adLDAP.php
index a8f33b47e..c1f92abe2 100644
--- a/lib/plugins/authad/adLDAP/adLDAP.php
+++ b/lib/plugins/authad/adLDAP/adLDAP.php
@@ -1,951 +1,951 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 169 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-
-/**
-* Main adLDAP class
-*
-* Can be initialised using $adldap = new adLDAP();
-*
-* Something to keep in mind is that Active Directory is a permissions
-* based directory. If you bind as a domain user, you can't fetch as
-* much information on other users as you could as a domain admin.
-*
-* Before asking questions, please read the Documentation at
-* http://adldap.sourceforge.net/wiki/doku.php?id=api
-*/
-require_once(dirname(__FILE__) . '/collections/adLDAPCollection.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPGroups.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPUsers.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPFolders.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPUtils.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPContacts.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPExchange.php');
-require_once(dirname(__FILE__) . '/classes/adLDAPComputers.php');
-
-class adLDAP {
-
- /**
- * Define the different types of account in AD
- */
- const ADLDAP_NORMAL_ACCOUNT = 805306368;
- const ADLDAP_WORKSTATION_TRUST = 805306369;
- const ADLDAP_INTERDOMAIN_TRUST = 805306370;
- const ADLDAP_SECURITY_GLOBAL_GROUP = 268435456;
- const ADLDAP_DISTRIBUTION_GROUP = 268435457;
- const ADLDAP_SECURITY_LOCAL_GROUP = 536870912;
- const ADLDAP_DISTRIBUTION_LOCAL_GROUP = 536870913;
- const ADLDAP_FOLDER = 'OU';
- const ADLDAP_CONTAINER = 'CN';
-
- /**
- * The default port for LDAP non-SSL connections
- */
- const ADLDAP_LDAP_PORT = '389';
- /**
- * The default port for LDAPS SSL connections
- */
- const ADLDAP_LDAPS_PORT = '636';
-
- /**
- * The account suffix for your domain, can be set when the class is invoked
- *
- * @var string
- */
- protected $accountSuffix = "@mydomain.local";
-
- /**
- * The base dn for your domain
- *
- * If this is set to null then adLDAP will attempt to obtain this automatically from the rootDSE
- *
- * @var string
- */
- protected $baseDn = "DC=mydomain,DC=local";
-
- /**
- * Port used to talk to the domain controllers.
- *
- * @var int
- */
- protected $adPort = self::ADLDAP_LDAP_PORT;
-
- /**
- * Array of domain controllers. Specifiy multiple controllers if you
- * would like the class to balance the LDAP queries amongst multiple servers
- *
- * @var array
- */
- protected $domainControllers = array("dc01.mydomain.local");
-
- /**
- * Optional account with higher privileges for searching
- * This should be set to a domain admin account
- *
- * @var string
- * @var string
- */
- protected $adminUsername = NULL;
- protected $adminPassword = NULL;
-
- /**
- * AD does not return the primary group. http://support.microsoft.com/?kbid=321360
- * This tweak will resolve the real primary group.
- * Setting to false will fudge "Domain Users" and is much faster. Keep in mind though that if
- * someone's primary group is NOT domain users, this is obviously going to mess up the results
- *
- * @var bool
- */
- protected $realPrimaryGroup = true;
-
- /**
- * Use SSL (LDAPS), your server needs to be setup, please see
- * http://adldap.sourceforge.net/wiki/doku.php?id=ldap_over_ssl
- *
- * @var bool
- */
- protected $useSSL = false;
-
- /**
- * Use TLS
- * If you wish to use TLS you should ensure that $useSSL is set to false and vice-versa
- *
- * @var bool
- */
- protected $useTLS = false;
-
- /**
- * Use SSO
- * To indicate to adLDAP to reuse password set by the brower through NTLM or Kerberos
- *
- * @var bool
- */
- protected $useSSO = false;
-
- /**
- * When querying group memberships, do it recursively
- * eg. User Fred is a member of Group A, which is a member of Group B, which is a member of Group C
- * user_ingroup("Fred","C") will returns true with this option turned on, false if turned off
- *
- * @var bool
- */
- protected $recursiveGroups = true;
-
- // You should not need to edit anything below this line
- //******************************************************************************************
-
- /**
- * Connection and bind default variables
- *
- * @var mixed
- * @var mixed
- */
- protected $ldapConnection;
- protected $ldapBind;
-
- /**
- * Get the active LDAP Connection
- *
- * @return resource
- */
- public function getLdapConnection() {
- if ($this->ldapConnection) {
- return $this->ldapConnection;
- }
- return false;
- }
-
- /**
- * Get the bind status
- *
- * @return bool
- */
- public function getLdapBind() {
- return $this->ldapBind;
- }
-
- /**
- * Get the current base DN
- *
- * @return string
- */
- public function getBaseDn() {
- return $this->baseDn;
- }
-
- /**
- * The group class
- *
- * @var adLDAPGroups
- */
- protected $groupClass;
-
- /**
- * Get the group class interface
- *
- * @return adLDAPGroups
- */
- public function group() {
- if (!$this->groupClass) {
- $this->groupClass = new adLDAPGroups($this);
- }
- return $this->groupClass;
- }
-
- /**
- * The user class
- *
- * @var adLDAPUsers
- */
- protected $userClass;
-
- /**
- * Get the userclass interface
- *
- * @return adLDAPUsers
- */
- public function user() {
- if (!$this->userClass) {
- $this->userClass = new adLDAPUsers($this);
- }
- return $this->userClass;
- }
-
- /**
- * The folders class
- *
- * @var adLDAPFolders
- */
- protected $folderClass;
-
- /**
- * Get the folder class interface
- *
- * @return adLDAPFolders
- */
- public function folder() {
- if (!$this->folderClass) {
- $this->folderClass = new adLDAPFolders($this);
- }
- return $this->folderClass;
- }
-
- /**
- * The utils class
- *
- * @var adLDAPUtils
- */
- protected $utilClass;
-
- /**
- * Get the utils class interface
- *
- * @return adLDAPUtils
- */
- public function utilities() {
- if (!$this->utilClass) {
- $this->utilClass = new adLDAPUtils($this);
- }
- return $this->utilClass;
- }
-
- /**
- * The contacts class
- *
- * @var adLDAPContacts
- */
- protected $contactClass;
-
- /**
- * Get the contacts class interface
- *
- * @return adLDAPContacts
- */
- public function contact() {
- if (!$this->contactClass) {
- $this->contactClass = new adLDAPContacts($this);
- }
- return $this->contactClass;
- }
-
- /**
- * The exchange class
- *
- * @var adLDAPExchange
- */
- protected $exchangeClass;
-
- /**
- * Get the exchange class interface
- *
- * @return adLDAPExchange
- */
- public function exchange() {
- if (!$this->exchangeClass) {
- $this->exchangeClass = new adLDAPExchange($this);
- }
- return $this->exchangeClass;
- }
-
- /**
- * The computers class
- *
- * @var adLDAPComputers
- */
- protected $computersClass;
-
- /**
- * Get the computers class interface
- *
- * @return adLDAPComputers
- */
- public function computer() {
- if (!$this->computerClass) {
- $this->computerClass = new adLDAPComputers($this);
- }
- return $this->computerClass;
- }
-
- /**
- * Getters and Setters
- */
-
- /**
- * Set the account suffix
- *
- * @param string $accountSuffix
- * @return void
- */
- public function setAccountSuffix($accountSuffix)
- {
- $this->accountSuffix = $accountSuffix;
- }
-
- /**
- * Get the account suffix
- *
- * @return string
- */
- public function getAccountSuffix()
- {
- return $this->accountSuffix;
- }
-
- /**
- * Set the domain controllers array
- *
- * @param array $domainControllers
- * @return void
- */
- public function setDomainControllers(array $domainControllers)
- {
- $this->domainControllers = $domainControllers;
- }
-
- /**
- * Get the list of domain controllers
- *
- * @return void
- */
- public function getDomainControllers()
- {
- return $this->domainControllers;
- }
-
- /**
- * Sets the port number your domain controller communicates over
- *
- * @param int $adPort
- */
- public function setPort($adPort)
- {
- $this->adPort = $adPort;
- }
-
- /**
- * Gets the port number your domain controller communicates over
- *
- * @return int
- */
- public function getPort()
- {
- return $this->adPort;
- }
-
- /**
- * Set the username of an account with higher priviledges
- *
- * @param string $adminUsername
- * @return void
- */
- public function setAdminUsername($adminUsername)
- {
- $this->adminUsername = $adminUsername;
- }
-
- /**
- * Get the username of the account with higher priviledges
- *
- * This will throw an exception for security reasons
- */
- public function getAdminUsername()
- {
- throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
- }
-
- /**
- * Set the password of an account with higher priviledges
- *
- * @param string $adminPassword
- * @return void
- */
- public function setAdminPassword($adminPassword)
- {
- $this->adminPassword = $adminPassword;
- }
-
- /**
- * Get the password of the account with higher priviledges
- *
- * This will throw an exception for security reasons
- */
- public function getAdminPassword()
- {
- throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
- }
-
- /**
- * Set whether to detect the true primary group
- *
- * @param bool $realPrimaryGroup
- * @return void
- */
- public function setRealPrimaryGroup($realPrimaryGroup)
- {
- $this->realPrimaryGroup = $realPrimaryGroup;
- }
-
- /**
- * Get the real primary group setting
- *
- * @return bool
- */
- public function getRealPrimaryGroup()
- {
- return $this->realPrimaryGroup;
- }
-
- /**
- * Set whether to use SSL
- *
- * @param bool $useSSL
- * @return void
- */
- public function setUseSSL($useSSL)
- {
- $this->useSSL = $useSSL;
- // Set the default port correctly
- if($this->useSSL) {
- $this->setPort(self::ADLDAP_LDAPS_PORT);
- }
- else {
- $this->setPort(self::ADLDAP_LDAP_PORT);
- }
- }
-
- /**
- * Get the SSL setting
- *
- * @return bool
- */
- public function getUseSSL()
- {
- return $this->useSSL;
- }
-
- /**
- * Set whether to use TLS
- *
- * @param bool $useTLS
- * @return void
- */
- public function setUseTLS($useTLS)
- {
- $this->useTLS = $useTLS;
- }
-
- /**
- * Get the TLS setting
- *
- * @return bool
- */
- public function getUseTLS()
- {
- return $this->useTLS;
- }
-
- /**
- * Set whether to use SSO
- * Requires ldap_sasl_bind support. Be sure --with-ldap-sasl is used when configuring PHP otherwise this function will be undefined.
- *
- * @param bool $useSSO
- * @return void
- */
- public function setUseSSO($useSSO)
- {
- if ($useSSO === true && !$this->ldapSaslSupported()) {
- throw new adLDAPException('No LDAP SASL support for PHP. See: http://www.php.net/ldap_sasl_bind');
- }
- $this->useSSO = $useSSO;
- }
-
- /**
- * Get the SSO setting
- *
- * @return bool
- */
- public function getUseSSO()
- {
- return $this->useSSO;
- }
-
- /**
- * Set whether to lookup recursive groups
- *
- * @param bool $recursiveGroups
- * @return void
- */
- public function setRecursiveGroups($recursiveGroups)
- {
- $this->recursiveGroups = $recursiveGroups;
- }
-
- /**
- * Get the recursive groups setting
- *
- * @return bool
- */
- public function getRecursiveGroups()
- {
- return $this->recursiveGroups;
- }
-
- /**
- * Default Constructor
- *
- * Tries to bind to the AD domain over LDAP or LDAPs
- *
- * @param array $options Array of options to pass to the constructor
- * @throws Exception - if unable to bind to Domain Controller
- * @return bool
- */
- function __construct($options = array()) {
- // You can specifically overide any of the default configuration options setup above
- if (count($options) > 0) {
- if (array_key_exists("account_suffix",$options)){ $this->accountSuffix = $options["account_suffix"]; }
- if (array_key_exists("base_dn",$options)){ $this->baseDn = $options["base_dn"]; }
- if (array_key_exists("domain_controllers",$options)){
- if (!is_array($options["domain_controllers"])) {
- throw new adLDAPException('[domain_controllers] option must be an array');
- }
- $this->domainControllers = $options["domain_controllers"];
- }
- if (array_key_exists("admin_username",$options)){ $this->adminUsername = $options["admin_username"]; }
- if (array_key_exists("admin_password",$options)){ $this->adminPassword = $options["admin_password"]; }
- if (array_key_exists("real_primarygroup",$options)){ $this->realPrimaryGroup = $options["real_primarygroup"]; }
- if (array_key_exists("use_ssl",$options)){ $this->setUseSSL($options["use_ssl"]); }
- if (array_key_exists("use_tls",$options)){ $this->useTLS = $options["use_tls"]; }
- if (array_key_exists("recursive_groups",$options)){ $this->recursiveGroups = $options["recursive_groups"]; }
- if (array_key_exists("ad_port",$options)){ $this->setPort($options["ad_port"]); }
- if (array_key_exists("sso",$options)) {
- $this->setUseSSO($options["sso"]);
- if (!$this->ldapSaslSupported()) {
- $this->setUseSSO(false);
- }
- }
- }
-
- if ($this->ldapSupported() === false) {
- throw new adLDAPException('No LDAP support for PHP. See: http://www.php.net/ldap');
- }
-
- return $this->connect();
- }
-
- /**
- * Default Destructor
- *
- * Closes the LDAP connection
- *
- * @return void
- */
- function __destruct() {
- $this->close();
- }
-
- /**
- * Connects and Binds to the Domain Controller
- *
- * @return bool
- */
- public function connect()
- {
- // Connect to the AD/LDAP server as the username/password
- $domainController = $this->randomController();
- if ($this->useSSL) {
- $this->ldapConnection = ldap_connect("ldaps://" . $domainController, $this->adPort);
- } else {
- $this->ldapConnection = ldap_connect($domainController, $this->adPort);
- }
-
- // Set some ldap options for talking to AD
- ldap_set_option($this->ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
- ldap_set_option($this->ldapConnection, LDAP_OPT_REFERRALS, 0);
-
- if ($this->useTLS) {
- ldap_start_tls($this->ldapConnection);
- }
-
- // Bind as a domain admin if they've set it up
- if ($this->adminUsername !== NULL && $this->adminPassword !== NULL) {
- $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix, $this->adminPassword);
- if (!$this->ldapBind) {
- if ($this->useSSL && !$this->useTLS) {
- // If you have problems troubleshooting, remove the @ character from the ldapldapBind command above to get the actual error message
- throw new adLDAPException('Bind to Active Directory failed. Either the LDAPs connection failed or the login credentials are incorrect. AD said: ' . $this->getLastError());
- }
- else {
- throw new adLDAPException('Bind to Active Directory failed. Check the login credentials and/or server details. AD said: ' . $this->getLastError());
- }
- }
- }
- if ($this->useSSO && $_SERVER['REMOTE_USER'] && $this->adminUsername === null && $_SERVER['KRB5CCNAME']) {
- putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
- $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
- if (!$this->ldapBind){
- throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
- }
- else {
- return true;
- }
- }
-
-
- if ($this->baseDn == NULL) {
- $this->baseDn = $this->findBaseDn();
- }
-
- return true;
- }
-
- /**
- * Closes the LDAP connection
- *
- * @return void
- */
- public function close() {
- if ($this->ldapConnection) {
- @ldap_close($this->ldapConnection);
- }
- }
-
- /**
- * Validate a user's login credentials
- *
- * @param string $username A user's AD username
- * @param string $password A user's AD password
- * @param bool optional $preventRebind
- * @return bool
- */
- public function authenticate($username, $password, $preventRebind = false) {
- // Prevent null binding
- if ($username === NULL || $password === NULL) { return false; }
- if (empty($username) || empty($password)) { return false; }
-
- // Allow binding over SSO for Kerberos
- if ($this->useSSO && $_SERVER['REMOTE_USER'] && $_SERVER['REMOTE_USER'] == $username && $this->adminUsername === NULL && $_SERVER['KRB5CCNAME']) {
- putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
- $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
- if (!$this->ldapBind) {
- throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
- }
- else {
- return true;
- }
- }
-
- // Bind as the user
- $ret = true;
- $this->ldapBind = @ldap_bind($this->ldapConnection, $username . $this->accountSuffix, $password);
- if (!$this->ldapBind){
- $ret = false;
- }
-
- // Cnce we've checked their details, kick back into admin mode if we have it
- if ($this->adminUsername !== NULL && !$preventRebind) {
- $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix , $this->adminPassword);
- if (!$this->ldapBind){
- // This should never happen in theory
- throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
- }
- }
-
- return $ret;
- }
-
- /**
- * Find the Base DN of your domain controller
- *
- * @return string
- */
- public function findBaseDn()
- {
- $namingContext = $this->getRootDse(array('defaultnamingcontext'));
- return $namingContext[0]['defaultnamingcontext'][0];
- }
-
- /**
- * Get the RootDSE properties from a domain controller
- *
- * @param array $attributes The attributes you wish to query e.g. defaultnamingcontext
- * @return array
- */
- public function getRootDse($attributes = array("*", "+")) {
- if (!$this->ldapBind){ return (false); }
-
- $sr = @ldap_read($this->ldapConnection, NULL, 'objectClass=*', $attributes);
- $entries = @ldap_get_entries($this->ldapConnection, $sr);
- return $entries;
- }
-
- /**
- * Get last error from Active Directory
- *
- * This function gets the last message from Active Directory
- * This may indeed be a 'Success' message but if you get an unknown error
- * it might be worth calling this function to see what errors were raised
- *
- * return string
- */
- public function getLastError() {
- return @ldap_error($this->ldapConnection);
- }
-
- /**
- * Detect LDAP support in php
- *
- * @return bool
- */
- protected function ldapSupported()
- {
- if (!function_exists('ldap_connect')) {
- return false;
- }
- return true;
- }
-
- /**
- * Detect ldap_sasl_bind support in PHP
- *
- * @return bool
- */
- protected function ldapSaslSupported()
- {
- if (!function_exists('ldap_sasl_bind')) {
- return false;
- }
- return true;
- }
-
- /**
- * Schema
- *
- * @param array $attributes Attributes to be queried
- * @return array
- */
- public function adldap_schema($attributes){
-
- // LDAP doesn't like NULL attributes, only set them if they have values
- // If you wish to remove an attribute you should set it to a space
- // TO DO: Adapt user_modify to use ldap_mod_delete to remove a NULL attribute
- $mod=array();
-
- // Check every attribute to see if it contains 8bit characters and then UTF8 encode them
- array_walk($attributes, array($this, 'encode8bit'));
-
- if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; }
- if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; }
- //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes?
- if ($attributes["address_country"]){ $mod["c"][0]=$attributes["address_country"]; }
- if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; }
- if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; }
- if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; }
- if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; }
- if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; }
- if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; }
- if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; }
- if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; }
- if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; }
- if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format?
- if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; }
- if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; }
- if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; }
- if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; }
- if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; }
- if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; } //UNTESTED ***Use DistinguishedName***
- if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; }
- if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->user()->encodePassword($attributes["password"]); }
- if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; }
- if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; }
- if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; }
- if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; }
- if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; }
- if ($attributes["mobile"]){ $mod["mobile"][0]=$attributes["mobile"]; }
- if ($attributes["pager"]){ $mod["pager"][0]=$attributes["pager"]; }
- if ($attributes["ipphone"]){ $mod["ipphone"][0]=$attributes["ipphone"]; }
- if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; }
- if ($attributes["fax"]){ $mod["facsimileTelephoneNumber"][0]=$attributes["fax"]; }
- if ($attributes["enabled"]){ $mod["userAccountControl"][0]=$attributes["enabled"]; }
- if ($attributes["homephone"]){ $mod["homephone"][0]=$attributes["homephone"]; }
-
- // Distribution List specific schema
- if ($attributes["group_sendpermission"]){ $mod["dlMemSubmitPerms"][0]=$attributes["group_sendpermission"]; }
- if ($attributes["group_rejectpermission"]){ $mod["dlMemRejectPerms"][0]=$attributes["group_rejectpermission"]; }
-
- // Exchange Schema
- if ($attributes["exchange_homemdb"]){ $mod["homeMDB"][0]=$attributes["exchange_homemdb"]; }
- if ($attributes["exchange_mailnickname"]){ $mod["mailNickname"][0]=$attributes["exchange_mailnickname"]; }
- if ($attributes["exchange_proxyaddress"]){ $mod["proxyAddresses"][0]=$attributes["exchange_proxyaddress"]; }
- if ($attributes["exchange_usedefaults"]){ $mod["mDBUseDefaults"][0]=$attributes["exchange_usedefaults"]; }
- if ($attributes["exchange_policyexclude"]){ $mod["msExchPoliciesExcluded"][0]=$attributes["exchange_policyexclude"]; }
- if ($attributes["exchange_policyinclude"]){ $mod["msExchPoliciesIncluded"][0]=$attributes["exchange_policyinclude"]; }
- if ($attributes["exchange_addressbook"]){ $mod["showInAddressBook"][0]=$attributes["exchange_addressbook"]; }
- if ($attributes["exchange_altrecipient"]){ $mod["altRecipient"][0]=$attributes["exchange_altrecipient"]; }
- if ($attributes["exchange_deliverandredirect"]){ $mod["deliverAndRedirect"][0]=$attributes["exchange_deliverandredirect"]; }
-
- // This schema is designed for contacts
- if ($attributes["exchange_hidefromlists"]){ $mod["msExchHideFromAddressLists"][0]=$attributes["exchange_hidefromlists"]; }
- if ($attributes["contact_email"]){ $mod["targetAddress"][0]=$attributes["contact_email"]; }
-
- //echo ("<pre>"); print_r($mod);
- /*
- // modifying a name is a bit fiddly
- if ($attributes["firstname"] && $attributes["surname"]){
- $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
- $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
- $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
- }
- */
-
- if (count($mod)==0){ return (false); }
- return ($mod);
- }
-
- /**
- * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
- */
- protected function encode8Bit(&$item, $key) {
- $encode = false;
- if (is_string($item)) {
- for ($i=0; $i<strlen($item); $i++) {
- if (ord($item[$i]) >> 7) {
- $encode = true;
- }
- }
- }
- if ($encode === true && $key != 'password') {
- $item = utf8_encode($item);
- }
- }
-
- /**
- * Select a random domain controller from your domain controller array
- *
- * @return string
- */
- protected function randomController()
- {
- mt_srand(doubleval(microtime()) * 100000000); // For older PHP versions
- /*if (sizeof($this->domainControllers) > 1) {
- $adController = $this->domainControllers[array_rand($this->domainControllers)];
- // Test if the controller is responding to pings
- $ping = $this->pingController($adController);
- if ($ping === false) {
- // Find the current key in the domain controllers array
- $key = array_search($adController, $this->domainControllers);
- // Remove it so that we don't end up in a recursive loop
- unset($this->domainControllers[$key]);
- // Select a new controller
- return $this->randomController();
- }
- else {
- return ($adController);
- }
- } */
- return $this->domainControllers[array_rand($this->domainControllers)];
- }
-
- /**
- * Test basic connectivity to controller
- *
- * @return bool
- */
- protected function pingController($host) {
- $port = $this->adPort;
- fsockopen($host, $port, $errno, $errstr, 10);
- if ($errno > 0) {
- return false;
- }
- return true;
- }
-
-}
-
-/**
-* adLDAP Exception Handler
-*
-* Exceptions of this type are thrown on bind failure or when SSL is required but not configured
-* Example:
-* try {
-* $adldap = new adLDAP();
-* }
-* catch (adLDAPException $e) {
-* echo $e;
-* exit();
-* }
-*/
-class adLDAPException extends Exception {}
-
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 169 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+
+/**
+* Main adLDAP class
+*
+* Can be initialised using $adldap = new adLDAP();
+*
+* Something to keep in mind is that Active Directory is a permissions
+* based directory. If you bind as a domain user, you can't fetch as
+* much information on other users as you could as a domain admin.
+*
+* Before asking questions, please read the Documentation at
+* http://adldap.sourceforge.net/wiki/doku.php?id=api
+*/
+require_once(dirname(__FILE__) . '/collections/adLDAPCollection.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPGroups.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPUsers.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPFolders.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPUtils.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPContacts.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPExchange.php');
+require_once(dirname(__FILE__) . '/classes/adLDAPComputers.php');
+
+class adLDAP {
+
+ /**
+ * Define the different types of account in AD
+ */
+ const ADLDAP_NORMAL_ACCOUNT = 805306368;
+ const ADLDAP_WORKSTATION_TRUST = 805306369;
+ const ADLDAP_INTERDOMAIN_TRUST = 805306370;
+ const ADLDAP_SECURITY_GLOBAL_GROUP = 268435456;
+ const ADLDAP_DISTRIBUTION_GROUP = 268435457;
+ const ADLDAP_SECURITY_LOCAL_GROUP = 536870912;
+ const ADLDAP_DISTRIBUTION_LOCAL_GROUP = 536870913;
+ const ADLDAP_FOLDER = 'OU';
+ const ADLDAP_CONTAINER = 'CN';
+
+ /**
+ * The default port for LDAP non-SSL connections
+ */
+ const ADLDAP_LDAP_PORT = '389';
+ /**
+ * The default port for LDAPS SSL connections
+ */
+ const ADLDAP_LDAPS_PORT = '636';
+
+ /**
+ * The account suffix for your domain, can be set when the class is invoked
+ *
+ * @var string
+ */
+ protected $accountSuffix = "@mydomain.local";
+
+ /**
+ * The base dn for your domain
+ *
+ * If this is set to null then adLDAP will attempt to obtain this automatically from the rootDSE
+ *
+ * @var string
+ */
+ protected $baseDn = "DC=mydomain,DC=local";
+
+ /**
+ * Port used to talk to the domain controllers.
+ *
+ * @var int
+ */
+ protected $adPort = self::ADLDAP_LDAP_PORT;
+
+ /**
+ * Array of domain controllers. Specifiy multiple controllers if you
+ * would like the class to balance the LDAP queries amongst multiple servers
+ *
+ * @var array
+ */
+ protected $domainControllers = array("dc01.mydomain.local");
+
+ /**
+ * Optional account with higher privileges for searching
+ * This should be set to a domain admin account
+ *
+ * @var string
+ * @var string
+ */
+ protected $adminUsername = NULL;
+ protected $adminPassword = NULL;
+
+ /**
+ * AD does not return the primary group. http://support.microsoft.com/?kbid=321360
+ * This tweak will resolve the real primary group.
+ * Setting to false will fudge "Domain Users" and is much faster. Keep in mind though that if
+ * someone's primary group is NOT domain users, this is obviously going to mess up the results
+ *
+ * @var bool
+ */
+ protected $realPrimaryGroup = true;
+
+ /**
+ * Use SSL (LDAPS), your server needs to be setup, please see
+ * http://adldap.sourceforge.net/wiki/doku.php?id=ldap_over_ssl
+ *
+ * @var bool
+ */
+ protected $useSSL = false;
+
+ /**
+ * Use TLS
+ * If you wish to use TLS you should ensure that $useSSL is set to false and vice-versa
+ *
+ * @var bool
+ */
+ protected $useTLS = false;
+
+ /**
+ * Use SSO
+ * To indicate to adLDAP to reuse password set by the brower through NTLM or Kerberos
+ *
+ * @var bool
+ */
+ protected $useSSO = false;
+
+ /**
+ * When querying group memberships, do it recursively
+ * eg. User Fred is a member of Group A, which is a member of Group B, which is a member of Group C
+ * user_ingroup("Fred","C") will returns true with this option turned on, false if turned off
+ *
+ * @var bool
+ */
+ protected $recursiveGroups = true;
+
+ // You should not need to edit anything below this line
+ //******************************************************************************************
+
+ /**
+ * Connection and bind default variables
+ *
+ * @var mixed
+ * @var mixed
+ */
+ protected $ldapConnection;
+ protected $ldapBind;
+
+ /**
+ * Get the active LDAP Connection
+ *
+ * @return resource
+ */
+ public function getLdapConnection() {
+ if ($this->ldapConnection) {
+ return $this->ldapConnection;
+ }
+ return false;
+ }
+
+ /**
+ * Get the bind status
+ *
+ * @return bool
+ */
+ public function getLdapBind() {
+ return $this->ldapBind;
+ }
+
+ /**
+ * Get the current base DN
+ *
+ * @return string
+ */
+ public function getBaseDn() {
+ return $this->baseDn;
+ }
+
+ /**
+ * The group class
+ *
+ * @var adLDAPGroups
+ */
+ protected $groupClass;
+
+ /**
+ * Get the group class interface
+ *
+ * @return adLDAPGroups
+ */
+ public function group() {
+ if (!$this->groupClass) {
+ $this->groupClass = new adLDAPGroups($this);
+ }
+ return $this->groupClass;
+ }
+
+ /**
+ * The user class
+ *
+ * @var adLDAPUsers
+ */
+ protected $userClass;
+
+ /**
+ * Get the userclass interface
+ *
+ * @return adLDAPUsers
+ */
+ public function user() {
+ if (!$this->userClass) {
+ $this->userClass = new adLDAPUsers($this);
+ }
+ return $this->userClass;
+ }
+
+ /**
+ * The folders class
+ *
+ * @var adLDAPFolders
+ */
+ protected $folderClass;
+
+ /**
+ * Get the folder class interface
+ *
+ * @return adLDAPFolders
+ */
+ public function folder() {
+ if (!$this->folderClass) {
+ $this->folderClass = new adLDAPFolders($this);
+ }
+ return $this->folderClass;
+ }
+
+ /**
+ * The utils class
+ *
+ * @var adLDAPUtils
+ */
+ protected $utilClass;
+
+ /**
+ * Get the utils class interface
+ *
+ * @return adLDAPUtils
+ */
+ public function utilities() {
+ if (!$this->utilClass) {
+ $this->utilClass = new adLDAPUtils($this);
+ }
+ return $this->utilClass;
+ }
+
+ /**
+ * The contacts class
+ *
+ * @var adLDAPContacts
+ */
+ protected $contactClass;
+
+ /**
+ * Get the contacts class interface
+ *
+ * @return adLDAPContacts
+ */
+ public function contact() {
+ if (!$this->contactClass) {
+ $this->contactClass = new adLDAPContacts($this);
+ }
+ return $this->contactClass;
+ }
+
+ /**
+ * The exchange class
+ *
+ * @var adLDAPExchange
+ */
+ protected $exchangeClass;
+
+ /**
+ * Get the exchange class interface
+ *
+ * @return adLDAPExchange
+ */
+ public function exchange() {
+ if (!$this->exchangeClass) {
+ $this->exchangeClass = new adLDAPExchange($this);
+ }
+ return $this->exchangeClass;
+ }
+
+ /**
+ * The computers class
+ *
+ * @var adLDAPComputers
+ */
+ protected $computersClass;
+
+ /**
+ * Get the computers class interface
+ *
+ * @return adLDAPComputers
+ */
+ public function computer() {
+ if (!$this->computerClass) {
+ $this->computerClass = new adLDAPComputers($this);
+ }
+ return $this->computerClass;
+ }
+
+ /**
+ * Getters and Setters
+ */
+
+ /**
+ * Set the account suffix
+ *
+ * @param string $accountSuffix
+ * @return void
+ */
+ public function setAccountSuffix($accountSuffix)
+ {
+ $this->accountSuffix = $accountSuffix;
+ }
+
+ /**
+ * Get the account suffix
+ *
+ * @return string
+ */
+ public function getAccountSuffix()
+ {
+ return $this->accountSuffix;
+ }
+
+ /**
+ * Set the domain controllers array
+ *
+ * @param array $domainControllers
+ * @return void
+ */
+ public function setDomainControllers(array $domainControllers)
+ {
+ $this->domainControllers = $domainControllers;
+ }
+
+ /**
+ * Get the list of domain controllers
+ *
+ * @return void
+ */
+ public function getDomainControllers()
+ {
+ return $this->domainControllers;
+ }
+
+ /**
+ * Sets the port number your domain controller communicates over
+ *
+ * @param int $adPort
+ */
+ public function setPort($adPort)
+ {
+ $this->adPort = $adPort;
+ }
+
+ /**
+ * Gets the port number your domain controller communicates over
+ *
+ * @return int
+ */
+ public function getPort()
+ {
+ return $this->adPort;
+ }
+
+ /**
+ * Set the username of an account with higher priviledges
+ *
+ * @param string $adminUsername
+ * @return void
+ */
+ public function setAdminUsername($adminUsername)
+ {
+ $this->adminUsername = $adminUsername;
+ }
+
+ /**
+ * Get the username of the account with higher priviledges
+ *
+ * This will throw an exception for security reasons
+ */
+ public function getAdminUsername()
+ {
+ throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
+ }
+
+ /**
+ * Set the password of an account with higher priviledges
+ *
+ * @param string $adminPassword
+ * @return void
+ */
+ public function setAdminPassword($adminPassword)
+ {
+ $this->adminPassword = $adminPassword;
+ }
+
+ /**
+ * Get the password of the account with higher priviledges
+ *
+ * This will throw an exception for security reasons
+ */
+ public function getAdminPassword()
+ {
+ throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
+ }
+
+ /**
+ * Set whether to detect the true primary group
+ *
+ * @param bool $realPrimaryGroup
+ * @return void
+ */
+ public function setRealPrimaryGroup($realPrimaryGroup)
+ {
+ $this->realPrimaryGroup = $realPrimaryGroup;
+ }
+
+ /**
+ * Get the real primary group setting
+ *
+ * @return bool
+ */
+ public function getRealPrimaryGroup()
+ {
+ return $this->realPrimaryGroup;
+ }
+
+ /**
+ * Set whether to use SSL
+ *
+ * @param bool $useSSL
+ * @return void
+ */
+ public function setUseSSL($useSSL)
+ {
+ $this->useSSL = $useSSL;
+ // Set the default port correctly
+ if($this->useSSL) {
+ $this->setPort(self::ADLDAP_LDAPS_PORT);
+ }
+ else {
+ $this->setPort(self::ADLDAP_LDAP_PORT);
+ }
+ }
+
+ /**
+ * Get the SSL setting
+ *
+ * @return bool
+ */
+ public function getUseSSL()
+ {
+ return $this->useSSL;
+ }
+
+ /**
+ * Set whether to use TLS
+ *
+ * @param bool $useTLS
+ * @return void
+ */
+ public function setUseTLS($useTLS)
+ {
+ $this->useTLS = $useTLS;
+ }
+
+ /**
+ * Get the TLS setting
+ *
+ * @return bool
+ */
+ public function getUseTLS()
+ {
+ return $this->useTLS;
+ }
+
+ /**
+ * Set whether to use SSO
+ * Requires ldap_sasl_bind support. Be sure --with-ldap-sasl is used when configuring PHP otherwise this function will be undefined.
+ *
+ * @param bool $useSSO
+ * @return void
+ */
+ public function setUseSSO($useSSO)
+ {
+ if ($useSSO === true && !$this->ldapSaslSupported()) {
+ throw new adLDAPException('No LDAP SASL support for PHP. See: http://www.php.net/ldap_sasl_bind');
+ }
+ $this->useSSO = $useSSO;
+ }
+
+ /**
+ * Get the SSO setting
+ *
+ * @return bool
+ */
+ public function getUseSSO()
+ {
+ return $this->useSSO;
+ }
+
+ /**
+ * Set whether to lookup recursive groups
+ *
+ * @param bool $recursiveGroups
+ * @return void
+ */
+ public function setRecursiveGroups($recursiveGroups)
+ {
+ $this->recursiveGroups = $recursiveGroups;
+ }
+
+ /**
+ * Get the recursive groups setting
+ *
+ * @return bool
+ */
+ public function getRecursiveGroups()
+ {
+ return $this->recursiveGroups;
+ }
+
+ /**
+ * Default Constructor
+ *
+ * Tries to bind to the AD domain over LDAP or LDAPs
+ *
+ * @param array $options Array of options to pass to the constructor
+ * @throws Exception - if unable to bind to Domain Controller
+ * @return bool
+ */
+ function __construct($options = array()) {
+ // You can specifically overide any of the default configuration options setup above
+ if (count($options) > 0) {
+ if (array_key_exists("account_suffix",$options)){ $this->accountSuffix = $options["account_suffix"]; }
+ if (array_key_exists("base_dn",$options)){ $this->baseDn = $options["base_dn"]; }
+ if (array_key_exists("domain_controllers",$options)){
+ if (!is_array($options["domain_controllers"])) {
+ throw new adLDAPException('[domain_controllers] option must be an array');
+ }
+ $this->domainControllers = $options["domain_controllers"];
+ }
+ if (array_key_exists("admin_username",$options)){ $this->adminUsername = $options["admin_username"]; }
+ if (array_key_exists("admin_password",$options)){ $this->adminPassword = $options["admin_password"]; }
+ if (array_key_exists("real_primarygroup",$options)){ $this->realPrimaryGroup = $options["real_primarygroup"]; }
+ if (array_key_exists("use_ssl",$options)){ $this->setUseSSL($options["use_ssl"]); }
+ if (array_key_exists("use_tls",$options)){ $this->useTLS = $options["use_tls"]; }
+ if (array_key_exists("recursive_groups",$options)){ $this->recursiveGroups = $options["recursive_groups"]; }
+ if (array_key_exists("ad_port",$options)){ $this->setPort($options["ad_port"]); }
+ if (array_key_exists("sso",$options)) {
+ $this->setUseSSO($options["sso"]);
+ if (!$this->ldapSaslSupported()) {
+ $this->setUseSSO(false);
+ }
+ }
+ }
+
+ if ($this->ldapSupported() === false) {
+ throw new adLDAPException('No LDAP support for PHP. See: http://www.php.net/ldap');
+ }
+
+ return $this->connect();
+ }
+
+ /**
+ * Default Destructor
+ *
+ * Closes the LDAP connection
+ *
+ * @return void
+ */
+ function __destruct() {
+ $this->close();
+ }
+
+ /**
+ * Connects and Binds to the Domain Controller
+ *
+ * @return bool
+ */
+ public function connect()
+ {
+ // Connect to the AD/LDAP server as the username/password
+ $domainController = $this->randomController();
+ if ($this->useSSL) {
+ $this->ldapConnection = ldap_connect("ldaps://" . $domainController, $this->adPort);
+ } else {
+ $this->ldapConnection = ldap_connect($domainController, $this->adPort);
+ }
+
+ // Set some ldap options for talking to AD
+ ldap_set_option($this->ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
+ ldap_set_option($this->ldapConnection, LDAP_OPT_REFERRALS, 0);
+
+ if ($this->useTLS) {
+ ldap_start_tls($this->ldapConnection);
+ }
+
+ // Bind as a domain admin if they've set it up
+ if ($this->adminUsername !== NULL && $this->adminPassword !== NULL) {
+ $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix, $this->adminPassword);
+ if (!$this->ldapBind) {
+ if ($this->useSSL && !$this->useTLS) {
+ // If you have problems troubleshooting, remove the @ character from the ldapldapBind command above to get the actual error message
+ throw new adLDAPException('Bind to Active Directory failed. Either the LDAPs connection failed or the login credentials are incorrect. AD said: ' . $this->getLastError());
+ }
+ else {
+ throw new adLDAPException('Bind to Active Directory failed. Check the login credentials and/or server details. AD said: ' . $this->getLastError());
+ }
+ }
+ }
+ if ($this->useSSO && $_SERVER['REMOTE_USER'] && $this->adminUsername === null && $_SERVER['KRB5CCNAME']) {
+ putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
+ $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
+ if (!$this->ldapBind){
+ throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
+ }
+ else {
+ return true;
+ }
+ }
+
+
+ if ($this->baseDn == NULL) {
+ $this->baseDn = $this->findBaseDn();
+ }
+
+ return true;
+ }
+
+ /**
+ * Closes the LDAP connection
+ *
+ * @return void
+ */
+ public function close() {
+ if ($this->ldapConnection) {
+ @ldap_close($this->ldapConnection);
+ }
+ }
+
+ /**
+ * Validate a user's login credentials
+ *
+ * @param string $username A user's AD username
+ * @param string $password A user's AD password
+ * @param bool optional $preventRebind
+ * @return bool
+ */
+ public function authenticate($username, $password, $preventRebind = false) {
+ // Prevent null binding
+ if ($username === NULL || $password === NULL) { return false; }
+ if (empty($username) || empty($password)) { return false; }
+
+ // Allow binding over SSO for Kerberos
+ if ($this->useSSO && $_SERVER['REMOTE_USER'] && $_SERVER['REMOTE_USER'] == $username && $this->adminUsername === NULL && $_SERVER['KRB5CCNAME']) {
+ putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
+ $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
+ if (!$this->ldapBind) {
+ throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
+ }
+ else {
+ return true;
+ }
+ }
+
+ // Bind as the user
+ $ret = true;
+ $this->ldapBind = @ldap_bind($this->ldapConnection, $username . $this->accountSuffix, $password);
+ if (!$this->ldapBind){
+ $ret = false;
+ }
+
+ // Cnce we've checked their details, kick back into admin mode if we have it
+ if ($this->adminUsername !== NULL && !$preventRebind) {
+ $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix , $this->adminPassword);
+ if (!$this->ldapBind){
+ // This should never happen in theory
+ throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Find the Base DN of your domain controller
+ *
+ * @return string
+ */
+ public function findBaseDn()
+ {
+ $namingContext = $this->getRootDse(array('defaultnamingcontext'));
+ return $namingContext[0]['defaultnamingcontext'][0];
+ }
+
+ /**
+ * Get the RootDSE properties from a domain controller
+ *
+ * @param array $attributes The attributes you wish to query e.g. defaultnamingcontext
+ * @return array
+ */
+ public function getRootDse($attributes = array("*", "+")) {
+ if (!$this->ldapBind){ return (false); }
+
+ $sr = @ldap_read($this->ldapConnection, NULL, 'objectClass=*', $attributes);
+ $entries = @ldap_get_entries($this->ldapConnection, $sr);
+ return $entries;
+ }
+
+ /**
+ * Get last error from Active Directory
+ *
+ * This function gets the last message from Active Directory
+ * This may indeed be a 'Success' message but if you get an unknown error
+ * it might be worth calling this function to see what errors were raised
+ *
+ * return string
+ */
+ public function getLastError() {
+ return @ldap_error($this->ldapConnection);
+ }
+
+ /**
+ * Detect LDAP support in php
+ *
+ * @return bool
+ */
+ protected function ldapSupported()
+ {
+ if (!function_exists('ldap_connect')) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Detect ldap_sasl_bind support in PHP
+ *
+ * @return bool
+ */
+ protected function ldapSaslSupported()
+ {
+ if (!function_exists('ldap_sasl_bind')) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Schema
+ *
+ * @param array $attributes Attributes to be queried
+ * @return array
+ */
+ public function adldap_schema($attributes){
+
+ // LDAP doesn't like NULL attributes, only set them if they have values
+ // If you wish to remove an attribute you should set it to a space
+ // TO DO: Adapt user_modify to use ldap_mod_delete to remove a NULL attribute
+ $mod=array();
+
+ // Check every attribute to see if it contains 8bit characters and then UTF8 encode them
+ array_walk($attributes, array($this, 'encode8bit'));
+
+ if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; }
+ if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; }
+ //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes?
+ if ($attributes["address_country"]){ $mod["c"][0]=$attributes["address_country"]; }
+ if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; }
+ if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; }
+ if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; }
+ if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; }
+ if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; }
+ if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; }
+ if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; }
+ if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; }
+ if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; }
+ if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format?
+ if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; }
+ if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; }
+ if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; }
+ if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; }
+ if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; }
+ if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; } //UNTESTED ***Use DistinguishedName***
+ if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; }
+ if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->user()->encodePassword($attributes["password"]); }
+ if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; }
+ if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; }
+ if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; }
+ if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; }
+ if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; }
+ if ($attributes["mobile"]){ $mod["mobile"][0]=$attributes["mobile"]; }
+ if ($attributes["pager"]){ $mod["pager"][0]=$attributes["pager"]; }
+ if ($attributes["ipphone"]){ $mod["ipphone"][0]=$attributes["ipphone"]; }
+ if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; }
+ if ($attributes["fax"]){ $mod["facsimileTelephoneNumber"][0]=$attributes["fax"]; }
+ if ($attributes["enabled"]){ $mod["userAccountControl"][0]=$attributes["enabled"]; }
+ if ($attributes["homephone"]){ $mod["homephone"][0]=$attributes["homephone"]; }
+
+ // Distribution List specific schema
+ if ($attributes["group_sendpermission"]){ $mod["dlMemSubmitPerms"][0]=$attributes["group_sendpermission"]; }
+ if ($attributes["group_rejectpermission"]){ $mod["dlMemRejectPerms"][0]=$attributes["group_rejectpermission"]; }
+
+ // Exchange Schema
+ if ($attributes["exchange_homemdb"]){ $mod["homeMDB"][0]=$attributes["exchange_homemdb"]; }
+ if ($attributes["exchange_mailnickname"]){ $mod["mailNickname"][0]=$attributes["exchange_mailnickname"]; }
+ if ($attributes["exchange_proxyaddress"]){ $mod["proxyAddresses"][0]=$attributes["exchange_proxyaddress"]; }
+ if ($attributes["exchange_usedefaults"]){ $mod["mDBUseDefaults"][0]=$attributes["exchange_usedefaults"]; }
+ if ($attributes["exchange_policyexclude"]){ $mod["msExchPoliciesExcluded"][0]=$attributes["exchange_policyexclude"]; }
+ if ($attributes["exchange_policyinclude"]){ $mod["msExchPoliciesIncluded"][0]=$attributes["exchange_policyinclude"]; }
+ if ($attributes["exchange_addressbook"]){ $mod["showInAddressBook"][0]=$attributes["exchange_addressbook"]; }
+ if ($attributes["exchange_altrecipient"]){ $mod["altRecipient"][0]=$attributes["exchange_altrecipient"]; }
+ if ($attributes["exchange_deliverandredirect"]){ $mod["deliverAndRedirect"][0]=$attributes["exchange_deliverandredirect"]; }
+
+ // This schema is designed for contacts
+ if ($attributes["exchange_hidefromlists"]){ $mod["msExchHideFromAddressLists"][0]=$attributes["exchange_hidefromlists"]; }
+ if ($attributes["contact_email"]){ $mod["targetAddress"][0]=$attributes["contact_email"]; }
+
+ //echo ("<pre>"); print_r($mod);
+ /*
+ // modifying a name is a bit fiddly
+ if ($attributes["firstname"] && $attributes["surname"]){
+ $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
+ $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
+ $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
+ }
+ */
+
+ if (count($mod)==0){ return (false); }
+ return ($mod);
+ }
+
+ /**
+ * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
+ */
+ protected function encode8Bit(&$item, $key) {
+ $encode = false;
+ if (is_string($item)) {
+ for ($i=0; $i<strlen($item); $i++) {
+ if (ord($item[$i]) >> 7) {
+ $encode = true;
+ }
+ }
+ }
+ if ($encode === true && $key != 'password') {
+ $item = utf8_encode($item);
+ }
+ }
+
+ /**
+ * Select a random domain controller from your domain controller array
+ *
+ * @return string
+ */
+ protected function randomController()
+ {
+ mt_srand(doubleval(microtime()) * 100000000); // For older PHP versions
+ /*if (sizeof($this->domainControllers) > 1) {
+ $adController = $this->domainControllers[array_rand($this->domainControllers)];
+ // Test if the controller is responding to pings
+ $ping = $this->pingController($adController);
+ if ($ping === false) {
+ // Find the current key in the domain controllers array
+ $key = array_search($adController, $this->domainControllers);
+ // Remove it so that we don't end up in a recursive loop
+ unset($this->domainControllers[$key]);
+ // Select a new controller
+ return $this->randomController();
+ }
+ else {
+ return ($adController);
+ }
+ } */
+ return $this->domainControllers[array_rand($this->domainControllers)];
+ }
+
+ /**
+ * Test basic connectivity to controller
+ *
+ * @return bool
+ */
+ protected function pingController($host) {
+ $port = $this->adPort;
+ fsockopen($host, $port, $errno, $errstr, 10);
+ if ($errno > 0) {
+ return false;
+ }
+ return true;
+ }
+
+}
+
+/**
+* adLDAP Exception Handler
+*
+* Exceptions of this type are thrown on bind failure or when SSL is required but not configured
+* Example:
+* try {
+* $adldap = new adLDAP();
+* }
+* catch (adLDAPException $e) {
+* echo $e;
+* exit();
+* }
+*/
+class adLDAPException extends Exception {}
+
?> \ No newline at end of file
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php b/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php
index 71b24a04f..aabd88fa5 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php
@@ -1,153 +1,153 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Computers
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-require_once(dirname(__FILE__) . '/../collections/adLDAPComputerCollection.php');
-
-/**
-* COMPUTER MANAGEMENT FUNCTIONS
-*/
-class adLDAPComputers {
-
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
- /**
- * Get information about a specific computer. Returned in a raw array format from AD
- *
- * @param string $computerName The name of the computer
- * @param array $fields Attributes to return
- * @return array
- */
- public function info($computerName, $fields = NULL)
- {
- if ($computerName === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $filter = "(&(objectClass=computer)(cn=" . $computerName . "))";
- if ($fields === NULL) {
- $fields = array("memberof","cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion");
- }
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- return $entries;
- }
-
- /**
- * Find information about the computers. Returned in a raw array format from AD
- *
- * @param string $computerName The name of the computer
- * @param array $fields Array of parameters to query
- * @return mixed
- */
- public function infoCollection($computerName, $fields = NULL)
- {
- if ($computerName === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $info = $this->info($computerName, $fields);
-
- if ($info !== false) {
- $collection = new adLDAPComputerCollection($info, $this->adldap);
- return $collection;
- }
- return false;
- }
-
- /**
- * Check if a computer is in a group
- *
- * @param string $computerName The name of the computer
- * @param string $group The group to check
- * @param bool $recursive Whether to check recursively
- * @return array
- */
- public function inGroup($computerName, $group, $recursive = NULL)
- {
- if ($computerName === NULL) { return false; }
- if ($group === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // use the default option if they haven't set it
-
- //get a list of the groups
- $groups = $this->groups($computerName, array("memberof"), $recursive);
-
- //return true if the specified group is in the group list
- if (in_array($group, $groups)){
- return true;
- }
-
- return false;
- }
-
- /**
- * Get the groups a computer is in
- *
- * @param string $computerName The name of the computer
- * @param bool $recursive Whether to check recursively
- * @return array
- */
- public function groups($computerName, $recursive = NULL)
- {
- if ($computerName === NULL) { return false; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
- if (!$this->adldap->getLdapBind()){ return false; }
-
- //search the directory for their information
- $info = @$this->info($computerName, array("memberof", "primarygroupid"));
- $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our guy (unique usernames)
-
- if ($recursive === true) {
- foreach ($groups as $id => $groupName){
- $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
- $groups = array_merge($groups, $extraGroups);
- }
- }
-
- return $groups;
- }
-
-}
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Computers
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+require_once(dirname(__FILE__) . '/../collections/adLDAPComputerCollection.php');
+
+/**
+* COMPUTER MANAGEMENT FUNCTIONS
+*/
+class adLDAPComputers {
+
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+ /**
+ * Get information about a specific computer. Returned in a raw array format from AD
+ *
+ * @param string $computerName The name of the computer
+ * @param array $fields Attributes to return
+ * @return array
+ */
+ public function info($computerName, $fields = NULL)
+ {
+ if ($computerName === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $filter = "(&(objectClass=computer)(cn=" . $computerName . "))";
+ if ($fields === NULL) {
+ $fields = array("memberof","cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion");
+ }
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ return $entries;
+ }
+
+ /**
+ * Find information about the computers. Returned in a raw array format from AD
+ *
+ * @param string $computerName The name of the computer
+ * @param array $fields Array of parameters to query
+ * @return mixed
+ */
+ public function infoCollection($computerName, $fields = NULL)
+ {
+ if ($computerName === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $info = $this->info($computerName, $fields);
+
+ if ($info !== false) {
+ $collection = new adLDAPComputerCollection($info, $this->adldap);
+ return $collection;
+ }
+ return false;
+ }
+
+ /**
+ * Check if a computer is in a group
+ *
+ * @param string $computerName The name of the computer
+ * @param string $group The group to check
+ * @param bool $recursive Whether to check recursively
+ * @return array
+ */
+ public function inGroup($computerName, $group, $recursive = NULL)
+ {
+ if ($computerName === NULL) { return false; }
+ if ($group === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // use the default option if they haven't set it
+
+ //get a list of the groups
+ $groups = $this->groups($computerName, array("memberof"), $recursive);
+
+ //return true if the specified group is in the group list
+ if (in_array($group, $groups)){
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the groups a computer is in
+ *
+ * @param string $computerName The name of the computer
+ * @param bool $recursive Whether to check recursively
+ * @return array
+ */
+ public function groups($computerName, $recursive = NULL)
+ {
+ if ($computerName === NULL) { return false; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
+ if (!$this->adldap->getLdapBind()){ return false; }
+
+ //search the directory for their information
+ $info = @$this->info($computerName, array("memberof", "primarygroupid"));
+ $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our guy (unique usernames)
+
+ if ($recursive === true) {
+ foreach ($groups as $id => $groupName){
+ $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
+ $groups = array_merge($groups, $extraGroups);
+ }
+ }
+
+ return $groups;
+ }
+
+}
?> \ No newline at end of file
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php b/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php
index addd3e5f0..42a0d756b 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php
@@ -1,294 +1,294 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Contacts
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-require_once(dirname(__FILE__) . '/../collections/adLDAPContactCollection.php');
-
-class adLDAPContacts {
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
- //*****************************************************************************************************************
- // CONTACT FUNCTIONS
- // * Still work to do in this area, and new functions to write
-
- /**
- * Create a contact
- *
- * @param array $attributes The attributes to set to the contact
- * @return bool
- */
- public function create($attributes)
- {
- // Check for compulsory fields
- if (!array_key_exists("display_name", $attributes)) { return "Missing compulsory field [display_name]"; }
- if (!array_key_exists("email", $attributes)) { return "Missing compulsory field [email]"; }
- if (!array_key_exists("container", $attributes)) { return "Missing compulsory field [container]"; }
- if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
-
- // Translate the schema
- $add = $this->adldap->adldap_schema($attributes);
-
- // Additional stuff only used for adding contacts
- $add["cn"][0] = $attributes["display_name"];
- $add["objectclass"][0] = "top";
- $add["objectclass"][1] = "person";
- $add["objectclass"][2] = "organizationalPerson";
- $add["objectclass"][3] = "contact";
- if (!isset($attributes['exchange_hidefromlists'])) {
- $add["msExchHideFromAddressLists"][0] = "TRUE";
- }
-
- // Determine the container
- $attributes["container"] = array_reverse($attributes["container"]);
- $container= "OU=" . implode(",OU=", $attributes["container"]);
-
- // Add the entry
- $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $this->adldap->utilities()->escapeCharacters($add["cn"][0]) . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
- if ($result != true) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Determine the list of groups a contact is a member of
- *
- * @param string $distinguisedname The full DN of a contact
- * @param bool $recursive Recursively check groups
- * @return array
- */
- public function groups($distinguishedName, $recursive = NULL)
- {
- if ($distinguishedName === NULL) { return false; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
- if (!$this->adldap->getLdapBind()){ return false; }
-
- // Search the directory for their information
- $info = @$this->info($distinguishedName, array("memberof", "primarygroupid"));
- $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our contact
-
- if ($recursive === true){
- foreach ($groups as $id => $groupName){
- $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
- $groups = array_merge($groups, $extraGroups);
- }
- }
-
- return $groups;
- }
-
- /**
- * Get contact information. Returned in a raw array format from AD
- *
- * @param string $distinguisedname The full DN of a contact
- * @param array $fields Attributes to be returned
- * @return array
- */
- public function info($distinguishedName, $fields = NULL)
- {
- if ($distinguishedName === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $filter = "distinguishedName=" . $distinguishedName;
- if ($fields === NULL) {
- $fields = array("distinguishedname", "mail", "memberof", "department", "displayname", "telephonenumber", "primarygroupid", "objectsid");
- }
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- if ($entries[0]['count'] >= 1) {
- // AD does not return the primary group in the ldap query, we may need to fudge it
- if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["primarygroupid"][0])){
- //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
- $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
- } else {
- $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
- }
- }
-
- $entries[0]["memberof"]["count"]++;
- return $entries;
- }
-
- /**
- * Find information about the contacts. Returned in a raw array format from AD
- *
- * @param string $distinguishedName The full DN of a contact
- * @param array $fields Array of parameters to query
- * @return mixed
- */
- public function infoCollection($distinguishedName, $fields = NULL)
- {
- if ($distinguishedName === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $info = $this->info($distinguishedName, $fields);
-
- if ($info !== false) {
- $collection = new adLDAPContactCollection($info, $this->adldap);
- return $collection;
- }
- return false;
- }
-
- /**
- * Determine if a contact is a member of a group
- *
- * @param string $distinguisedName The full DN of a contact
- * @param string $group The group name to query
- * @param bool $recursive Recursively check groups
- * @return bool
- */
- public function inGroup($distinguisedName, $group, $recursive = NULL)
- {
- if ($distinguisedName === NULL) { return false; }
- if ($group === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
-
- // Get a list of the groups
- $groups = $this->groups($distinguisedName, array("memberof"), $recursive);
-
- // Return true if the specified group is in the group list
- if (in_array($group, $groups)){
- return true;
- }
-
- return false;
- }
-
- /**
- * Modify a contact
- *
- * @param string $distinguishedName The contact to query
- * @param array $attributes The attributes to modify. Note if you set the enabled attribute you must not specify any other attributes
- * @return bool
- */
- public function modify($distinguishedName, $attributes) {
- if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedname]"; }
-
- // Translate the update to the LDAP schema
- $mod = $this->adldap->adldap_schema($attributes);
-
- // Check to see if this is an enabled status update
- if (!$mod) {
- return false;
- }
-
- // Do the update
- $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Delete a contact
- *
- * @param string $distinguishedName The contact dn to delete (please be careful here!)
- * @return array
- */
- public function delete($distinguishedName)
- {
- $result = $this->folder()->delete($distinguishedName);
- if ($result != true) {
- return false;
- }
- return true;
- }
-
- /**
- * Return a list of all contacts
- *
- * @param bool $includeDescription Include a description of a contact
- * @param string $search The search parameters
- * @param bool $sorted Whether to sort the results
- * @return array
- */
- public function all($includeDescription = false, $search = "*", $sorted = true) {
- if (!$this->adldap->getLdapBind()) { return false; }
-
- // Perform the search and grab all their details
- $filter = "(&(objectClass=contact)(cn=" . $search . "))";
- $fields = array("displayname","distinguishedname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- $usersArray = array();
- for ($i=0; $i<$entries["count"]; $i++){
- if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
- $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["displayname"][0];
- } elseif ($includeDescription){
- $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["distinguishedname"][0];
- } else {
- array_push($usersArray, $entries[$i]["distinguishedname"][0]);
- }
- }
- if ($sorted) {
- asort($usersArray);
- }
- return $usersArray;
- }
-
- /**
- * Mail enable a contact
- * Allows email to be sent to them through Exchange
- *
- * @param string $distinguishedname The contact to mail enable
- * @param string $emailaddress The email address to allow emails to be sent through
- * @param string $mailnickname The mailnickname for the contact in Exchange. If NULL this will be set to the display name
- * @return bool
- */
- public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL){
- return $this->adldap->exchange()->contactMailEnable($distinguishedName, $emailAddress, $mailNickname);
- }
-
-
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Contacts
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+require_once(dirname(__FILE__) . '/../collections/adLDAPContactCollection.php');
+
+class adLDAPContacts {
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+ //*****************************************************************************************************************
+ // CONTACT FUNCTIONS
+ // * Still work to do in this area, and new functions to write
+
+ /**
+ * Create a contact
+ *
+ * @param array $attributes The attributes to set to the contact
+ * @return bool
+ */
+ public function create($attributes)
+ {
+ // Check for compulsory fields
+ if (!array_key_exists("display_name", $attributes)) { return "Missing compulsory field [display_name]"; }
+ if (!array_key_exists("email", $attributes)) { return "Missing compulsory field [email]"; }
+ if (!array_key_exists("container", $attributes)) { return "Missing compulsory field [container]"; }
+ if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
+
+ // Translate the schema
+ $add = $this->adldap->adldap_schema($attributes);
+
+ // Additional stuff only used for adding contacts
+ $add["cn"][0] = $attributes["display_name"];
+ $add["objectclass"][0] = "top";
+ $add["objectclass"][1] = "person";
+ $add["objectclass"][2] = "organizationalPerson";
+ $add["objectclass"][3] = "contact";
+ if (!isset($attributes['exchange_hidefromlists'])) {
+ $add["msExchHideFromAddressLists"][0] = "TRUE";
+ }
+
+ // Determine the container
+ $attributes["container"] = array_reverse($attributes["container"]);
+ $container= "OU=" . implode(",OU=", $attributes["container"]);
+
+ // Add the entry
+ $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $this->adldap->utilities()->escapeCharacters($add["cn"][0]) . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
+ if ($result != true) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Determine the list of groups a contact is a member of
+ *
+ * @param string $distinguisedname The full DN of a contact
+ * @param bool $recursive Recursively check groups
+ * @return array
+ */
+ public function groups($distinguishedName, $recursive = NULL)
+ {
+ if ($distinguishedName === NULL) { return false; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
+ if (!$this->adldap->getLdapBind()){ return false; }
+
+ // Search the directory for their information
+ $info = @$this->info($distinguishedName, array("memberof", "primarygroupid"));
+ $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our contact
+
+ if ($recursive === true){
+ foreach ($groups as $id => $groupName){
+ $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
+ $groups = array_merge($groups, $extraGroups);
+ }
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Get contact information. Returned in a raw array format from AD
+ *
+ * @param string $distinguisedname The full DN of a contact
+ * @param array $fields Attributes to be returned
+ * @return array
+ */
+ public function info($distinguishedName, $fields = NULL)
+ {
+ if ($distinguishedName === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $filter = "distinguishedName=" . $distinguishedName;
+ if ($fields === NULL) {
+ $fields = array("distinguishedname", "mail", "memberof", "department", "displayname", "telephonenumber", "primarygroupid", "objectsid");
+ }
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ if ($entries[0]['count'] >= 1) {
+ // AD does not return the primary group in the ldap query, we may need to fudge it
+ if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["primarygroupid"][0])){
+ //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
+ $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
+ } else {
+ $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
+ }
+ }
+
+ $entries[0]["memberof"]["count"]++;
+ return $entries;
+ }
+
+ /**
+ * Find information about the contacts. Returned in a raw array format from AD
+ *
+ * @param string $distinguishedName The full DN of a contact
+ * @param array $fields Array of parameters to query
+ * @return mixed
+ */
+ public function infoCollection($distinguishedName, $fields = NULL)
+ {
+ if ($distinguishedName === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $info = $this->info($distinguishedName, $fields);
+
+ if ($info !== false) {
+ $collection = new adLDAPContactCollection($info, $this->adldap);
+ return $collection;
+ }
+ return false;
+ }
+
+ /**
+ * Determine if a contact is a member of a group
+ *
+ * @param string $distinguisedName The full DN of a contact
+ * @param string $group The group name to query
+ * @param bool $recursive Recursively check groups
+ * @return bool
+ */
+ public function inGroup($distinguisedName, $group, $recursive = NULL)
+ {
+ if ($distinguisedName === NULL) { return false; }
+ if ($group === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
+
+ // Get a list of the groups
+ $groups = $this->groups($distinguisedName, array("memberof"), $recursive);
+
+ // Return true if the specified group is in the group list
+ if (in_array($group, $groups)){
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Modify a contact
+ *
+ * @param string $distinguishedName The contact to query
+ * @param array $attributes The attributes to modify. Note if you set the enabled attribute you must not specify any other attributes
+ * @return bool
+ */
+ public function modify($distinguishedName, $attributes) {
+ if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedname]"; }
+
+ // Translate the update to the LDAP schema
+ $mod = $this->adldap->adldap_schema($attributes);
+
+ // Check to see if this is an enabled status update
+ if (!$mod) {
+ return false;
+ }
+
+ // Do the update
+ $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Delete a contact
+ *
+ * @param string $distinguishedName The contact dn to delete (please be careful here!)
+ * @return array
+ */
+ public function delete($distinguishedName)
+ {
+ $result = $this->folder()->delete($distinguishedName);
+ if ($result != true) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return a list of all contacts
+ *
+ * @param bool $includeDescription Include a description of a contact
+ * @param string $search The search parameters
+ * @param bool $sorted Whether to sort the results
+ * @return array
+ */
+ public function all($includeDescription = false, $search = "*", $sorted = true) {
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ // Perform the search and grab all their details
+ $filter = "(&(objectClass=contact)(cn=" . $search . "))";
+ $fields = array("displayname","distinguishedname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ $usersArray = array();
+ for ($i=0; $i<$entries["count"]; $i++){
+ if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
+ $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["displayname"][0];
+ } elseif ($includeDescription){
+ $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["distinguishedname"][0];
+ } else {
+ array_push($usersArray, $entries[$i]["distinguishedname"][0]);
+ }
+ }
+ if ($sorted) {
+ asort($usersArray);
+ }
+ return $usersArray;
+ }
+
+ /**
+ * Mail enable a contact
+ * Allows email to be sent to them through Exchange
+ *
+ * @param string $distinguishedname The contact to mail enable
+ * @param string $emailaddress The email address to allow emails to be sent through
+ * @param string $mailnickname The mailnickname for the contact in Exchange. If NULL this will be set to the display name
+ * @return bool
+ */
+ public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL){
+ return $this->adldap->exchange()->contactMailEnable($distinguishedName, $emailAddress, $mailNickname);
+ }
+
+
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php b/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php
index dd0c6de05..d70aac779 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php
@@ -1,390 +1,390 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Exchange
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-
-/**
-* MICROSOFT EXCHANGE FUNCTIONS
-*/
-class adLDAPExchange {
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
- /**
- * Create an Exchange account
- *
- * @param string $username The username of the user to add the Exchange account to
- * @param array $storageGroup The mailbox, Exchange Storage Group, for the user account, this must be a full CN
- * If the storage group has a different base_dn to the adLDAP configuration, set it using $base_dn
- * @param string $emailAddress The primary email address to add to this user
- * @param string $mailNickname The mail nick name. If mail nickname is blank, the username will be used
- * @param bool $mdbUseDefaults Indicates whether the store should use the default quota, rather than the per-mailbox quota.
- * @param string $baseDn Specify an alternative base_dn for the Exchange storage group
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function createMailbox($username, $storageGroup, $emailAddress, $mailNickname=NULL, $useDefaults=TRUE, $baseDn=NULL, $isGUID=false)
- {
- if ($username === NULL){ return "Missing compulsory field [username]"; }
- if ($storageGroup === NULL) { return "Missing compulsory array [storagegroup]"; }
- if (!is_array($storageGroup)) { return "[storagegroup] must be an array"; }
- if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }
-
- if ($baseDn === NULL) {
- $baseDn = $this->adldap->getBaseDn();
- }
-
- $container = "CN=" . implode(",CN=", $storageGroup);
-
- if ($mailNickname === NULL) {
- $mailNickname = $username;
- }
- $mdbUseDefaults = $this->adldap->utilities()->boolToString($useDefaults);
-
- $attributes = array(
- 'exchange_homemdb'=>$container.",".$baseDn,
- 'exchange_proxyaddress'=>'SMTP:' . $emailAddress,
- 'exchange_mailnickname'=>$mailNickname,
- 'exchange_usedefaults'=>$mdbUseDefaults
- );
- $result = $this->adldap->user()->modify($username, $attributes, $isGUID);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Add an X400 address to Exchange
- * See http://tools.ietf.org/html/rfc1685 for more information.
- * An X400 Address looks similar to this X400:c=US;a= ;p=Domain;o=Organization;s=Doe;g=John;
- *
- * @param string $username The username of the user to add the X400 to to
- * @param string $country Country
- * @param string $admd Administration Management Domain
- * @param string $pdmd Private Management Domain (often your AD domain)
- * @param string $org Organization
- * @param string $surname Surname
- * @param string $givenName Given name
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function addX400($username, $country, $admd, $pdmd, $org, $surname, $givenName, $isGUID=false)
- {
- if ($username === NULL){ return "Missing compulsory field [username]"; }
-
- $proxyValue = 'X400:';
-
- // Find the dn of the user
- $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
- if ($user[0]["dn"] === NULL) { return false; }
- $userDn = $user[0]["dn"];
-
- // We do not have to demote an email address from the default so we can just add the new proxy address
- $attributes['exchange_proxyaddress'] = $proxyValue . 'c=' . $country . ';a=' . $admd . ';p=' . $pdmd . ';o=' . $org . ';s=' . $surname . ';g=' . $givenName . ';';
-
- // Translate the update to the LDAP schema
- $add = $this->adldap->adldap_schema($attributes);
-
- if (!$add) { return false; }
-
- // Do the update
- // Take out the @ to see any errors, usually this error might occur because the address already
- // exists in the list of proxyAddresses
- $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn, $add);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Add an address to Exchange
- *
- * @param string $username The username of the user to add the Exchange account to
- * @param string $emailAddress The email address to add to this user
- * @param bool $default Make this email address the default address, this is a bit more intensive as we have to demote any existing default addresses
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function addAddress($username, $emailAddress, $default = FALSE, $isGUID = false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
-
- $proxyValue = 'smtp:';
- if ($default === true) {
- $proxyValue = 'SMTP:';
- }
-
- // Find the dn of the user
- $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
- if ($user[0]["dn"] === NULL){ return false; }
- $userDn = $user[0]["dn"];
-
- // We need to scan existing proxy addresses and demote the default one
- if (is_array($user[0]["proxyaddresses"]) && $default === true) {
- $modAddresses = array();
- for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) {
- if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false) {
- $user[0]['proxyaddresses'][$i] = str_replace('SMTP:', 'smtp:', $user[0]['proxyaddresses'][$i]);
- }
- if ($user[0]['proxyaddresses'][$i] != '') {
- $modAddresses['proxyAddresses'][$i] = $user[0]['proxyaddresses'][$i];
- }
- }
- $modAddresses['proxyAddresses'][(sizeof($user[0]['proxyaddresses'])-1)] = 'SMTP:' . $emailAddress;
-
- $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $modAddresses);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
- else {
- // We do not have to demote an email address from the default so we can just add the new proxy address
- $attributes['exchange_proxyaddress'] = $proxyValue . $emailAddress;
-
- // Translate the update to the LDAP schema
- $add = $this->adldap->adldap_schema($attributes);
-
- if (!$add) {
- return false;
- }
-
- // Do the update
- // Take out the @ to see any errors, usually this error might occur because the address already
- // exists in the list of proxyAddresses
- $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn,$add);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
- }
-
- /**
- * Remove an address to Exchange
- * If you remove a default address the account will no longer have a default,
- * we recommend changing the default address first
- *
- * @param string $username The username of the user to add the Exchange account to
- * @param string $emailAddress The email address to add to this user
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function deleteAddress($username, $emailAddress, $isGUID=false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
-
- // Find the dn of the user
- $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
- if ($user[0]["dn"] === NULL) { return false; }
- $userDn = $user[0]["dn"];
-
- if (is_array($user[0]["proxyaddresses"])) {
- $mod = array();
- for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) {
- if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false && $user[0]['proxyaddresses'][$i] == 'SMTP:' . $emailAddress) {
- $mod['proxyAddresses'][0] = 'SMTP:' . $emailAddress;
- }
- elseif (strstr($user[0]['proxyaddresses'][$i], 'smtp:') !== false && $user[0]['proxyaddresses'][$i] == 'smtp:' . $emailAddress) {
- $mod['proxyAddresses'][0] = 'smtp:' . $emailAddress;
- }
- }
-
- $result = @ldap_mod_del($this->adldap->getLdapConnection(), $userDn,$mod);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
- else {
- return false;
- }
- }
- /**
- * Change the default address
- *
- * @param string $username The username of the user to add the Exchange account to
- * @param string $emailAddress The email address to make default
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function primaryAddress($username, $emailAddress, $isGUID = false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
-
- // Find the dn of the user
- $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
- if ($user[0]["dn"] === NULL){ return false; }
- $userDn = $user[0]["dn"];
-
- if (is_array($user[0]["proxyaddresses"])) {
- $modAddresses = array();
- for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) {
- if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false) {
- $user[0]['proxyaddresses'][$i] = str_replace('SMTP:', 'smtp:', $user[0]['proxyaddresses'][$i]);
- }
- if ($user[0]['proxyaddresses'][$i] == 'smtp:' . $emailAddress) {
- $user[0]['proxyaddresses'][$i] = str_replace('smtp:', 'SMTP:', $user[0]['proxyaddresses'][$i]);
- }
- if ($user[0]['proxyaddresses'][$i] != '') {
- $modAddresses['proxyAddresses'][$i] = $user[0]['proxyaddresses'][$i];
- }
- }
-
- $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $modAddresses);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
-
- }
-
- /**
- * Mail enable a contact
- * Allows email to be sent to them through Exchange
- *
- * @param string $distinguishedName The contact to mail enable
- * @param string $emailAddress The email address to allow emails to be sent through
- * @param string $mailNickname The mailnickname for the contact in Exchange. If NULL this will be set to the display name
- * @return bool
- */
- public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL)
- {
- if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedName]"; }
- if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }
-
- if ($mailNickname !== NULL) {
- // Find the dn of the user
- $user = $this->adldap->contact()->info($distinguishedName, array("cn","displayname"));
- if ($user[0]["displayname"] === NULL) { return false; }
- $mailNickname = $user[0]['displayname'][0];
- }
-
- $attributes = array("email"=>$emailAddress,"contact_email"=>"SMTP:" . $emailAddress,"exchange_proxyaddress"=>"SMTP:" . $emailAddress,"exchange_mailnickname" => $mailNickname);
-
- // Translate the update to the LDAP schema
- $mod = $this->adldap->adldap_schema($attributes);
-
- // Check to see if this is an enabled status update
- if (!$mod) { return false; }
-
- // Do the update
- $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
- if ($result == false) { return false; }
-
- return true;
- }
-
- /**
- * Returns a list of Exchange Servers in the ConfigurationNamingContext of the domain
- *
- * @param array $attributes An array of the AD attributes you wish to return
- * @return array
- */
- public function servers($attributes = array('cn','distinguishedname','serialnumber'))
- {
- if (!$this->adldap->getLdapBind()){ return false; }
-
- $configurationNamingContext = $this->adldap->getRootDse(array('configurationnamingcontext'));
- $sr = @ldap_search($this->adldap->getLdapConnection(), $configurationNamingContext[0]['configurationnamingcontext'][0],'(&(objectCategory=msExchExchangeServer))', $attributes);
- $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- return $entries;
- }
-
- /**
- * Returns a list of Storage Groups in Exchange for a given mail server
- *
- * @param string $exchangeServer The full DN of an Exchange server. You can use exchange_servers() to find the DN for your server
- * @param array $attributes An array of the AD attributes you wish to return
- * @param bool $recursive If enabled this will automatically query the databases within a storage group
- * @return array
- */
- public function storageGroups($exchangeServer, $attributes = array('cn','distinguishedname'), $recursive = NULL)
- {
- if (!$this->adldap->getLdapBind()){ return false; }
- if ($exchangeServer === NULL) { return "Missing compulsory field [exchangeServer]"; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); }
-
- $filter = '(&(objectCategory=msExchStorageGroup))';
- $sr = @ldap_search($this->adldap->getLdapConnection(), $exchangeServer, $filter, $attributes);
- $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- if ($recursive === true) {
- for ($i=0; $i<$entries['count']; $i++) {
- $entries[$i]['msexchprivatemdb'] = $this->storageDatabases($entries[$i]['distinguishedname'][0]);
- }
- }
-
- return $entries;
- }
-
- /**
- * Returns a list of Databases within any given storage group in Exchange for a given mail server
- *
- * @param string $storageGroup The full DN of an Storage Group. You can use exchange_storage_groups() to find the DN
- * @param array $attributes An array of the AD attributes you wish to return
- * @return array
- */
- public function storageDatabases($storageGroup, $attributes = array('cn','distinguishedname','displayname')) {
- if (!$this->adldap->getLdapBind()){ return false; }
- if ($storageGroup === NULL) { return "Missing compulsory field [storageGroup]"; }
-
- $filter = '(&(objectCategory=msExchPrivateMDB))';
- $sr = @ldap_search($this->adldap->getLdapConnection(), $storageGroup, $filter, $attributes);
- $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- return $entries;
- }
-}
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Exchange
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+
+/**
+* MICROSOFT EXCHANGE FUNCTIONS
+*/
+class adLDAPExchange {
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+ /**
+ * Create an Exchange account
+ *
+ * @param string $username The username of the user to add the Exchange account to
+ * @param array $storageGroup The mailbox, Exchange Storage Group, for the user account, this must be a full CN
+ * If the storage group has a different base_dn to the adLDAP configuration, set it using $base_dn
+ * @param string $emailAddress The primary email address to add to this user
+ * @param string $mailNickname The mail nick name. If mail nickname is blank, the username will be used
+ * @param bool $mdbUseDefaults Indicates whether the store should use the default quota, rather than the per-mailbox quota.
+ * @param string $baseDn Specify an alternative base_dn for the Exchange storage group
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function createMailbox($username, $storageGroup, $emailAddress, $mailNickname=NULL, $useDefaults=TRUE, $baseDn=NULL, $isGUID=false)
+ {
+ if ($username === NULL){ return "Missing compulsory field [username]"; }
+ if ($storageGroup === NULL) { return "Missing compulsory array [storagegroup]"; }
+ if (!is_array($storageGroup)) { return "[storagegroup] must be an array"; }
+ if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }
+
+ if ($baseDn === NULL) {
+ $baseDn = $this->adldap->getBaseDn();
+ }
+
+ $container = "CN=" . implode(",CN=", $storageGroup);
+
+ if ($mailNickname === NULL) {
+ $mailNickname = $username;
+ }
+ $mdbUseDefaults = $this->adldap->utilities()->boolToString($useDefaults);
+
+ $attributes = array(
+ 'exchange_homemdb'=>$container.",".$baseDn,
+ 'exchange_proxyaddress'=>'SMTP:' . $emailAddress,
+ 'exchange_mailnickname'=>$mailNickname,
+ 'exchange_usedefaults'=>$mdbUseDefaults
+ );
+ $result = $this->adldap->user()->modify($username, $attributes, $isGUID);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Add an X400 address to Exchange
+ * See http://tools.ietf.org/html/rfc1685 for more information.
+ * An X400 Address looks similar to this X400:c=US;a= ;p=Domain;o=Organization;s=Doe;g=John;
+ *
+ * @param string $username The username of the user to add the X400 to to
+ * @param string $country Country
+ * @param string $admd Administration Management Domain
+ * @param string $pdmd Private Management Domain (often your AD domain)
+ * @param string $org Organization
+ * @param string $surname Surname
+ * @param string $givenName Given name
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function addX400($username, $country, $admd, $pdmd, $org, $surname, $givenName, $isGUID=false)
+ {
+ if ($username === NULL){ return "Missing compulsory field [username]"; }
+
+ $proxyValue = 'X400:';
+
+ // Find the dn of the user
+ $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
+ if ($user[0]["dn"] === NULL) { return false; }
+ $userDn = $user[0]["dn"];
+
+ // We do not have to demote an email address from the default so we can just add the new proxy address
+ $attributes['exchange_proxyaddress'] = $proxyValue . 'c=' . $country . ';a=' . $admd . ';p=' . $pdmd . ';o=' . $org . ';s=' . $surname . ';g=' . $givenName . ';';
+
+ // Translate the update to the LDAP schema
+ $add = $this->adldap->adldap_schema($attributes);
+
+ if (!$add) { return false; }
+
+ // Do the update
+ // Take out the @ to see any errors, usually this error might occur because the address already
+ // exists in the list of proxyAddresses
+ $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn, $add);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Add an address to Exchange
+ *
+ * @param string $username The username of the user to add the Exchange account to
+ * @param string $emailAddress The email address to add to this user
+ * @param bool $default Make this email address the default address, this is a bit more intensive as we have to demote any existing default addresses
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function addAddress($username, $emailAddress, $default = FALSE, $isGUID = false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
+
+ $proxyValue = 'smtp:';
+ if ($default === true) {
+ $proxyValue = 'SMTP:';
+ }
+
+ // Find the dn of the user
+ $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
+ if ($user[0]["dn"] === NULL){ return false; }
+ $userDn = $user[0]["dn"];
+
+ // We need to scan existing proxy addresses and demote the default one
+ if (is_array($user[0]["proxyaddresses"]) && $default === true) {
+ $modAddresses = array();
+ for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) {
+ if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false) {
+ $user[0]['proxyaddresses'][$i] = str_replace('SMTP:', 'smtp:', $user[0]['proxyaddresses'][$i]);
+ }
+ if ($user[0]['proxyaddresses'][$i] != '') {
+ $modAddresses['proxyAddresses'][$i] = $user[0]['proxyaddresses'][$i];
+ }
+ }
+ $modAddresses['proxyAddresses'][(sizeof($user[0]['proxyaddresses'])-1)] = 'SMTP:' . $emailAddress;
+
+ $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $modAddresses);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+ else {
+ // We do not have to demote an email address from the default so we can just add the new proxy address
+ $attributes['exchange_proxyaddress'] = $proxyValue . $emailAddress;
+
+ // Translate the update to the LDAP schema
+ $add = $this->adldap->adldap_schema($attributes);
+
+ if (!$add) {
+ return false;
+ }
+
+ // Do the update
+ // Take out the @ to see any errors, usually this error might occur because the address already
+ // exists in the list of proxyAddresses
+ $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn,$add);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Remove an address to Exchange
+ * If you remove a default address the account will no longer have a default,
+ * we recommend changing the default address first
+ *
+ * @param string $username The username of the user to add the Exchange account to
+ * @param string $emailAddress The email address to add to this user
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function deleteAddress($username, $emailAddress, $isGUID=false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
+
+ // Find the dn of the user
+ $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
+ if ($user[0]["dn"] === NULL) { return false; }
+ $userDn = $user[0]["dn"];
+
+ if (is_array($user[0]["proxyaddresses"])) {
+ $mod = array();
+ for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) {
+ if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false && $user[0]['proxyaddresses'][$i] == 'SMTP:' . $emailAddress) {
+ $mod['proxyAddresses'][0] = 'SMTP:' . $emailAddress;
+ }
+ elseif (strstr($user[0]['proxyaddresses'][$i], 'smtp:') !== false && $user[0]['proxyaddresses'][$i] == 'smtp:' . $emailAddress) {
+ $mod['proxyAddresses'][0] = 'smtp:' . $emailAddress;
+ }
+ }
+
+ $result = @ldap_mod_del($this->adldap->getLdapConnection(), $userDn,$mod);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ /**
+ * Change the default address
+ *
+ * @param string $username The username of the user to add the Exchange account to
+ * @param string $emailAddress The email address to make default
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function primaryAddress($username, $emailAddress, $isGUID = false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
+
+ // Find the dn of the user
+ $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
+ if ($user[0]["dn"] === NULL){ return false; }
+ $userDn = $user[0]["dn"];
+
+ if (is_array($user[0]["proxyaddresses"])) {
+ $modAddresses = array();
+ for ($i=0;$i<sizeof($user[0]['proxyaddresses']);$i++) {
+ if (strstr($user[0]['proxyaddresses'][$i], 'SMTP:') !== false) {
+ $user[0]['proxyaddresses'][$i] = str_replace('SMTP:', 'smtp:', $user[0]['proxyaddresses'][$i]);
+ }
+ if ($user[0]['proxyaddresses'][$i] == 'smtp:' . $emailAddress) {
+ $user[0]['proxyaddresses'][$i] = str_replace('smtp:', 'SMTP:', $user[0]['proxyaddresses'][$i]);
+ }
+ if ($user[0]['proxyaddresses'][$i] != '') {
+ $modAddresses['proxyAddresses'][$i] = $user[0]['proxyaddresses'][$i];
+ }
+ }
+
+ $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $modAddresses);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+
+ /**
+ * Mail enable a contact
+ * Allows email to be sent to them through Exchange
+ *
+ * @param string $distinguishedName The contact to mail enable
+ * @param string $emailAddress The email address to allow emails to be sent through
+ * @param string $mailNickname The mailnickname for the contact in Exchange. If NULL this will be set to the display name
+ * @return bool
+ */
+ public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL)
+ {
+ if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedName]"; }
+ if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }
+
+ if ($mailNickname !== NULL) {
+ // Find the dn of the user
+ $user = $this->adldap->contact()->info($distinguishedName, array("cn","displayname"));
+ if ($user[0]["displayname"] === NULL) { return false; }
+ $mailNickname = $user[0]['displayname'][0];
+ }
+
+ $attributes = array("email"=>$emailAddress,"contact_email"=>"SMTP:" . $emailAddress,"exchange_proxyaddress"=>"SMTP:" . $emailAddress,"exchange_mailnickname" => $mailNickname);
+
+ // Translate the update to the LDAP schema
+ $mod = $this->adldap->adldap_schema($attributes);
+
+ // Check to see if this is an enabled status update
+ if (!$mod) { return false; }
+
+ // Do the update
+ $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
+ if ($result == false) { return false; }
+
+ return true;
+ }
+
+ /**
+ * Returns a list of Exchange Servers in the ConfigurationNamingContext of the domain
+ *
+ * @param array $attributes An array of the AD attributes you wish to return
+ * @return array
+ */
+ public function servers($attributes = array('cn','distinguishedname','serialnumber'))
+ {
+ if (!$this->adldap->getLdapBind()){ return false; }
+
+ $configurationNamingContext = $this->adldap->getRootDse(array('configurationnamingcontext'));
+ $sr = @ldap_search($this->adldap->getLdapConnection(), $configurationNamingContext[0]['configurationnamingcontext'][0],'(&(objectCategory=msExchExchangeServer))', $attributes);
+ $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ return $entries;
+ }
+
+ /**
+ * Returns a list of Storage Groups in Exchange for a given mail server
+ *
+ * @param string $exchangeServer The full DN of an Exchange server. You can use exchange_servers() to find the DN for your server
+ * @param array $attributes An array of the AD attributes you wish to return
+ * @param bool $recursive If enabled this will automatically query the databases within a storage group
+ * @return array
+ */
+ public function storageGroups($exchangeServer, $attributes = array('cn','distinguishedname'), $recursive = NULL)
+ {
+ if (!$this->adldap->getLdapBind()){ return false; }
+ if ($exchangeServer === NULL) { return "Missing compulsory field [exchangeServer]"; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); }
+
+ $filter = '(&(objectCategory=msExchStorageGroup))';
+ $sr = @ldap_search($this->adldap->getLdapConnection(), $exchangeServer, $filter, $attributes);
+ $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ if ($recursive === true) {
+ for ($i=0; $i<$entries['count']; $i++) {
+ $entries[$i]['msexchprivatemdb'] = $this->storageDatabases($entries[$i]['distinguishedname'][0]);
+ }
+ }
+
+ return $entries;
+ }
+
+ /**
+ * Returns a list of Databases within any given storage group in Exchange for a given mail server
+ *
+ * @param string $storageGroup The full DN of an Storage Group. You can use exchange_storage_groups() to find the DN
+ * @param array $attributes An array of the AD attributes you wish to return
+ * @return array
+ */
+ public function storageDatabases($storageGroup, $attributes = array('cn','distinguishedname','displayname')) {
+ if (!$this->adldap->getLdapBind()){ return false; }
+ if ($storageGroup === NULL) { return "Missing compulsory field [storageGroup]"; }
+
+ $filter = '(&(objectCategory=msExchPrivateMDB))';
+ $sr = @ldap_search($this->adldap->getLdapConnection(), $storageGroup, $filter, $attributes);
+ $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ return $entries;
+ }
+}
?> \ No newline at end of file
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php b/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php
index 55120152d..67b1474db 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php
@@ -1,179 +1,179 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Folders
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-
-/**
-* FOLDER / OU MANAGEMENT FUNCTIONS
-*/
-class adLDAPFolders {
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
- /**
- * Delete a distinguished name from Active Directory
- * You should never need to call this yourself, just use the wrapper functions user_delete and contact_delete
- *
- * @param string $dn The distinguished name to delete
- * @return bool
- */
- public function delete($dn){
- $result = ldap_delete($this->adldap->getLdapConnection(), $dn);
- if ($result != true) {
- return false;
- }
- return true;
- }
-
- /**
- * Returns a folder listing for a specific OU
- * See http://adldap.sourceforge.net/wiki/doku.php?id=api_folder_functions
- *
- * @param array $folderName An array to the OU you wish to list.
- * If set to NULL will list the root, strongly recommended to set
- * $recursive to false in that instance!
- * @param string $dnType The type of record to list. This can be ADLDAP_FOLDER or ADLDAP_CONTAINER.
- * @param bool $recursive Recursively search sub folders
- * @param bool $type Specify a type of object to search for
- * @return array
- */
- public function listing($folderName = NULL, $dnType = adLDAP::ADLDAP_FOLDER, $recursive = NULL, $type = NULL)
- {
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $filter = '(&';
- if ($type !== NULL) {
- switch ($type) {
- case 'contact':
- $filter .= '(objectClass=contact)';
- break;
- case 'computer':
- $filter .= '(objectClass=computer)';
- break;
- case 'group':
- $filter .= '(objectClass=group)';
- break;
- case 'folder':
- $filter .= '(objectClass=organizationalUnit)';
- break;
- case 'container':
- $filter .= '(objectClass=container)';
- break;
- case 'domain':
- $filter .= '(objectClass=builtinDomain)';
- break;
- default:
- $filter .= '(objectClass=user)';
- break;
- }
- }
- else {
- $filter .= '(objectClass=*)';
- }
- // If the folder name is null then we will search the root level of AD
- // This requires us to not have an OU= part, just the base_dn
- $searchOu = $this->adldap->getBaseDn();
- if (is_array($folderName)) {
- $ou = $dnType . "=" . implode("," . $dnType . "=", $folderName);
- $filter .= '(!(distinguishedname=' . $ou . ',' . $this->adldap->getBaseDn() . ')))';
- $searchOu = $ou . ',' . $this->adldap->getBaseDn();
- }
- else {
- $filter .= '(!(distinguishedname=' . $this->adldap->getBaseDn() . ')))';
- }
-
- if ($recursive === true) {
- $sr = ldap_search($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
- $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- if (is_array($entries)) {
- return $entries;
- }
- }
- else {
- $sr = ldap_list($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
- $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- if (is_array($entries)) {
- return $entries;
- }
- }
-
- return false;
- }
-
- /**
- * Create an organizational unit
- *
- * @param array $attributes Default attributes of the ou
- * @return bool
- */
- public function create($attributes)
- {
- if (!is_array($attributes)){ return "Attributes must be an array"; }
- if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
- if (!array_key_exists("ou_name",$attributes)) { return "Missing compulsory field [ou_name]"; }
- if (!array_key_exists("container",$attributes)) { return "Missing compulsory field [container]"; }
-
- $attributes["container"] = array_reverse($attributes["container"]);
-
- $add=array();
- $add["objectClass"] = "organizationalUnit";
- $add["OU"] = $attributes['ou_name'];
- $containers = "";
- if (count($attributes['container']) > 0) {
- $containers = "OU=" . implode(",OU=", $attributes["container"]) . ",";
- }
-
- $containers = "OU=" . implode(",OU=", $attributes["container"]);
- $result = ldap_add($this->adldap->getLdapConnection(), "OU=" . $add["OU"] . ", " . $containers . $this->adldap->getBaseDn(), $add);
- if ($result != true) {
- return false;
- }
-
- return true;
- }
-
-}
-
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Folders
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+
+/**
+* FOLDER / OU MANAGEMENT FUNCTIONS
+*/
+class adLDAPFolders {
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+ /**
+ * Delete a distinguished name from Active Directory
+ * You should never need to call this yourself, just use the wrapper functions user_delete and contact_delete
+ *
+ * @param string $dn The distinguished name to delete
+ * @return bool
+ */
+ public function delete($dn){
+ $result = ldap_delete($this->adldap->getLdapConnection(), $dn);
+ if ($result != true) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a folder listing for a specific OU
+ * See http://adldap.sourceforge.net/wiki/doku.php?id=api_folder_functions
+ *
+ * @param array $folderName An array to the OU you wish to list.
+ * If set to NULL will list the root, strongly recommended to set
+ * $recursive to false in that instance!
+ * @param string $dnType The type of record to list. This can be ADLDAP_FOLDER or ADLDAP_CONTAINER.
+ * @param bool $recursive Recursively search sub folders
+ * @param bool $type Specify a type of object to search for
+ * @return array
+ */
+ public function listing($folderName = NULL, $dnType = adLDAP::ADLDAP_FOLDER, $recursive = NULL, $type = NULL)
+ {
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $filter = '(&';
+ if ($type !== NULL) {
+ switch ($type) {
+ case 'contact':
+ $filter .= '(objectClass=contact)';
+ break;
+ case 'computer':
+ $filter .= '(objectClass=computer)';
+ break;
+ case 'group':
+ $filter .= '(objectClass=group)';
+ break;
+ case 'folder':
+ $filter .= '(objectClass=organizationalUnit)';
+ break;
+ case 'container':
+ $filter .= '(objectClass=container)';
+ break;
+ case 'domain':
+ $filter .= '(objectClass=builtinDomain)';
+ break;
+ default:
+ $filter .= '(objectClass=user)';
+ break;
+ }
+ }
+ else {
+ $filter .= '(objectClass=*)';
+ }
+ // If the folder name is null then we will search the root level of AD
+ // This requires us to not have an OU= part, just the base_dn
+ $searchOu = $this->adldap->getBaseDn();
+ if (is_array($folderName)) {
+ $ou = $dnType . "=" . implode("," . $dnType . "=", $folderName);
+ $filter .= '(!(distinguishedname=' . $ou . ',' . $this->adldap->getBaseDn() . ')))';
+ $searchOu = $ou . ',' . $this->adldap->getBaseDn();
+ }
+ else {
+ $filter .= '(!(distinguishedname=' . $this->adldap->getBaseDn() . ')))';
+ }
+
+ if ($recursive === true) {
+ $sr = ldap_search($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
+ $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ if (is_array($entries)) {
+ return $entries;
+ }
+ }
+ else {
+ $sr = ldap_list($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
+ $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ if (is_array($entries)) {
+ return $entries;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Create an organizational unit
+ *
+ * @param array $attributes Default attributes of the ou
+ * @return bool
+ */
+ public function create($attributes)
+ {
+ if (!is_array($attributes)){ return "Attributes must be an array"; }
+ if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
+ if (!array_key_exists("ou_name",$attributes)) { return "Missing compulsory field [ou_name]"; }
+ if (!array_key_exists("container",$attributes)) { return "Missing compulsory field [container]"; }
+
+ $attributes["container"] = array_reverse($attributes["container"]);
+
+ $add=array();
+ $add["objectClass"] = "organizationalUnit";
+ $add["OU"] = $attributes['ou_name'];
+ $containers = "";
+ if (count($attributes['container']) > 0) {
+ $containers = "OU=" . implode(",OU=", $attributes["container"]) . ",";
+ }
+
+ $containers = "OU=" . implode(",OU=", $attributes["container"]);
+ $result = ldap_add($this->adldap->getLdapConnection(), "OU=" . $add["OU"] . ", " . $containers . $this->adldap->getBaseDn(), $add);
+ if ($result != true) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
?> \ No newline at end of file
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php b/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php
index 05e4cc93b..94bc04853 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php
@@ -1,631 +1,631 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Groups
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-require_once(dirname(__FILE__) . '/../collections/adLDAPGroupCollection.php');
-
-/**
-* GROUP FUNCTIONS
-*/
-class adLDAPGroups {
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
- /**
- * Add a group to a group
- *
- * @param string $parent The parent group name
- * @param string $child The child group name
- * @return bool
- */
- public function addGroup($parent,$child){
-
- // Find the parent group's dn
- $parentGroup = $this->ginfo($parent, array("cn"));
- if ($parentGroup[0]["dn"] === NULL){
- return false;
- }
- $parentDn = $parentGroup[0]["dn"];
-
- // Find the child group's dn
- $childGroup = $this->info($child, array("cn"));
- if ($childGroup[0]["dn"] === NULL){
- return false;
- }
- $childDn = $childGroup[0]["dn"];
-
- $add = array();
- $add["member"] = $childDn;
-
- $result = @ldap_mod_add($this->adldap->getLdapConnection(), $parentDn, $add);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Add a user to a group
- *
- * @param string $group The group to add the user to
- * @param string $user The user to add to the group
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function addUser($group, $user, $isGUID = false)
- {
- // Adding a user is a bit fiddly, we need to get the full DN of the user
- // and add it using the full DN of the group
-
- // Find the user's dn
- $userDn = $this->adldap->user()->dn($user, $isGUID);
- if ($userDn === false) {
- return false;
- }
-
- // Find the group's dn
- $groupInfo = $this->info($group, array("cn"));
- if ($groupInfo[0]["dn"] === NULL) {
- return false;
- }
- $groupDn = $groupInfo[0]["dn"];
-
- $add = array();
- $add["member"] = $userDn;
-
- $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Add a contact to a group
- *
- * @param string $group The group to add the contact to
- * @param string $contactDn The DN of the contact to add
- * @return bool
- */
- public function addContact($group, $contactDn)
- {
- // To add a contact we take the contact's DN
- // and add it using the full DN of the group
-
- // Find the group's dn
- $groupInfo = $this->info($group, array("cn"));
- if ($groupInfo[0]["dn"] === NULL) {
- return false;
- }
- $groupDn = $groupInfo[0]["dn"];
-
- $add = array();
- $add["member"] = $contactDn;
-
- $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Create a group
- *
- * @param array $attributes Default attributes of the group
- * @return bool
- */
- public function create($attributes)
- {
- if (!is_array($attributes)){ return "Attributes must be an array"; }
- if (!array_key_exists("group_name", $attributes)){ return "Missing compulsory field [group_name]"; }
- if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
- if (!array_key_exists("description", $attributes)){ return "Missing compulsory field [description]"; }
- if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
- $attributes["container"] = array_reverse($attributes["container"]);
-
- //$member_array = array();
- //$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
- //$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";
-
- $add = array();
- $add["cn"] = $attributes["group_name"];
- $add["samaccountname"] = $attributes["group_name"];
- $add["objectClass"] = "Group";
- $add["description"] = $attributes["description"];
- //$add["member"] = $member_array; UNTESTED
-
- $container = "OU=" . implode(",OU=", $attributes["container"]);
- $result = ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
- if ($result != true) {
- return false;
- }
- return true;
- }
-
- /**
- * Delete a group account
- *
- * @param string $group The group to delete (please be careful here!)
- *
- * @return array
- */
- public function delete($group) {
- if (!$this->adldap->getLdapBind()){ return false; }
- if ($group === null){ return "Missing compulsory field [group]"; }
-
- $groupInfo = $this->info($group, array("*"));
- $dn = $groupInfo[0]['distinguishedname'][0];
- $result = $this->adldap->folder()->delete($dn);
- if ($result !== true) {
- return false;
- } return true;
- }
-
- /**
- * Remove a group from a group
- *
- * @param string $parent The parent group name
- * @param string $child The child group name
- * @return bool
- */
- public function removeGroup($parent , $child)
- {
-
- // Find the parent dn
- $parentGroup = $this->info($parent, array("cn"));
- if ($parentGroup[0]["dn"] === NULL) {
- return false;
- }
- $parentDn = $parentGroup[0]["dn"];
-
- // Find the child dn
- $childGroup = $this->info($child, array("cn"));
- if ($childGroup[0]["dn"] === NULL) {
- return false;
- }
- $childDn = $childGroup[0]["dn"];
-
- $del = array();
- $del["member"] = $childDn;
-
- $result = @ldap_mod_del($this->adldap->getLdapConnection(), $parentDn, $del);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Remove a user from a group
- *
- * @param string $group The group to remove a user from
- * @param string $user The AD user to remove from the group
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function removeUser($group, $user, $isGUID = false)
- {
-
- // Find the parent dn
- $groupInfo = $this->info($group, array("cn"));
- if ($groupInfo[0]["dn"] === NULL){
- return false;
- }
- $groupDn = $groupInfo[0]["dn"];
-
- // Find the users dn
- $userDn = $this->adldap->user()->dn($user, $isGUID);
- if ($userDn === false) {
- return false;
- }
-
- $del = array();
- $del["member"] = $userDn;
-
- $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Remove a contact from a group
- *
- * @param string $group The group to remove a user from
- * @param string $contactDn The DN of a contact to remove from the group
- * @return bool
- */
- public function removeContact($group, $contactDn)
- {
-
- // Find the parent dn
- $groupInfo = $this->info($group, array("cn"));
- if ($groupInfo[0]["dn"] === NULL) {
- return false;
- }
- $groupDn = $groupInfo[0]["dn"];
-
- $del = array();
- $del["member"] = $contactDn;
-
- $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
- if ($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Return a list of groups in a group
- *
- * @param string $group The group to query
- * @param bool $recursive Recursively get groups
- * @return array
- */
- public function inGroup($group, $recursive = NULL)
- {
- if (!$this->adldap->getLdapBind()){ return false; }
- if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
-
- // Search the directory for the members of a group
- $info = $this->info($group, array("member","cn"));
- $groups = $info[0]["member"];
- if (!is_array($groups)) {
- return false;
- }
-
- $groupArray = array();
-
- for ($i=0; $i<$groups["count"]; $i++){
- $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
- $fields = array("samaccountname", "distinguishedname", "objectClass");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- // not a person, look for a group
- if ($entries['count'] == 0 && $recursive == true) {
- $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
- $fields = array("distinguishedname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- if (!isset($entries[0]['distinguishedname'][0])) {
- continue;
- }
- $subGroups = $this->inGroup($entries[0]['distinguishedname'][0], $recursive);
- if (is_array($subGroups)) {
- $groupArray = array_merge($groupArray, $subGroups);
- $groupArray = array_unique($groupArray);
- }
- continue;
- }
-
- $groupArray[] = $entries[0]['distinguishedname'][0];
- }
- return $groupArray;
- }
-
- /**
- * Return a list of members in a group
- *
- * @param string $group The group to query
- * @param bool $recursive Recursively get group members
- * @return array
- */
- public function members($group, $recursive = NULL)
- {
- if (!$this->adldap->getLdapBind()){ return false; }
- if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
- // Search the directory for the members of a group
- $info = $this->info($group, array("member","cn"));
- $users = $info[0]["member"];
- if (!is_array($users)) {
- return false;
- }
-
- $userArray = array();
-
- for ($i=0; $i<$users["count"]; $i++){
- $filter = "(&(objectCategory=person)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
- $fields = array("samaccountname", "distinguishedname", "objectClass");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- // not a person, look for a group
- if ($entries['count'] == 0 && $recursive == true) {
- $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
- $fields = array("samaccountname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- if (!isset($entries[0]['samaccountname'][0])) {
- continue;
- }
- $subUsers = $this->members($entries[0]['samaccountname'][0], $recursive);
- if (is_array($subUsers)) {
- $userArray = array_merge($userArray, $subUsers);
- $userArray = array_unique($userArray);
- }
- continue;
- }
- else if ($entries['count'] == 0) {
- continue;
- }
-
- if ((!isset($entries[0]['samaccountname'][0]) || $entries[0]['samaccountname'][0] === NULL) && $entries[0]['distinguishedname'][0] !== NULL) {
- $userArray[] = $entries[0]['distinguishedname'][0];
- }
- else if ($entries[0]['samaccountname'][0] !== NULL) {
- $userArray[] = $entries[0]['samaccountname'][0];
- }
- }
- return $userArray;
- }
-
- /**
- * Group Information. Returns an array of raw information about a group.
- * The group name is case sensitive
- *
- * @param string $groupName The group name to retrieve info about
- * @param array $fields Fields to retrieve
- * @return array
- */
- public function info($groupName, $fields = NULL)
- {
- if ($groupName === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- if (stristr($groupName, '+')) {
- $groupName = stripslashes($groupName);
- }
-
- $filter = "(&(objectCategory=group)(name=" . $this->adldap->utilities()->ldapSlashes($groupName) . "))";
- if ($fields === NULL) {
- $fields = array("member","memberof","cn","description","distinguishedname","objectcategory","samaccountname");
- }
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- return $entries;
- }
-
- /**
- * Group Information. Returns an collection
- * The group name is case sensitive
- *
- * @param string $groupName The group name to retrieve info about
- * @param array $fields Fields to retrieve
- * @return adLDAPGroupCollection
- */
- public function infoCollection($groupName, $fields = NULL)
- {
- if ($groupName === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $info = $this->info($groupName, $fields);
- if ($info !== false) {
- $collection = new adLDAPGroupCollection($info, $this->adldap);
- return $collection;
- }
- return false;
- }
-
- /**
- * Return a complete list of "groups in groups"
- *
- * @param string $group The group to get the list from
- * @return array
- */
- public function recursiveGroups($group)
- {
- if ($group === NULL) { return false; }
-
- $stack = array();
- $processed = array();
- $retGroups = array();
-
- array_push($stack, $group); // Initial Group to Start with
- while (count($stack) > 0) {
- $parent = array_pop($stack);
- array_push($processed, $parent);
-
- $info = $this->info($parent, array("memberof"));
-
- if (isset($info[0]["memberof"]) && is_array($info[0]["memberof"])) {
- $groups = $info[0]["memberof"];
- if ($groups) {
- $groupNames = $this->adldap->utilities()->niceNames($groups);
- $retGroups = array_merge($retGroups, $groupNames); //final groups to return
- foreach ($groupNames as $id => $groupName) {
- if (!in_array($groupName, $processed)) {
- array_push($stack, $groupName);
- }
- }
- }
- }
- }
-
- return $retGroups;
- }
-
- /**
- * Returns a complete list of the groups in AD based on a SAM Account Type
- *
- * @param string $sAMAaccountType The account type to return
- * @param bool $includeDescription Whether to return a description
- * @param string $search Search parameters
- * @param bool $sorted Whether to sort the results
- * @return array
- */
- public function search($sAMAaccountType = adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription = false, $search = "*", $sorted = true) {
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $filter = '(&(objectCategory=group)';
- if ($sAMAaccountType !== null) {
- $filter .= '(samaccounttype='. $sAMAaccountType .')';
- }
- $filter .= '(cn=' . $search . '))';
- // Perform the search and grab all their details
- $fields = array("samaccountname", "description");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- $groupsArray = array();
- for ($i=0; $i<$entries["count"]; $i++){
- if ($includeDescription && strlen($entries[$i]["description"][0]) > 0 ) {
- $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["description"][0];
- }
- else if ($includeDescription){
- $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
- }
- else {
- array_push($groupsArray, $entries[$i]["samaccountname"][0]);
- }
- }
- if ($sorted) {
- asort($groupsArray);
- }
- return $groupsArray;
- }
-
- /**
- * Returns a complete list of all groups in AD
- *
- * @param bool $includeDescription Whether to return a description
- * @param string $search Search parameters
- * @param bool $sorted Whether to sort the results
- * @return array
- */
- public function all($includeDescription = false, $search = "*", $sorted = true){
- $groupsArray = $this->search(null, $includeDescription, $search, $sorted);
- return $groupsArray;
- }
-
- /**
- * Returns a complete list of security groups in AD
- *
- * @param bool $includeDescription Whether to return a description
- * @param string $search Search parameters
- * @param bool $sorted Whether to sort the results
- * @return array
- */
- public function allSecurity($includeDescription = false, $search = "*", $sorted = true){
- $groupsArray = $this->search(adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription, $search, $sorted);
- return $groupsArray;
- }
-
- /**
- * Returns a complete list of distribution lists in AD
- *
- * @param bool $includeDescription Whether to return a description
- * @param string $search Search parameters
- * @param bool $sorted Whether to sort the results
- * @return array
- */
- public function allDistribution($includeDescription = false, $search = "*", $sorted = true){
- $groupsArray = $this->search(adLDAP::ADLDAP_DISTRIBUTION_GROUP, $includeDescription, $search, $sorted);
- return $groupsArray;
- }
-
- /**
- * Coping with AD not returning the primary group
- * http://support.microsoft.com/?kbid=321360
- *
- * This is a re-write based on code submitted by Bruce which prevents the
- * need to search each security group to find the true primary group
- *
- * @param string $gid Group ID
- * @param string $usersid User's Object SID
- * @return mixed
- */
- public function getPrimaryGroup($gid, $usersid)
- {
- if ($gid === NULL || $usersid === NULL) { return false; }
- $sr = false;
-
- $gsid = substr_replace($usersid, pack('V',$gid), strlen($usersid)-4,4);
- $filter = '(objectsid=' . $this->adldap->utilities()->getTextSID($gsid).')';
- $fields = array("samaccountname","distinguishedname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- if (isset($entries[0]['distinguishedname'][0])) {
- return $entries[0]['distinguishedname'][0];
- }
- return false;
- }
-
- /**
- * Coping with AD not returning the primary group
- * http://support.microsoft.com/?kbid=321360
- *
- * For some reason it's not possible to search on primarygrouptoken=XXX
- * If someone can show otherwise, I'd like to know about it :)
- * this way is resource intensive and generally a pain in the @#%^
- *
- * @deprecated deprecated since version 3.1, see get get_primary_group
- * @param string $gid Group ID
- * @return string
- */
- public function cn($gid){
- if ($gid === NULL) { return false; }
- $sr = false;
- $r = '';
-
- $filter = "(&(objectCategory=group)(samaccounttype=" . adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP . "))";
- $fields = array("primarygrouptoken", "samaccountname", "distinguishedname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- for ($i=0; $i<$entries["count"]; $i++){
- if ($entries[$i]["primarygrouptoken"][0] == $gid) {
- $r = $entries[$i]["distinguishedname"][0];
- $i = $entries["count"];
- }
- }
-
- return $r;
- }
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Groups
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+require_once(dirname(__FILE__) . '/../collections/adLDAPGroupCollection.php');
+
+/**
+* GROUP FUNCTIONS
+*/
+class adLDAPGroups {
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+ /**
+ * Add a group to a group
+ *
+ * @param string $parent The parent group name
+ * @param string $child The child group name
+ * @return bool
+ */
+ public function addGroup($parent,$child){
+
+ // Find the parent group's dn
+ $parentGroup = $this->ginfo($parent, array("cn"));
+ if ($parentGroup[0]["dn"] === NULL){
+ return false;
+ }
+ $parentDn = $parentGroup[0]["dn"];
+
+ // Find the child group's dn
+ $childGroup = $this->info($child, array("cn"));
+ if ($childGroup[0]["dn"] === NULL){
+ return false;
+ }
+ $childDn = $childGroup[0]["dn"];
+
+ $add = array();
+ $add["member"] = $childDn;
+
+ $result = @ldap_mod_add($this->adldap->getLdapConnection(), $parentDn, $add);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Add a user to a group
+ *
+ * @param string $group The group to add the user to
+ * @param string $user The user to add to the group
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function addUser($group, $user, $isGUID = false)
+ {
+ // Adding a user is a bit fiddly, we need to get the full DN of the user
+ // and add it using the full DN of the group
+
+ // Find the user's dn
+ $userDn = $this->adldap->user()->dn($user, $isGUID);
+ if ($userDn === false) {
+ return false;
+ }
+
+ // Find the group's dn
+ $groupInfo = $this->info($group, array("cn"));
+ if ($groupInfo[0]["dn"] === NULL) {
+ return false;
+ }
+ $groupDn = $groupInfo[0]["dn"];
+
+ $add = array();
+ $add["member"] = $userDn;
+
+ $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Add a contact to a group
+ *
+ * @param string $group The group to add the contact to
+ * @param string $contactDn The DN of the contact to add
+ * @return bool
+ */
+ public function addContact($group, $contactDn)
+ {
+ // To add a contact we take the contact's DN
+ // and add it using the full DN of the group
+
+ // Find the group's dn
+ $groupInfo = $this->info($group, array("cn"));
+ if ($groupInfo[0]["dn"] === NULL) {
+ return false;
+ }
+ $groupDn = $groupInfo[0]["dn"];
+
+ $add = array();
+ $add["member"] = $contactDn;
+
+ $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Create a group
+ *
+ * @param array $attributes Default attributes of the group
+ * @return bool
+ */
+ public function create($attributes)
+ {
+ if (!is_array($attributes)){ return "Attributes must be an array"; }
+ if (!array_key_exists("group_name", $attributes)){ return "Missing compulsory field [group_name]"; }
+ if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
+ if (!array_key_exists("description", $attributes)){ return "Missing compulsory field [description]"; }
+ if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
+ $attributes["container"] = array_reverse($attributes["container"]);
+
+ //$member_array = array();
+ //$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
+ //$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";
+
+ $add = array();
+ $add["cn"] = $attributes["group_name"];
+ $add["samaccountname"] = $attributes["group_name"];
+ $add["objectClass"] = "Group";
+ $add["description"] = $attributes["description"];
+ //$add["member"] = $member_array; UNTESTED
+
+ $container = "OU=" . implode(",OU=", $attributes["container"]);
+ $result = ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
+ if ($result != true) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Delete a group account
+ *
+ * @param string $group The group to delete (please be careful here!)
+ *
+ * @return array
+ */
+ public function delete($group) {
+ if (!$this->adldap->getLdapBind()){ return false; }
+ if ($group === null){ return "Missing compulsory field [group]"; }
+
+ $groupInfo = $this->info($group, array("*"));
+ $dn = $groupInfo[0]['distinguishedname'][0];
+ $result = $this->adldap->folder()->delete($dn);
+ if ($result !== true) {
+ return false;
+ } return true;
+ }
+
+ /**
+ * Remove a group from a group
+ *
+ * @param string $parent The parent group name
+ * @param string $child The child group name
+ * @return bool
+ */
+ public function removeGroup($parent , $child)
+ {
+
+ // Find the parent dn
+ $parentGroup = $this->info($parent, array("cn"));
+ if ($parentGroup[0]["dn"] === NULL) {
+ return false;
+ }
+ $parentDn = $parentGroup[0]["dn"];
+
+ // Find the child dn
+ $childGroup = $this->info($child, array("cn"));
+ if ($childGroup[0]["dn"] === NULL) {
+ return false;
+ }
+ $childDn = $childGroup[0]["dn"];
+
+ $del = array();
+ $del["member"] = $childDn;
+
+ $result = @ldap_mod_del($this->adldap->getLdapConnection(), $parentDn, $del);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Remove a user from a group
+ *
+ * @param string $group The group to remove a user from
+ * @param string $user The AD user to remove from the group
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function removeUser($group, $user, $isGUID = false)
+ {
+
+ // Find the parent dn
+ $groupInfo = $this->info($group, array("cn"));
+ if ($groupInfo[0]["dn"] === NULL){
+ return false;
+ }
+ $groupDn = $groupInfo[0]["dn"];
+
+ // Find the users dn
+ $userDn = $this->adldap->user()->dn($user, $isGUID);
+ if ($userDn === false) {
+ return false;
+ }
+
+ $del = array();
+ $del["member"] = $userDn;
+
+ $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Remove a contact from a group
+ *
+ * @param string $group The group to remove a user from
+ * @param string $contactDn The DN of a contact to remove from the group
+ * @return bool
+ */
+ public function removeContact($group, $contactDn)
+ {
+
+ // Find the parent dn
+ $groupInfo = $this->info($group, array("cn"));
+ if ($groupInfo[0]["dn"] === NULL) {
+ return false;
+ }
+ $groupDn = $groupInfo[0]["dn"];
+
+ $del = array();
+ $del["member"] = $contactDn;
+
+ $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
+ if ($result == false) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return a list of groups in a group
+ *
+ * @param string $group The group to query
+ * @param bool $recursive Recursively get groups
+ * @return array
+ */
+ public function inGroup($group, $recursive = NULL)
+ {
+ if (!$this->adldap->getLdapBind()){ return false; }
+ if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
+
+ // Search the directory for the members of a group
+ $info = $this->info($group, array("member","cn"));
+ $groups = $info[0]["member"];
+ if (!is_array($groups)) {
+ return false;
+ }
+
+ $groupArray = array();
+
+ for ($i=0; $i<$groups["count"]; $i++){
+ $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
+ $fields = array("samaccountname", "distinguishedname", "objectClass");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ // not a person, look for a group
+ if ($entries['count'] == 0 && $recursive == true) {
+ $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
+ $fields = array("distinguishedname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ if (!isset($entries[0]['distinguishedname'][0])) {
+ continue;
+ }
+ $subGroups = $this->inGroup($entries[0]['distinguishedname'][0], $recursive);
+ if (is_array($subGroups)) {
+ $groupArray = array_merge($groupArray, $subGroups);
+ $groupArray = array_unique($groupArray);
+ }
+ continue;
+ }
+
+ $groupArray[] = $entries[0]['distinguishedname'][0];
+ }
+ return $groupArray;
+ }
+
+ /**
+ * Return a list of members in a group
+ *
+ * @param string $group The group to query
+ * @param bool $recursive Recursively get group members
+ * @return array
+ */
+ public function members($group, $recursive = NULL)
+ {
+ if (!$this->adldap->getLdapBind()){ return false; }
+ if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
+ // Search the directory for the members of a group
+ $info = $this->info($group, array("member","cn"));
+ $users = $info[0]["member"];
+ if (!is_array($users)) {
+ return false;
+ }
+
+ $userArray = array();
+
+ for ($i=0; $i<$users["count"]; $i++){
+ $filter = "(&(objectCategory=person)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
+ $fields = array("samaccountname", "distinguishedname", "objectClass");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ // not a person, look for a group
+ if ($entries['count'] == 0 && $recursive == true) {
+ $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
+ $fields = array("samaccountname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ if (!isset($entries[0]['samaccountname'][0])) {
+ continue;
+ }
+ $subUsers = $this->members($entries[0]['samaccountname'][0], $recursive);
+ if (is_array($subUsers)) {
+ $userArray = array_merge($userArray, $subUsers);
+ $userArray = array_unique($userArray);
+ }
+ continue;
+ }
+ else if ($entries['count'] == 0) {
+ continue;
+ }
+
+ if ((!isset($entries[0]['samaccountname'][0]) || $entries[0]['samaccountname'][0] === NULL) && $entries[0]['distinguishedname'][0] !== NULL) {
+ $userArray[] = $entries[0]['distinguishedname'][0];
+ }
+ else if ($entries[0]['samaccountname'][0] !== NULL) {
+ $userArray[] = $entries[0]['samaccountname'][0];
+ }
+ }
+ return $userArray;
+ }
+
+ /**
+ * Group Information. Returns an array of raw information about a group.
+ * The group name is case sensitive
+ *
+ * @param string $groupName The group name to retrieve info about
+ * @param array $fields Fields to retrieve
+ * @return array
+ */
+ public function info($groupName, $fields = NULL)
+ {
+ if ($groupName === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ if (stristr($groupName, '+')) {
+ $groupName = stripslashes($groupName);
+ }
+
+ $filter = "(&(objectCategory=group)(name=" . $this->adldap->utilities()->ldapSlashes($groupName) . "))";
+ if ($fields === NULL) {
+ $fields = array("member","memberof","cn","description","distinguishedname","objectcategory","samaccountname");
+ }
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ return $entries;
+ }
+
+ /**
+ * Group Information. Returns an collection
+ * The group name is case sensitive
+ *
+ * @param string $groupName The group name to retrieve info about
+ * @param array $fields Fields to retrieve
+ * @return adLDAPGroupCollection
+ */
+ public function infoCollection($groupName, $fields = NULL)
+ {
+ if ($groupName === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $info = $this->info($groupName, $fields);
+ if ($info !== false) {
+ $collection = new adLDAPGroupCollection($info, $this->adldap);
+ return $collection;
+ }
+ return false;
+ }
+
+ /**
+ * Return a complete list of "groups in groups"
+ *
+ * @param string $group The group to get the list from
+ * @return array
+ */
+ public function recursiveGroups($group)
+ {
+ if ($group === NULL) { return false; }
+
+ $stack = array();
+ $processed = array();
+ $retGroups = array();
+
+ array_push($stack, $group); // Initial Group to Start with
+ while (count($stack) > 0) {
+ $parent = array_pop($stack);
+ array_push($processed, $parent);
+
+ $info = $this->info($parent, array("memberof"));
+
+ if (isset($info[0]["memberof"]) && is_array($info[0]["memberof"])) {
+ $groups = $info[0]["memberof"];
+ if ($groups) {
+ $groupNames = $this->adldap->utilities()->niceNames($groups);
+ $retGroups = array_merge($retGroups, $groupNames); //final groups to return
+ foreach ($groupNames as $id => $groupName) {
+ if (!in_array($groupName, $processed)) {
+ array_push($stack, $groupName);
+ }
+ }
+ }
+ }
+ }
+
+ return $retGroups;
+ }
+
+ /**
+ * Returns a complete list of the groups in AD based on a SAM Account Type
+ *
+ * @param string $sAMAaccountType The account type to return
+ * @param bool $includeDescription Whether to return a description
+ * @param string $search Search parameters
+ * @param bool $sorted Whether to sort the results
+ * @return array
+ */
+ public function search($sAMAaccountType = adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription = false, $search = "*", $sorted = true) {
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $filter = '(&(objectCategory=group)';
+ if ($sAMAaccountType !== null) {
+ $filter .= '(samaccounttype='. $sAMAaccountType .')';
+ }
+ $filter .= '(cn=' . $search . '))';
+ // Perform the search and grab all their details
+ $fields = array("samaccountname", "description");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ $groupsArray = array();
+ for ($i=0; $i<$entries["count"]; $i++){
+ if ($includeDescription && strlen($entries[$i]["description"][0]) > 0 ) {
+ $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["description"][0];
+ }
+ else if ($includeDescription){
+ $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
+ }
+ else {
+ array_push($groupsArray, $entries[$i]["samaccountname"][0]);
+ }
+ }
+ if ($sorted) {
+ asort($groupsArray);
+ }
+ return $groupsArray;
+ }
+
+ /**
+ * Returns a complete list of all groups in AD
+ *
+ * @param bool $includeDescription Whether to return a description
+ * @param string $search Search parameters
+ * @param bool $sorted Whether to sort the results
+ * @return array
+ */
+ public function all($includeDescription = false, $search = "*", $sorted = true){
+ $groupsArray = $this->search(null, $includeDescription, $search, $sorted);
+ return $groupsArray;
+ }
+
+ /**
+ * Returns a complete list of security groups in AD
+ *
+ * @param bool $includeDescription Whether to return a description
+ * @param string $search Search parameters
+ * @param bool $sorted Whether to sort the results
+ * @return array
+ */
+ public function allSecurity($includeDescription = false, $search = "*", $sorted = true){
+ $groupsArray = $this->search(adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription, $search, $sorted);
+ return $groupsArray;
+ }
+
+ /**
+ * Returns a complete list of distribution lists in AD
+ *
+ * @param bool $includeDescription Whether to return a description
+ * @param string $search Search parameters
+ * @param bool $sorted Whether to sort the results
+ * @return array
+ */
+ public function allDistribution($includeDescription = false, $search = "*", $sorted = true){
+ $groupsArray = $this->search(adLDAP::ADLDAP_DISTRIBUTION_GROUP, $includeDescription, $search, $sorted);
+ return $groupsArray;
+ }
+
+ /**
+ * Coping with AD not returning the primary group
+ * http://support.microsoft.com/?kbid=321360
+ *
+ * This is a re-write based on code submitted by Bruce which prevents the
+ * need to search each security group to find the true primary group
+ *
+ * @param string $gid Group ID
+ * @param string $usersid User's Object SID
+ * @return mixed
+ */
+ public function getPrimaryGroup($gid, $usersid)
+ {
+ if ($gid === NULL || $usersid === NULL) { return false; }
+ $sr = false;
+
+ $gsid = substr_replace($usersid, pack('V',$gid), strlen($usersid)-4,4);
+ $filter = '(objectsid=' . $this->adldap->utilities()->getTextSID($gsid).')';
+ $fields = array("samaccountname","distinguishedname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ if (isset($entries[0]['distinguishedname'][0])) {
+ return $entries[0]['distinguishedname'][0];
+ }
+ return false;
+ }
+
+ /**
+ * Coping with AD not returning the primary group
+ * http://support.microsoft.com/?kbid=321360
+ *
+ * For some reason it's not possible to search on primarygrouptoken=XXX
+ * If someone can show otherwise, I'd like to know about it :)
+ * this way is resource intensive and generally a pain in the @#%^
+ *
+ * @deprecated deprecated since version 3.1, see get get_primary_group
+ * @param string $gid Group ID
+ * @return string
+ */
+ public function cn($gid){
+ if ($gid === NULL) { return false; }
+ $sr = false;
+ $r = '';
+
+ $filter = "(&(objectCategory=group)(samaccounttype=" . adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP . "))";
+ $fields = array("primarygrouptoken", "samaccountname", "distinguishedname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ for ($i=0; $i<$entries["count"]; $i++){
+ if ($entries[$i]["primarygrouptoken"][0] == $gid) {
+ $r = $entries[$i]["distinguishedname"][0];
+ $i = $entries["count"];
+ }
+ }
+
+ return $r;
+ }
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php b/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php
index 96a93b512..839fd592d 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php
@@ -1,682 +1,682 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage User
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-require_once(dirname(__FILE__) . '/../collections/adLDAPUserCollection.php');
-
-/**
-* USER FUNCTIONS
-*/
-class adLDAPUsers {
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
- /**
- * Validate a user's login credentials
- *
- * @param string $username A user's AD username
- * @param string $password A user's AD password
- * @param bool optional $prevent_rebind
- * @return bool
- */
- public function authenticate($username, $password, $preventRebind = false) {
- return $this->adldap->authenticate($username, $password, $preventRebind);
- }
-
- /**
- * Create a user
- *
- * If you specify a password here, this can only be performed over SSL
- *
- * @param array $attributes The attributes to set to the user account
- * @return bool
- */
- public function create($attributes)
- {
- // Check for compulsory fields
- if (!array_key_exists("username", $attributes)){ return "Missing compulsory field [username]"; }
- if (!array_key_exists("firstname", $attributes)){ return "Missing compulsory field [firstname]"; }
- if (!array_key_exists("surname", $attributes)){ return "Missing compulsory field [surname]"; }
- if (!array_key_exists("email", $attributes)){ return "Missing compulsory field [email]"; }
- if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
- if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
-
- if (array_key_exists("password",$attributes) && (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS())){
- throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
- }
-
- if (!array_key_exists("display_name", $attributes)) {
- $attributes["display_name"] = $attributes["firstname"] . " " . $attributes["surname"];
- }
-
- // Translate the schema
- $add = $this->adldap->adldap_schema($attributes);
-
- // Additional stuff only used for adding accounts
- $add["cn"][0] = $attributes["display_name"];
- $add["samaccountname"][0] = $attributes["username"];
- $add["objectclass"][0] = "top";
- $add["objectclass"][1] = "person";
- $add["objectclass"][2] = "organizationalPerson";
- $add["objectclass"][3] = "user"; //person?
- //$add["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
-
- // Set the account control attribute
- $control_options = array("NORMAL_ACCOUNT");
- if (!$attributes["enabled"]) {
- $control_options[] = "ACCOUNTDISABLE";
- }
- $add["userAccountControl"][0] = $this->accountControl($control_options);
-
- // Determine the container
- $attributes["container"] = array_reverse($attributes["container"]);
- $container = "OU=" . implode(", OU=",$attributes["container"]);
-
- // Add the entry
- $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"][0] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
- if ($result != true) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Account control options
- *
- * @param array $options The options to convert to int
- * @return int
- */
- protected function accountControl($options)
- {
- $val=0;
-
- if (is_array($options)) {
- if (in_array("SCRIPT",$options)){ $val=$val+1; }
- if (in_array("ACCOUNTDISABLE",$options)){ $val=$val+2; }
- if (in_array("HOMEDIR_REQUIRED",$options)){ $val=$val+8; }
- if (in_array("LOCKOUT",$options)){ $val=$val+16; }
- if (in_array("PASSWD_NOTREQD",$options)){ $val=$val+32; }
- //PASSWD_CANT_CHANGE Note You cannot assign this permission by directly modifying the UserAccountControl attribute.
- //For information about how to set the permission programmatically, see the "Property flag descriptions" section.
- if (in_array("ENCRYPTED_TEXT_PWD_ALLOWED",$options)){ $val=$val+128; }
- if (in_array("TEMP_DUPLICATE_ACCOUNT",$options)){ $val=$val+256; }
- if (in_array("NORMAL_ACCOUNT",$options)){ $val=$val+512; }
- if (in_array("INTERDOMAIN_TRUST_ACCOUNT",$options)){ $val=$val+2048; }
- if (in_array("WORKSTATION_TRUST_ACCOUNT",$options)){ $val=$val+4096; }
- if (in_array("SERVER_TRUST_ACCOUNT",$options)){ $val=$val+8192; }
- if (in_array("DONT_EXPIRE_PASSWORD",$options)){ $val=$val+65536; }
- if (in_array("MNS_LOGON_ACCOUNT",$options)){ $val=$val+131072; }
- if (in_array("SMARTCARD_REQUIRED",$options)){ $val=$val+262144; }
- if (in_array("TRUSTED_FOR_DELEGATION",$options)){ $val=$val+524288; }
- if (in_array("NOT_DELEGATED",$options)){ $val=$val+1048576; }
- if (in_array("USE_DES_KEY_ONLY",$options)){ $val=$val+2097152; }
- if (in_array("DONT_REQ_PREAUTH",$options)){ $val=$val+4194304; }
- if (in_array("PASSWORD_EXPIRED",$options)){ $val=$val+8388608; }
- if (in_array("TRUSTED_TO_AUTH_FOR_DELEGATION",$options)){ $val=$val+16777216; }
- }
- return $val;
- }
-
- /**
- * Delete a user account
- *
- * @param string $username The username to delete (please be careful here!)
- * @param bool $isGUID Is the username a GUID or a samAccountName
- * @return array
- */
- public function delete($username, $isGUID = false)
- {
- $userinfo = $this->info($username, array("*"), $isGUID);
- $dn = $userinfo[0]['distinguishedname'][0];
- $result = $this->adldap->folder()->delete($dn);
- if ($result != true) {
- return false;
- }
- return true;
- }
-
- /**
- * Groups the user is a member of
- *
- * @param string $username The username to query
- * @param bool $recursive Recursive list of groups
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return array
- */
- public function groups($username, $recursive = NULL, $isGUID = false)
- {
- if ($username === NULL) { return false; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
- if (!$this->adldap->getLdapBind()) { return false; }
-
- // Search the directory for their information
- $info = @$this->info($username, array("memberof", "primarygroupid"), $isGUID);
- $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); // Presuming the entry returned is our guy (unique usernames)
-
- if ($recursive === true){
- foreach ($groups as $id => $groupName){
- $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
- $groups = array_merge($groups, $extraGroups);
- }
- }
-
- return $groups;
- }
-
- /**
- * Find information about the users. Returned in a raw array format from AD
- *
- * @param string $username The username to query
- * @param array $fields Array of parameters to query
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return array
- */
- public function info($username, $fields = NULL, $isGUID = false)
- {
- if ($username === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- if ($isGUID === true) {
- $username = $this->adldap->utilities()->strGuidToHex($username);
- $filter = "objectguid=" . $username;
- }
- else if (strstr($username, "@")) {
- $filter = "userPrincipalName=" . $username;
- }
- else {
- $filter = "samaccountname=" . $username;
- }
- $filter = "(&(objectCategory=person)({$filter}))";
- if ($fields === NULL) {
- $fields = array("samaccountname","mail","memberof","department","displayname","telephonenumber","primarygroupid","objectsid");
- }
- if (!in_array("objectsid", $fields)) {
- $fields[] = "objectsid";
- }
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- if (isset($entries[0])) {
- if ($entries[0]['count'] >= 1) {
- if (in_array("memberof", $fields)) {
- // AD does not return the primary group in the ldap query, we may need to fudge it
- if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){
- //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
- $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
- } else {
- $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
- }
- if (!isset($entries[0]["memberof"]["count"])) {
- $entries[0]["memberof"]["count"] = 0;
- }
- $entries[0]["memberof"]["count"]++;
- }
- }
-
- return $entries;
- }
- return false;
- }
-
- /**
- * Find information about the users. Returned in a raw array format from AD
- *
- * @param string $username The username to query
- * @param array $fields Array of parameters to query
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return mixed
- */
- public function infoCollection($username, $fields = NULL, $isGUID = false)
- {
- if ($username === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
-
- $info = $this->info($username, $fields, $isGUID);
-
- if ($info !== false) {
- $collection = new adLDAPUserCollection($info, $this->adldap);
- return $collection;
- }
- return false;
- }
-
- /**
- * Determine if a user is in a specific group
- *
- * @param string $username The username to query
- * @param string $group The name of the group to check against
- * @param bool $recursive Check groups recursively
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function inGroup($username, $group, $recursive = NULL, $isGUID = false)
- {
- if ($username === NULL) { return false; }
- if ($group === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
- if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
-
- // Get a list of the groups
- $groups = $this->groups($username, $recursive, $isGUID);
-
- // Return true if the specified group is in the group list
- if (in_array($group, $groups)) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Determine a user's password expiry date
- *
- * @param string $username The username to query
- * @param book $isGUID Is the username passed a GUID or a samAccountName
- * @requires bcmath http://www.php.net/manual/en/book.bc.php
- * @return array
- */
- public function passwordExpiry($username, $isGUID = false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- if (!$this->adldap->getLdapBind()) { return false; }
- if (!function_exists('bcmod')) { throw new adLDAPException("Missing function support [bcmod] http://www.php.net/manual/en/book.bc.php"); };
-
- $userInfo = $this->info($username, array("pwdlastset", "useraccountcontrol"), $isGUID);
- $pwdLastSet = $userInfo[0]['pwdlastset'][0];
- $status = array();
-
- if ($userInfo[0]['useraccountcontrol'][0] == '66048') {
- // Password does not expire
- return "Does not expire";
- }
- if ($pwdLastSet === '0') {
- // Password has already expired
- return "Password has expired";
- }
-
- // Password expiry in AD can be calculated from TWO values:
- // - User's own pwdLastSet attribute: stores the last time the password was changed
- // - Domain's maxPwdAge attribute: how long passwords last in the domain
- //
- // Although Microsoft chose to use a different base and unit for time measurements.
- // This function will convert them to Unix timestamps
- $sr = ldap_read($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), 'objectclass=*', array('maxPwdAge'));
- if (!$sr) {
- return false;
- }
- $info = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
- $maxPwdAge = $info[0]['maxpwdage'][0];
-
-
- // See MSDN: http://msdn.microsoft.com/en-us/library/ms974598.aspx
- //
- // pwdLastSet contains the number of 100 nanosecond intervals since January 1, 1601 (UTC),
- // stored in a 64 bit integer.
- //
- // The number of seconds between this date and Unix epoch is 11644473600.
- //
- // maxPwdAge is stored as a large integer that represents the number of 100 nanosecond
- // intervals from the time the password was set before the password expires.
- //
- // We also need to scale this to seconds but also this value is a _negative_ quantity!
- //
- // If the low 32 bits of maxPwdAge are equal to 0 passwords do not expire
- //
- // Unfortunately the maths involved are too big for PHP integers, so I've had to require
- // BCMath functions to work with arbitrary precision numbers.
- if (bcmod($maxPwdAge, 4294967296) === '0') {
- return "Domain does not expire passwords";
- }
-
- // Add maxpwdage and pwdlastset and we get password expiration time in Microsoft's
- // time units. Because maxpwd age is negative we need to subtract it.
- $pwdExpire = bcsub($pwdLastSet, $maxPwdAge);
-
- // Convert MS's time to Unix time
- $status['expiryts'] = bcsub(bcdiv($pwdExpire, '10000000'), '11644473600');
- $status['expiryformat'] = date('Y-m-d H:i:s', bcsub(bcdiv($pwdExpire, '10000000'), '11644473600'));
-
- return $status;
- }
-
- /**
- * Modify a user
- *
- * @param string $username The username to query
- * @param array $attributes The attributes to modify. Note if you set the enabled attribute you must not specify any other attributes
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function modify($username, $attributes, $isGUID = false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- if (array_key_exists("password", $attributes) && !$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) {
- throw new adLDAPException('SSL/TLS must be configured on your webserver and enabled in the class to set passwords.');
- }
-
- // Find the dn of the user
- $userDn = $this->dn($username, $isGUID);
- if ($userDn === false) {
- return false;
- }
-
- // Translate the update to the LDAP schema
- $mod = $this->adldap->adldap_schema($attributes);
-
- // Check to see if this is an enabled status update
- if (!$mod && !array_key_exists("enabled", $attributes)){
- return false;
- }
-
- // Set the account control attribute (only if specified)
- if (array_key_exists("enabled", $attributes)){
- if ($attributes["enabled"]){
- $controlOptions = array("NORMAL_ACCOUNT");
- }
- else {
- $controlOptions = array("NORMAL_ACCOUNT", "ACCOUNTDISABLE");
- }
- $mod["userAccountControl"][0] = $this->accountControl($controlOptions);
- }
-
- // Do the update
- $result = @ldap_modify($this->adldap->getLdapConnection(), $userDn, $mod);
- if ($result == false) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Disable a user account
- *
- * @param string $username The username to disable
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function disable($username, $isGUID = false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- $attributes = array("enabled" => 0);
- $result = $this->modify($username, $attributes, $isGUID);
- if ($result == false) { return false; }
-
- return true;
- }
-
- /**
- * Enable a user account
- *
- * @param string $username The username to enable
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function enable($username, $isGUID = false)
- {
- if ($username === NULL) { return "Missing compulsory field [username]"; }
- $attributes = array("enabled" => 1);
- $result = $this->modify($username, $attributes, $isGUID);
- if ($result == false) { return false; }
-
- return true;
- }
-
- /**
- * Set the password of a user - This must be performed over SSL
- *
- * @param string $username The username to modify
- * @param string $password The new password
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return bool
- */
- public function password($username, $password, $isGUID = false)
- {
- if ($username === NULL) { return false; }
- if ($password === NULL) { return false; }
- if (!$this->adldap->getLdapBind()) { return false; }
- if (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) {
- throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
- }
-
- $userDn = $this->dn($username, $isGUID);
- if ($userDn === false) {
- return false;
- }
-
- $add=array();
- $add["unicodePwd"][0] = $this->encodePassword($password);
-
- $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $add);
- if ($result === false){
- $err = ldap_errno($this->adldap->getLdapConnection());
- if ($err) {
- $msg = 'Error ' . $err . ': ' . ldap_err2str($err) . '.';
- if($err == 53) {
- $msg .= ' Your password might not match the password policy.';
- }
- throw new adLDAPException($msg);
- }
- else {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Encode a password for transmission over LDAP
- *
- * @param string $password The password to encode
- * @return string
- */
- public function encodePassword($password)
- {
- $password="\"".$password."\"";
- $encoded="";
- for ($i=0; $i <strlen($password); $i++){ $encoded.="{$password{$i}}\000"; }
- return $encoded;
- }
-
- /**
- * Obtain the user's distinguished name based on their userid
- *
- *
- * @param string $username The username
- * @param bool $isGUID Is the username passed a GUID or a samAccountName
- * @return string
- */
- public function dn($username, $isGUID=false)
- {
- $user = $this->info($username, array("cn"), $isGUID);
- if ($user[0]["dn"] === NULL) {
- return false;
- }
- $userDn = $user[0]["dn"];
- return $userDn;
- }
-
- /**
- * Return a list of all users in AD
- *
- * @param bool $includeDescription Return a description of the user
- * @param string $search Search parameter
- * @param bool $sorted Sort the user accounts
- * @return array
- */
- public function all($includeDescription = false, $search = "*", $sorted = true)
- {
- if (!$this->adldap->getLdapBind()) { return false; }
-
- // Perform the search and grab all their details
- $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=" . $search . "))";
- $fields = array("samaccountname","displayname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- $usersArray = array();
- for ($i=0; $i<$entries["count"]; $i++){
- if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
- $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
- } elseif ($includeDescription){
- $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
- } else {
- array_push($usersArray, $entries[$i]["samaccountname"][0]);
- }
- }
- if ($sorted) {
- asort($usersArray);
- }
- return $usersArray;
- }
-
- /**
- * Converts a username (samAccountName) to a GUID
- *
- * @param string $username The username to query
- * @return string
- */
- public function usernameToGuid($username)
- {
- if (!$this->adldap->getLdapBind()){ return false; }
- if ($username === null){ return "Missing compulsory field [username]"; }
-
- $filter = "samaccountname=" . $username;
- $fields = array("objectGUID");
- $sr = @ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- if (ldap_count_entries($this->adldap->getLdapConnection(), $sr) > 0) {
- $entry = @ldap_first_entry($this->adldap->getLdapConnection(), $sr);
- $guid = @ldap_get_values_len($this->adldap->getLdapConnection(), $entry, 'objectGUID');
- $strGUID = $this->adldap->utilities()->binaryToText($guid[0]);
- return $strGUID;
- }
- return false;
- }
-
- /**
- * Return a list of all users in AD that have a specific value in a field
- *
- * @param bool $includeDescription Return a description of the user
- * @param string $searchField Field to search search for
- * @param string $searchFilter Value to search for in the specified field
- * @param bool $sorted Sort the user accounts
- * @return array
- */
- public function find($includeDescription = false, $searchField = false, $searchFilter = false, $sorted = true){
- if (!$this->adldap->getLdapBind()){ return false; }
-
- // Perform the search and grab all their details
- $searchParams = "";
- if ($searchField) {
- $searchParams = "(" . $searchField . "=" . $searchFilter . ")";
- }
- $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)" . $searchParams . ")";
- $fields = array("samaccountname","displayname");
- $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
- $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
-
- $usersArray = array();
- for ($i=0; $i < $entries["count"]; $i++) {
- if ($includeDescription && strlen($entries[$i]["displayname"][0]) > 0) {
- $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
- }
- else if ($includeDescription) {
- $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
- }
- else {
- array_push($usersArray, $entries[$i]["samaccountname"][0]);
- }
- }
- if ($sorted){
- asort($usersArray);
- }
- return ($usersArray);
- }
-
- /**
- * Move a user account to a different OU
- *
- * @param string $username The username to move (please be careful here!)
- * @param array $container The container or containers to move the user to (please be careful here!).
- * accepts containers in 1. parent 2. child order
- * @return array
- */
- public function move($username, $container)
- {
- if (!$this->adldap->getLdapBind()) { return false; }
- if ($username === null) { return "Missing compulsory field [username]"; }
- if ($container === null) { return "Missing compulsory field [container]"; }
- if (!is_array($container)) { return "Container must be an array"; }
-
- $userInfo = $this->info($username, array("*"));
- $dn = $userInfo[0]['distinguishedname'][0];
- $newRDn = "cn=" . $username;
- $container = array_reverse($container);
- $newContainer = "ou=" . implode(",ou=",$container);
- $newBaseDn = strtolower($newContainer) . "," . $this->adldap->getBaseDn();
- $result = @ldap_rename($this->adldap->getLdapConnection(), $dn, $newRDn, $newBaseDn, true);
- if ($result !== true) {
- return false;
- }
- return true;
- }
-
- /**
- * Get the last logon time of any user as a Unix timestamp
- *
- * @param string $username
- * @return long $unixTimestamp
- */
- public function getLastLogon($username) {
- if (!$this->adldap->getLdapBind()) { return false; }
- if ($username === null) { return "Missing compulsory field [username]"; }
- $userInfo = $this->info($username, array("lastLogonTimestamp"));
- $lastLogon = adLDAPUtils::convertWindowsTimeToUnixTime($userInfo[0]['lastLogonTimestamp'][0]);
- return $lastLogon;
- }
-
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage User
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+require_once(dirname(__FILE__) . '/../collections/adLDAPUserCollection.php');
+
+/**
+* USER FUNCTIONS
+*/
+class adLDAPUsers {
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+ /**
+ * Validate a user's login credentials
+ *
+ * @param string $username A user's AD username
+ * @param string $password A user's AD password
+ * @param bool optional $prevent_rebind
+ * @return bool
+ */
+ public function authenticate($username, $password, $preventRebind = false) {
+ return $this->adldap->authenticate($username, $password, $preventRebind);
+ }
+
+ /**
+ * Create a user
+ *
+ * If you specify a password here, this can only be performed over SSL
+ *
+ * @param array $attributes The attributes to set to the user account
+ * @return bool
+ */
+ public function create($attributes)
+ {
+ // Check for compulsory fields
+ if (!array_key_exists("username", $attributes)){ return "Missing compulsory field [username]"; }
+ if (!array_key_exists("firstname", $attributes)){ return "Missing compulsory field [firstname]"; }
+ if (!array_key_exists("surname", $attributes)){ return "Missing compulsory field [surname]"; }
+ if (!array_key_exists("email", $attributes)){ return "Missing compulsory field [email]"; }
+ if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
+ if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
+
+ if (array_key_exists("password",$attributes) && (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS())){
+ throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
+ }
+
+ if (!array_key_exists("display_name", $attributes)) {
+ $attributes["display_name"] = $attributes["firstname"] . " " . $attributes["surname"];
+ }
+
+ // Translate the schema
+ $add = $this->adldap->adldap_schema($attributes);
+
+ // Additional stuff only used for adding accounts
+ $add["cn"][0] = $attributes["display_name"];
+ $add["samaccountname"][0] = $attributes["username"];
+ $add["objectclass"][0] = "top";
+ $add["objectclass"][1] = "person";
+ $add["objectclass"][2] = "organizationalPerson";
+ $add["objectclass"][3] = "user"; //person?
+ //$add["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
+
+ // Set the account control attribute
+ $control_options = array("NORMAL_ACCOUNT");
+ if (!$attributes["enabled"]) {
+ $control_options[] = "ACCOUNTDISABLE";
+ }
+ $add["userAccountControl"][0] = $this->accountControl($control_options);
+
+ // Determine the container
+ $attributes["container"] = array_reverse($attributes["container"]);
+ $container = "OU=" . implode(", OU=",$attributes["container"]);
+
+ // Add the entry
+ $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"][0] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
+ if ($result != true) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Account control options
+ *
+ * @param array $options The options to convert to int
+ * @return int
+ */
+ protected function accountControl($options)
+ {
+ $val=0;
+
+ if (is_array($options)) {
+ if (in_array("SCRIPT",$options)){ $val=$val+1; }
+ if (in_array("ACCOUNTDISABLE",$options)){ $val=$val+2; }
+ if (in_array("HOMEDIR_REQUIRED",$options)){ $val=$val+8; }
+ if (in_array("LOCKOUT",$options)){ $val=$val+16; }
+ if (in_array("PASSWD_NOTREQD",$options)){ $val=$val+32; }
+ //PASSWD_CANT_CHANGE Note You cannot assign this permission by directly modifying the UserAccountControl attribute.
+ //For information about how to set the permission programmatically, see the "Property flag descriptions" section.
+ if (in_array("ENCRYPTED_TEXT_PWD_ALLOWED",$options)){ $val=$val+128; }
+ if (in_array("TEMP_DUPLICATE_ACCOUNT",$options)){ $val=$val+256; }
+ if (in_array("NORMAL_ACCOUNT",$options)){ $val=$val+512; }
+ if (in_array("INTERDOMAIN_TRUST_ACCOUNT",$options)){ $val=$val+2048; }
+ if (in_array("WORKSTATION_TRUST_ACCOUNT",$options)){ $val=$val+4096; }
+ if (in_array("SERVER_TRUST_ACCOUNT",$options)){ $val=$val+8192; }
+ if (in_array("DONT_EXPIRE_PASSWORD",$options)){ $val=$val+65536; }
+ if (in_array("MNS_LOGON_ACCOUNT",$options)){ $val=$val+131072; }
+ if (in_array("SMARTCARD_REQUIRED",$options)){ $val=$val+262144; }
+ if (in_array("TRUSTED_FOR_DELEGATION",$options)){ $val=$val+524288; }
+ if (in_array("NOT_DELEGATED",$options)){ $val=$val+1048576; }
+ if (in_array("USE_DES_KEY_ONLY",$options)){ $val=$val+2097152; }
+ if (in_array("DONT_REQ_PREAUTH",$options)){ $val=$val+4194304; }
+ if (in_array("PASSWORD_EXPIRED",$options)){ $val=$val+8388608; }
+ if (in_array("TRUSTED_TO_AUTH_FOR_DELEGATION",$options)){ $val=$val+16777216; }
+ }
+ return $val;
+ }
+
+ /**
+ * Delete a user account
+ *
+ * @param string $username The username to delete (please be careful here!)
+ * @param bool $isGUID Is the username a GUID or a samAccountName
+ * @return array
+ */
+ public function delete($username, $isGUID = false)
+ {
+ $userinfo = $this->info($username, array("*"), $isGUID);
+ $dn = $userinfo[0]['distinguishedname'][0];
+ $result = $this->adldap->folder()->delete($dn);
+ if ($result != true) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Groups the user is a member of
+ *
+ * @param string $username The username to query
+ * @param bool $recursive Recursive list of groups
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return array
+ */
+ public function groups($username, $recursive = NULL, $isGUID = false)
+ {
+ if ($username === NULL) { return false; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ // Search the directory for their information
+ $info = @$this->info($username, array("memberof", "primarygroupid"), $isGUID);
+ $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); // Presuming the entry returned is our guy (unique usernames)
+
+ if ($recursive === true){
+ foreach ($groups as $id => $groupName){
+ $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
+ $groups = array_merge($groups, $extraGroups);
+ }
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Find information about the users. Returned in a raw array format from AD
+ *
+ * @param string $username The username to query
+ * @param array $fields Array of parameters to query
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return array
+ */
+ public function info($username, $fields = NULL, $isGUID = false)
+ {
+ if ($username === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ if ($isGUID === true) {
+ $username = $this->adldap->utilities()->strGuidToHex($username);
+ $filter = "objectguid=" . $username;
+ }
+ else if (strstr($username, "@")) {
+ $filter = "userPrincipalName=" . $username;
+ }
+ else {
+ $filter = "samaccountname=" . $username;
+ }
+ $filter = "(&(objectCategory=person)({$filter}))";
+ if ($fields === NULL) {
+ $fields = array("samaccountname","mail","memberof","department","displayname","telephonenumber","primarygroupid","objectsid");
+ }
+ if (!in_array("objectsid", $fields)) {
+ $fields[] = "objectsid";
+ }
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ if (isset($entries[0])) {
+ if ($entries[0]['count'] >= 1) {
+ if (in_array("memberof", $fields)) {
+ // AD does not return the primary group in the ldap query, we may need to fudge it
+ if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){
+ //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
+ $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
+ } else {
+ $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
+ }
+ if (!isset($entries[0]["memberof"]["count"])) {
+ $entries[0]["memberof"]["count"] = 0;
+ }
+ $entries[0]["memberof"]["count"]++;
+ }
+ }
+
+ return $entries;
+ }
+ return false;
+ }
+
+ /**
+ * Find information about the users. Returned in a raw array format from AD
+ *
+ * @param string $username The username to query
+ * @param array $fields Array of parameters to query
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return mixed
+ */
+ public function infoCollection($username, $fields = NULL, $isGUID = false)
+ {
+ if ($username === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ $info = $this->info($username, $fields, $isGUID);
+
+ if ($info !== false) {
+ $collection = new adLDAPUserCollection($info, $this->adldap);
+ return $collection;
+ }
+ return false;
+ }
+
+ /**
+ * Determine if a user is in a specific group
+ *
+ * @param string $username The username to query
+ * @param string $group The name of the group to check against
+ * @param bool $recursive Check groups recursively
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function inGroup($username, $group, $recursive = NULL, $isGUID = false)
+ {
+ if ($username === NULL) { return false; }
+ if ($group === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
+
+ // Get a list of the groups
+ $groups = $this->groups($username, $recursive, $isGUID);
+
+ // Return true if the specified group is in the group list
+ if (in_array($group, $groups)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine a user's password expiry date
+ *
+ * @param string $username The username to query
+ * @param book $isGUID Is the username passed a GUID or a samAccountName
+ * @requires bcmath http://www.php.net/manual/en/book.bc.php
+ * @return array
+ */
+ public function passwordExpiry($username, $isGUID = false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if (!function_exists('bcmod')) { throw new adLDAPException("Missing function support [bcmod] http://www.php.net/manual/en/book.bc.php"); };
+
+ $userInfo = $this->info($username, array("pwdlastset", "useraccountcontrol"), $isGUID);
+ $pwdLastSet = $userInfo[0]['pwdlastset'][0];
+ $status = array();
+
+ if ($userInfo[0]['useraccountcontrol'][0] == '66048') {
+ // Password does not expire
+ return "Does not expire";
+ }
+ if ($pwdLastSet === '0') {
+ // Password has already expired
+ return "Password has expired";
+ }
+
+ // Password expiry in AD can be calculated from TWO values:
+ // - User's own pwdLastSet attribute: stores the last time the password was changed
+ // - Domain's maxPwdAge attribute: how long passwords last in the domain
+ //
+ // Although Microsoft chose to use a different base and unit for time measurements.
+ // This function will convert them to Unix timestamps
+ $sr = ldap_read($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), 'objectclass=*', array('maxPwdAge'));
+ if (!$sr) {
+ return false;
+ }
+ $info = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+ $maxPwdAge = $info[0]['maxpwdage'][0];
+
+
+ // See MSDN: http://msdn.microsoft.com/en-us/library/ms974598.aspx
+ //
+ // pwdLastSet contains the number of 100 nanosecond intervals since January 1, 1601 (UTC),
+ // stored in a 64 bit integer.
+ //
+ // The number of seconds between this date and Unix epoch is 11644473600.
+ //
+ // maxPwdAge is stored as a large integer that represents the number of 100 nanosecond
+ // intervals from the time the password was set before the password expires.
+ //
+ // We also need to scale this to seconds but also this value is a _negative_ quantity!
+ //
+ // If the low 32 bits of maxPwdAge are equal to 0 passwords do not expire
+ //
+ // Unfortunately the maths involved are too big for PHP integers, so I've had to require
+ // BCMath functions to work with arbitrary precision numbers.
+ if (bcmod($maxPwdAge, 4294967296) === '0') {
+ return "Domain does not expire passwords";
+ }
+
+ // Add maxpwdage and pwdlastset and we get password expiration time in Microsoft's
+ // time units. Because maxpwd age is negative we need to subtract it.
+ $pwdExpire = bcsub($pwdLastSet, $maxPwdAge);
+
+ // Convert MS's time to Unix time
+ $status['expiryts'] = bcsub(bcdiv($pwdExpire, '10000000'), '11644473600');
+ $status['expiryformat'] = date('Y-m-d H:i:s', bcsub(bcdiv($pwdExpire, '10000000'), '11644473600'));
+
+ return $status;
+ }
+
+ /**
+ * Modify a user
+ *
+ * @param string $username The username to query
+ * @param array $attributes The attributes to modify. Note if you set the enabled attribute you must not specify any other attributes
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function modify($username, $attributes, $isGUID = false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ if (array_key_exists("password", $attributes) && !$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) {
+ throw new adLDAPException('SSL/TLS must be configured on your webserver and enabled in the class to set passwords.');
+ }
+
+ // Find the dn of the user
+ $userDn = $this->dn($username, $isGUID);
+ if ($userDn === false) {
+ return false;
+ }
+
+ // Translate the update to the LDAP schema
+ $mod = $this->adldap->adldap_schema($attributes);
+
+ // Check to see if this is an enabled status update
+ if (!$mod && !array_key_exists("enabled", $attributes)){
+ return false;
+ }
+
+ // Set the account control attribute (only if specified)
+ if (array_key_exists("enabled", $attributes)){
+ if ($attributes["enabled"]){
+ $controlOptions = array("NORMAL_ACCOUNT");
+ }
+ else {
+ $controlOptions = array("NORMAL_ACCOUNT", "ACCOUNTDISABLE");
+ }
+ $mod["userAccountControl"][0] = $this->accountControl($controlOptions);
+ }
+
+ // Do the update
+ $result = @ldap_modify($this->adldap->getLdapConnection(), $userDn, $mod);
+ if ($result == false) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Disable a user account
+ *
+ * @param string $username The username to disable
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function disable($username, $isGUID = false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ $attributes = array("enabled" => 0);
+ $result = $this->modify($username, $attributes, $isGUID);
+ if ($result == false) { return false; }
+
+ return true;
+ }
+
+ /**
+ * Enable a user account
+ *
+ * @param string $username The username to enable
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function enable($username, $isGUID = false)
+ {
+ if ($username === NULL) { return "Missing compulsory field [username]"; }
+ $attributes = array("enabled" => 1);
+ $result = $this->modify($username, $attributes, $isGUID);
+ if ($result == false) { return false; }
+
+ return true;
+ }
+
+ /**
+ * Set the password of a user - This must be performed over SSL
+ *
+ * @param string $username The username to modify
+ * @param string $password The new password
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return bool
+ */
+ public function password($username, $password, $isGUID = false)
+ {
+ if ($username === NULL) { return false; }
+ if ($password === NULL) { return false; }
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) {
+ throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
+ }
+
+ $userDn = $this->dn($username, $isGUID);
+ if ($userDn === false) {
+ return false;
+ }
+
+ $add=array();
+ $add["unicodePwd"][0] = $this->encodePassword($password);
+
+ $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $add);
+ if ($result === false){
+ $err = ldap_errno($this->adldap->getLdapConnection());
+ if ($err) {
+ $msg = 'Error ' . $err . ': ' . ldap_err2str($err) . '.';
+ if($err == 53) {
+ $msg .= ' Your password might not match the password policy.';
+ }
+ throw new adLDAPException($msg);
+ }
+ else {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Encode a password for transmission over LDAP
+ *
+ * @param string $password The password to encode
+ * @return string
+ */
+ public function encodePassword($password)
+ {
+ $password="\"".$password."\"";
+ $encoded="";
+ for ($i=0; $i <strlen($password); $i++){ $encoded.="{$password{$i}}\000"; }
+ return $encoded;
+ }
+
+ /**
+ * Obtain the user's distinguished name based on their userid
+ *
+ *
+ * @param string $username The username
+ * @param bool $isGUID Is the username passed a GUID or a samAccountName
+ * @return string
+ */
+ public function dn($username, $isGUID=false)
+ {
+ $user = $this->info($username, array("cn"), $isGUID);
+ if ($user[0]["dn"] === NULL) {
+ return false;
+ }
+ $userDn = $user[0]["dn"];
+ return $userDn;
+ }
+
+ /**
+ * Return a list of all users in AD
+ *
+ * @param bool $includeDescription Return a description of the user
+ * @param string $search Search parameter
+ * @param bool $sorted Sort the user accounts
+ * @return array
+ */
+ public function all($includeDescription = false, $search = "*", $sorted = true)
+ {
+ if (!$this->adldap->getLdapBind()) { return false; }
+
+ // Perform the search and grab all their details
+ $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=" . $search . "))";
+ $fields = array("samaccountname","displayname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ $usersArray = array();
+ for ($i=0; $i<$entries["count"]; $i++){
+ if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
+ $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
+ } elseif ($includeDescription){
+ $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
+ } else {
+ array_push($usersArray, $entries[$i]["samaccountname"][0]);
+ }
+ }
+ if ($sorted) {
+ asort($usersArray);
+ }
+ return $usersArray;
+ }
+
+ /**
+ * Converts a username (samAccountName) to a GUID
+ *
+ * @param string $username The username to query
+ * @return string
+ */
+ public function usernameToGuid($username)
+ {
+ if (!$this->adldap->getLdapBind()){ return false; }
+ if ($username === null){ return "Missing compulsory field [username]"; }
+
+ $filter = "samaccountname=" . $username;
+ $fields = array("objectGUID");
+ $sr = @ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ if (ldap_count_entries($this->adldap->getLdapConnection(), $sr) > 0) {
+ $entry = @ldap_first_entry($this->adldap->getLdapConnection(), $sr);
+ $guid = @ldap_get_values_len($this->adldap->getLdapConnection(), $entry, 'objectGUID');
+ $strGUID = $this->adldap->utilities()->binaryToText($guid[0]);
+ return $strGUID;
+ }
+ return false;
+ }
+
+ /**
+ * Return a list of all users in AD that have a specific value in a field
+ *
+ * @param bool $includeDescription Return a description of the user
+ * @param string $searchField Field to search search for
+ * @param string $searchFilter Value to search for in the specified field
+ * @param bool $sorted Sort the user accounts
+ * @return array
+ */
+ public function find($includeDescription = false, $searchField = false, $searchFilter = false, $sorted = true){
+ if (!$this->adldap->getLdapBind()){ return false; }
+
+ // Perform the search and grab all their details
+ $searchParams = "";
+ if ($searchField) {
+ $searchParams = "(" . $searchField . "=" . $searchFilter . ")";
+ }
+ $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)" . $searchParams . ")";
+ $fields = array("samaccountname","displayname");
+ $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
+ $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
+
+ $usersArray = array();
+ for ($i=0; $i < $entries["count"]; $i++) {
+ if ($includeDescription && strlen($entries[$i]["displayname"][0]) > 0) {
+ $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
+ }
+ else if ($includeDescription) {
+ $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
+ }
+ else {
+ array_push($usersArray, $entries[$i]["samaccountname"][0]);
+ }
+ }
+ if ($sorted){
+ asort($usersArray);
+ }
+ return ($usersArray);
+ }
+
+ /**
+ * Move a user account to a different OU
+ *
+ * @param string $username The username to move (please be careful here!)
+ * @param array $container The container or containers to move the user to (please be careful here!).
+ * accepts containers in 1. parent 2. child order
+ * @return array
+ */
+ public function move($username, $container)
+ {
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if ($username === null) { return "Missing compulsory field [username]"; }
+ if ($container === null) { return "Missing compulsory field [container]"; }
+ if (!is_array($container)) { return "Container must be an array"; }
+
+ $userInfo = $this->info($username, array("*"));
+ $dn = $userInfo[0]['distinguishedname'][0];
+ $newRDn = "cn=" . $username;
+ $container = array_reverse($container);
+ $newContainer = "ou=" . implode(",ou=",$container);
+ $newBaseDn = strtolower($newContainer) . "," . $this->adldap->getBaseDn();
+ $result = @ldap_rename($this->adldap->getLdapConnection(), $dn, $newRDn, $newBaseDn, true);
+ if ($result !== true) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get the last logon time of any user as a Unix timestamp
+ *
+ * @param string $username
+ * @return long $unixTimestamp
+ */
+ public function getLastLogon($username) {
+ if (!$this->adldap->getLdapBind()) { return false; }
+ if ($username === null) { return "Missing compulsory field [username]"; }
+ $userInfo = $this->info($username, array("lastLogonTimestamp"));
+ $lastLogon = adLDAPUtils::convertWindowsTimeToUnixTime($userInfo[0]['lastLogonTimestamp'][0]);
+ return $lastLogon;
+ }
+
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php b/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php
index f039a4290..5e8644188 100644
--- a/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php
+++ b/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php
@@ -1,264 +1,264 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Utils
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
- */
-require_once(dirname(__FILE__) . '/../adLDAP.php');
-
-/**
-* UTILITY FUNCTIONS
-*/
-class adLDAPUtils {
- const ADLDAP_VERSION = '4.0.4';
-
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- public function __construct(adLDAP $adldap) {
- $this->adldap = $adldap;
- }
-
-
- /**
- * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
- *
- * @param array $groups
- * @return array
- */
- public function niceNames($groups)
- {
-
- $groupArray = array();
- for ($i=0; $i<$groups["count"]; $i++){ // For each group
- $line = $groups[$i];
-
- if (strlen($line)>0) {
- // More presumptions, they're all prefixed with CN=
- // so we ditch the first three characters and the group
- // name goes up to the first comma
- $bits=explode(",", $line);
- $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
- }
- }
- return $groupArray;
- }
-
- /**
- * Escape characters for use in an ldap_create function
- *
- * @param string $str
- * @return string
- */
- public function escapeCharacters($str) {
- $str = str_replace(",", "\,", $str);
- return $str;
- }
-
- /**
- * Escape strings for the use in LDAP filters
- *
- * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
- * Ported from Perl's Net::LDAP::Util escape_filter_value
- *
- * @param string $str The string the parse
- * @author Port by Andreas Gohr <andi@splitbrain.org>
- * @return string
- */
- public function ldapSlashes($str){
- return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e',
- '"\\\\\".join("",unpack("H2","$1"))',
- $str);
- }
-
- /**
- * Converts a string GUID to a hexdecimal value so it can be queried
- *
- * @param string $strGUID A string representation of a GUID
- * @return string
- */
- public function strGuidToHex($strGUID)
- {
- $strGUID = str_replace('-', '', $strGUID);
-
- $octet_str = '\\' . substr($strGUID, 6, 2);
- $octet_str .= '\\' . substr($strGUID, 4, 2);
- $octet_str .= '\\' . substr($strGUID, 2, 2);
- $octet_str .= '\\' . substr($strGUID, 0, 2);
- $octet_str .= '\\' . substr($strGUID, 10, 2);
- $octet_str .= '\\' . substr($strGUID, 8, 2);
- $octet_str .= '\\' . substr($strGUID, 14, 2);
- $octet_str .= '\\' . substr($strGUID, 12, 2);
- //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
- for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
- if (($i % 2) == 0) {
- $octet_str .= '\\' . substr($strGUID, $i, 2);
- }
- }
-
- return $octet_str;
- }
-
- /**
- * Convert a binary SID to a text SID
- *
- * @param string $binsid A Binary SID
- * @return string
- */
- public function getTextSID($binsid) {
- $hex_sid = bin2hex($binsid);
- $rev = hexdec(substr($hex_sid, 0, 2));
- $subcount = hexdec(substr($hex_sid, 2, 2));
- $auth = hexdec(substr($hex_sid, 4, 12));
- $result = "$rev-$auth";
-
- for ($x=0;$x < $subcount; $x++) {
- $subauth[$x] =
- hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
- $result .= "-" . $subauth[$x];
- }
-
- // Cheat by tacking on the S-
- return 'S-' . $result;
- }
-
- /**
- * Converts a little-endian hex number to one that hexdec() can convert
- *
- * @param string $hex A hex code
- * @return string
- */
- public function littleEndian($hex)
- {
- $result = '';
- for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
- $result .= substr($hex, $x, 2);
- }
- return $result;
- }
-
- /**
- * Converts a binary attribute to a string
- *
- * @param string $bin A binary LDAP attribute
- * @return string
- */
- public function binaryToText($bin)
- {
- $hex_guid = bin2hex($bin);
- $hex_guid_to_guid_str = '';
- for($k = 1; $k <= 4; ++$k) {
- $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
- }
- $hex_guid_to_guid_str .= '-';
- for($k = 1; $k <= 2; ++$k) {
- $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
- }
- $hex_guid_to_guid_str .= '-';
- for($k = 1; $k <= 2; ++$k) {
- $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
- }
- $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
- $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
- return strtoupper($hex_guid_to_guid_str);
- }
-
- /**
- * Converts a binary GUID to a string GUID
- *
- * @param string $binaryGuid The binary GUID attribute to convert
- * @return string
- */
- public function decodeGuid($binaryGuid)
- {
- if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
-
- $strGUID = $this->binaryToText($binaryGuid);
- return $strGUID;
- }
-
- /**
- * Convert a boolean value to a string
- * You should never need to call this yourself
- *
- * @param bool $bool Boolean value
- * @return string
- */
- public function boolToStr($bool)
- {
- return ($bool) ? 'TRUE' : 'FALSE';
- }
-
- /**
- * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
- */
- public function encode8Bit(&$item, $key) {
- $encode = false;
- if (is_string($item)) {
- for ($i=0; $i<strlen($item); $i++) {
- if (ord($item[$i]) >> 7) {
- $encode = true;
- }
- }
- }
- if ($encode === true && $key != 'password') {
- $item = utf8_encode($item);
- }
- }
-
- /**
- * Get the current class version number
- *
- * @return string
- */
- public function getVersion() {
- return self::ADLDAP_VERSION;
- }
-
- /**
- * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
- *
- * @param long $windowsTime
- * @return long $unixTime
- */
- public static function convertWindowsTimeToUnixTime($windowsTime) {
- $unixTime = round($windowsTime / 10000000) - 11644477200;
- return $unixTime;
- }
-}
-
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Utils
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+ */
+require_once(dirname(__FILE__) . '/../adLDAP.php');
+
+/**
+* UTILITY FUNCTIONS
+*/
+class adLDAPUtils {
+ const ADLDAP_VERSION = '4.0.4';
+
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ public function __construct(adLDAP $adldap) {
+ $this->adldap = $adldap;
+ }
+
+
+ /**
+ * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
+ *
+ * @param array $groups
+ * @return array
+ */
+ public function niceNames($groups)
+ {
+
+ $groupArray = array();
+ for ($i=0; $i<$groups["count"]; $i++){ // For each group
+ $line = $groups[$i];
+
+ if (strlen($line)>0) {
+ // More presumptions, they're all prefixed with CN=
+ // so we ditch the first three characters and the group
+ // name goes up to the first comma
+ $bits=explode(",", $line);
+ $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
+ }
+ }
+ return $groupArray;
+ }
+
+ /**
+ * Escape characters for use in an ldap_create function
+ *
+ * @param string $str
+ * @return string
+ */
+ public function escapeCharacters($str) {
+ $str = str_replace(",", "\,", $str);
+ return $str;
+ }
+
+ /**
+ * Escape strings for the use in LDAP filters
+ *
+ * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
+ * Ported from Perl's Net::LDAP::Util escape_filter_value
+ *
+ * @param string $str The string the parse
+ * @author Port by Andreas Gohr <andi@splitbrain.org>
+ * @return string
+ */
+ public function ldapSlashes($str){
+ return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e',
+ '"\\\\\".join("",unpack("H2","$1"))',
+ $str);
+ }
+
+ /**
+ * Converts a string GUID to a hexdecimal value so it can be queried
+ *
+ * @param string $strGUID A string representation of a GUID
+ * @return string
+ */
+ public function strGuidToHex($strGUID)
+ {
+ $strGUID = str_replace('-', '', $strGUID);
+
+ $octet_str = '\\' . substr($strGUID, 6, 2);
+ $octet_str .= '\\' . substr($strGUID, 4, 2);
+ $octet_str .= '\\' . substr($strGUID, 2, 2);
+ $octet_str .= '\\' . substr($strGUID, 0, 2);
+ $octet_str .= '\\' . substr($strGUID, 10, 2);
+ $octet_str .= '\\' . substr($strGUID, 8, 2);
+ $octet_str .= '\\' . substr($strGUID, 14, 2);
+ $octet_str .= '\\' . substr($strGUID, 12, 2);
+ //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
+ for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
+ if (($i % 2) == 0) {
+ $octet_str .= '\\' . substr($strGUID, $i, 2);
+ }
+ }
+
+ return $octet_str;
+ }
+
+ /**
+ * Convert a binary SID to a text SID
+ *
+ * @param string $binsid A Binary SID
+ * @return string
+ */
+ public function getTextSID($binsid) {
+ $hex_sid = bin2hex($binsid);
+ $rev = hexdec(substr($hex_sid, 0, 2));
+ $subcount = hexdec(substr($hex_sid, 2, 2));
+ $auth = hexdec(substr($hex_sid, 4, 12));
+ $result = "$rev-$auth";
+
+ for ($x=0;$x < $subcount; $x++) {
+ $subauth[$x] =
+ hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
+ $result .= "-" . $subauth[$x];
+ }
+
+ // Cheat by tacking on the S-
+ return 'S-' . $result;
+ }
+
+ /**
+ * Converts a little-endian hex number to one that hexdec() can convert
+ *
+ * @param string $hex A hex code
+ * @return string
+ */
+ public function littleEndian($hex)
+ {
+ $result = '';
+ for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
+ $result .= substr($hex, $x, 2);
+ }
+ return $result;
+ }
+
+ /**
+ * Converts a binary attribute to a string
+ *
+ * @param string $bin A binary LDAP attribute
+ * @return string
+ */
+ public function binaryToText($bin)
+ {
+ $hex_guid = bin2hex($bin);
+ $hex_guid_to_guid_str = '';
+ for($k = 1; $k <= 4; ++$k) {
+ $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
+ }
+ $hex_guid_to_guid_str .= '-';
+ for($k = 1; $k <= 2; ++$k) {
+ $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
+ }
+ $hex_guid_to_guid_str .= '-';
+ for($k = 1; $k <= 2; ++$k) {
+ $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
+ }
+ $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
+ $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
+ return strtoupper($hex_guid_to_guid_str);
+ }
+
+ /**
+ * Converts a binary GUID to a string GUID
+ *
+ * @param string $binaryGuid The binary GUID attribute to convert
+ * @return string
+ */
+ public function decodeGuid($binaryGuid)
+ {
+ if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
+
+ $strGUID = $this->binaryToText($binaryGuid);
+ return $strGUID;
+ }
+
+ /**
+ * Convert a boolean value to a string
+ * You should never need to call this yourself
+ *
+ * @param bool $bool Boolean value
+ * @return string
+ */
+ public function boolToStr($bool)
+ {
+ return ($bool) ? 'TRUE' : 'FALSE';
+ }
+
+ /**
+ * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
+ */
+ public function encode8Bit(&$item, $key) {
+ $encode = false;
+ if (is_string($item)) {
+ for ($i=0; $i<strlen($item); $i++) {
+ if (ord($item[$i]) >> 7) {
+ $encode = true;
+ }
+ }
+ }
+ if ($encode === true && $key != 'password') {
+ $item = utf8_encode($item);
+ }
+ }
+
+ /**
+ * Get the current class version number
+ *
+ * @return string
+ */
+ public function getVersion() {
+ return self::ADLDAP_VERSION;
+ }
+
+ /**
+ * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
+ *
+ * @param long $windowsTime
+ * @return long $unixTime
+ */
+ public static function convertWindowsTimeToUnixTime($windowsTime) {
+ $unixTime = round($windowsTime / 10000000) - 11644477200;
+ return $unixTime;
+ }
+}
+
?> \ No newline at end of file
diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php
index c0a2eb2fa..433d39f18 100644
--- a/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php
+++ b/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php
@@ -1,137 +1,137 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage Collection
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
-*/
-
-abstract class adLDAPCollection
-{
- /**
- * The current adLDAP connection via dependency injection
- *
- * @var adLDAP
- */
- protected $adldap;
-
- /**
- * The current object being modifed / called
- *
- * @var mixed
- */
- protected $currentObject;
-
- /**
- * The raw info array from Active Directory
- *
- * @var array
- */
- protected $info;
-
- public function __construct($info, adLDAP $adldap)
- {
- $this->setInfo($info);
- $this->adldap = $adldap;
- }
-
- /**
- * Set the raw info array from Active Directory
- *
- * @param array $info
- */
- public function setInfo(array $info)
- {
- if ($this->info && sizeof($info) >= 1) {
- unset($this->info);
- }
- $this->info = $info;
- }
-
- /**
- * Magic get method to retrieve data from the raw array in a formatted way
- *
- * @param string $attribute
- * @return mixed
- */
- public function __get($attribute)
- {
- if (isset($this->info[0]) && is_array($this->info[0])) {
- foreach ($this->info[0] as $keyAttr => $valueAttr) {
- if (strtolower($keyAttr) == strtolower($attribute)) {
- if ($this->info[0][strtolower($attribute)]['count'] == 1) {
- return $this->info[0][strtolower($attribute)][0];
- }
- else {
- $array = array();
- foreach ($this->info[0][strtolower($attribute)] as $key => $value) {
- if ((string)$key != 'count') {
- $array[$key] = $value;
- }
- }
- return $array;
- }
- }
- }
- }
- else {
- return NULL;
- }
- }
-
- /**
- * Magic set method to update an attribute
- *
- * @param string $attribute
- * @param string $value
- * @return bool
- */
- abstract public function __set($attribute, $value);
-
- /**
- * Magic isset method to check for the existence of an attribute
- *
- * @param string $attribute
- * @return bool
- */
- public function __isset($attribute) {
- if (isset($this->info[0]) && is_array($this->info[0])) {
- foreach ($this->info[0] as $keyAttr => $valueAttr) {
- if (strtolower($keyAttr) == strtolower($attribute)) {
- return true;
- }
- }
- }
- return false;
- }
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage Collection
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+*/
+
+abstract class adLDAPCollection
+{
+ /**
+ * The current adLDAP connection via dependency injection
+ *
+ * @var adLDAP
+ */
+ protected $adldap;
+
+ /**
+ * The current object being modifed / called
+ *
+ * @var mixed
+ */
+ protected $currentObject;
+
+ /**
+ * The raw info array from Active Directory
+ *
+ * @var array
+ */
+ protected $info;
+
+ public function __construct($info, adLDAP $adldap)
+ {
+ $this->setInfo($info);
+ $this->adldap = $adldap;
+ }
+
+ /**
+ * Set the raw info array from Active Directory
+ *
+ * @param array $info
+ */
+ public function setInfo(array $info)
+ {
+ if ($this->info && sizeof($info) >= 1) {
+ unset($this->info);
+ }
+ $this->info = $info;
+ }
+
+ /**
+ * Magic get method to retrieve data from the raw array in a formatted way
+ *
+ * @param string $attribute
+ * @return mixed
+ */
+ public function __get($attribute)
+ {
+ if (isset($this->info[0]) && is_array($this->info[0])) {
+ foreach ($this->info[0] as $keyAttr => $valueAttr) {
+ if (strtolower($keyAttr) == strtolower($attribute)) {
+ if ($this->info[0][strtolower($attribute)]['count'] == 1) {
+ return $this->info[0][strtolower($attribute)][0];
+ }
+ else {
+ $array = array();
+ foreach ($this->info[0][strtolower($attribute)] as $key => $value) {
+ if ((string)$key != 'count') {
+ $array[$key] = $value;
+ }
+ }
+ return $array;
+ }
+ }
+ }
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Magic set method to update an attribute
+ *
+ * @param string $attribute
+ * @param string $value
+ * @return bool
+ */
+ abstract public function __set($attribute, $value);
+
+ /**
+ * Magic isset method to check for the existence of an attribute
+ *
+ * @param string $attribute
+ * @return bool
+ */
+ public function __isset($attribute) {
+ if (isset($this->info[0]) && is_array($this->info[0])) {
+ foreach ($this->info[0] as $keyAttr => $valueAttr) {
+ if (strtolower($keyAttr) == strtolower($attribute)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php
index 4f11d8f41..09f82cadc 100644
--- a/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php
+++ b/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php
@@ -1,46 +1,46 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage ComputerCollection
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
-*/
-
-class adLDAPComputerCollection extends adLDAPCollection
-{
-
- public function __set($attribute, $value)
- {
-
- }
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage ComputerCollection
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+*/
+
+class adLDAPComputerCollection extends adLDAPCollection
+{
+
+ public function __set($attribute, $value)
+ {
+
+ }
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php
index d42fe6d4c..a9efad5a9 100644
--- a/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php
+++ b/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php
@@ -1,46 +1,46 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage ContactCollection
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
-*/
-
-class adLDAPContactCollection extends adLDAPCollection
-{
-
- public function __set($attribute, $value)
- {
-
- }
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage ContactCollection
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+*/
+
+class adLDAPContactCollection extends adLDAPCollection
+{
+
+ public function __set($attribute, $value)
+ {
+
+ }
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php
index cff12fc20..ef4af8df2 100644
--- a/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php
+++ b/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php
@@ -1,46 +1,46 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage GroupCollection
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
-*/
-
-class adLDAPGroupCollection extends adLDAPCollection
-{
-
- public function __set($attribute, $value)
- {
-
- }
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage GroupCollection
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+*/
+
+class adLDAPGroupCollection extends adLDAPCollection
+{
+
+ public function __set($attribute, $value)
+ {
+
+ }
+}
+?>
diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php
index 801d90296..63fce5f96 100644
--- a/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php
+++ b/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php
@@ -1,46 +1,46 @@
-<?php
-/**
- * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
- * Version 4.0.4
- *
- * PHP Version 5 with SSL and LDAP support
- *
- * Written by Scott Barnett, Richard Hyland
- * email: scott@wiggumworld.com, adldap@richardhyland.com
- * http://adldap.sourceforge.net/
- *
- * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- *
- * We'd appreciate any improvements or additions to be submitted back
- * to benefit the entire community :)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * @category ToolsAndUtilities
- * @package adLDAP
- * @subpackage UserCollection
- * @author Scott Barnett, Richard Hyland
- * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
- * @revision $Revision: 97 $
- * @version 4.0.4
- * @link http://adldap.sourceforge.net/
-*/
-
-class adLDAPUserCollection extends adLDAPCollection
-{
-
- public function __set($attribute, $value)
- {
-
- }
-}
-?>
+<?php
+/**
+ * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
+ * Version 4.0.4
+ *
+ * PHP Version 5 with SSL and LDAP support
+ *
+ * Written by Scott Barnett, Richard Hyland
+ * email: scott@wiggumworld.com, adldap@richardhyland.com
+ * http://adldap.sourceforge.net/
+ *
+ * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ *
+ * We'd appreciate any improvements or additions to be submitted back
+ * to benefit the entire community :)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * @category ToolsAndUtilities
+ * @package adLDAP
+ * @subpackage UserCollection
+ * @author Scott Barnett, Richard Hyland
+ * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
+ * @revision $Revision: 97 $
+ * @version 4.0.4
+ * @link http://adldap.sourceforge.net/
+*/
+
+class adLDAPUserCollection extends adLDAPCollection
+{
+
+ public function __set($attribute, $value)
+ {
+
+ }
+}
+?>
diff --git a/lib/plugins/authad/lang/ar/settings.php b/lib/plugins/authad/lang/ar/settings.php
new file mode 100644
index 000000000..d2a2e2a35
--- /dev/null
+++ b/lib/plugins/authad/lang/ar/settings.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author alhajr <alhajr300@gmail.com>
+ */
+$lang['account_suffix'] = 'لاحقة الحساب الخاص بك. على سبيل المثال. <code>@my.domain.org</code>';
+$lang['domain_controllers'] = 'قائمة مفصولة بفواصل من وحدات التحكم بالمجال. على سبيل المثال. <code>srv1.domain.org,srv2.domain.org</code>';
+$lang['admin_password'] = 'كلمة المرور للمستخدم أعلاه.';
+$lang['real_primarygroup'] = 'ينبغي أن تحل المجموعة الأساسية الحقيقية بدلاً من افتراض "Domain Users" (أبطأ).';
+$lang['expirywarn'] = 'عدد الأيام المقدمة لتحذير المستخدم حول كلمة مرور منتهية الصلاحية. (0) للتعطيل.';
diff --git a/lib/plugins/authad/lang/bg/settings.php b/lib/plugins/authad/lang/bg/settings.php
index 877810c4e..bf7a2d8ce 100644
--- a/lib/plugins/authad/lang/bg/settings.php
+++ b/lib/plugins/authad/lang/bg/settings.php
@@ -1,18 +1,19 @@
<?php
+
/**
- * Bulgarian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Kiril <neohidra@gmail.com>
*/
-$lang['account_suffix'] = 'Наставка на акаунта Ви. Например <code>@някакъв.домейн.org</code>';
-$lang['base_dn'] = 'Вашият основен DN. Например <code>DC=моят,DC=домейн,DC=org</code>';
-$lang['domain_controllers'] = 'Domain controller списък, разделете сървърите със запетая. Например <code>сървър1.домейн.org,сървър2.домейн.org</code>';
-$lang['admin_username'] = 'Привилегирован Active Directory потребител с достъп до данните на останалите потребители. Не е задължително, но е необходимо за някои функционалности като изпращането на имейл за абонаменти.';
-$lang['admin_password'] = 'Паролата на горния потребител.';
-$lang['sso'] = 'Да се ползва ли еднократно вписване чрез Kerberos или NTLM?';
-$lang['real_primarygroup'] = 'Да се извлича ли истинската група вместо да се предполага "Domain Users" (по-бавно)';
-$lang['use_ssl'] = 'Ползване на SSL свързаност? Не отбелязвайте TLS (по-долу) ако включите опцията.';
-$lang['use_tls'] = 'Ползване на TLS свързаност? Не отбелязвайте SSL (по-горе) ако включите опцията.';
-$lang['debug'] = 'Показване на допълнителна debug информация при грешка?';
-$lang['expirywarn'] = 'Предупреждаване на потребителите Х дни преди изтичане валидността на паролата им. Въведете 0 за изключване.';
-$lang['additional'] = 'Списък с допълнителни AD атрибути за извличане от потребителските данни (разделяйте ги със запетая). Ползва се от няколко приставки.'; \ No newline at end of file
+$lang['account_suffix'] = 'Наставка на акаунта Ви. Например <code>@някакъв.домейн.org</code>';
+$lang['base_dn'] = 'Вашият основен DN. Например <code>DC=моят,DC=домейн,DC=org</code>';
+$lang['domain_controllers'] = 'Domain controller списък, разделете сървърите със запетая. Например <code>сървър1.домейн.org,сървър2.домейн.org</code>';
+$lang['admin_username'] = 'Привилегирован Active Directory потребител с достъп до данните на останалите потребители. Не е задължително, но е необходимо за някои функционалности като изпращането на имейл за абонаменти.';
+$lang['admin_password'] = 'Паролата на горния потребител.';
+$lang['sso'] = 'Да се ползва ли еднократно вписване чрез Kerberos или NTLM?';
+$lang['real_primarygroup'] = 'Да се извлича ли истинската група вместо да се предполага "Domain Users" (по-бавно)';
+$lang['use_ssl'] = 'Ползване на SSL свързаност? Не отбелязвайте TLS (по-долу) ако включите опцията.';
+$lang['use_tls'] = 'Ползване на TLS свързаност? Не отбелязвайте SSL (по-горе) ако включите опцията.';
+$lang['debug'] = 'Показване на допълнителна debug информация при грешка?';
+$lang['expirywarn'] = 'Предупреждаване на потребителите Х дни преди изтичане валидността на паролата им. Въведете 0 за изключване.';
+$lang['additional'] = 'Списък с допълнителни AD атрибути за извличане от потребителските данни (разделяйте ги със запетая). Ползва се от няколко приставки.';
diff --git a/lib/plugins/authad/lang/de/settings.php b/lib/plugins/authad/lang/de/settings.php
index fd624ad02..8105fb6f2 100644
--- a/lib/plugins/authad/lang/de/settings.php
+++ b/lib/plugins/authad/lang/de/settings.php
@@ -5,6 +5,8 @@
*
* @author Frank Loizzi <contact@software.bacal.de>
* @author Matthias Schulte <dokuwiki@lupo49.de>
+ * @author Ben Fey <benedikt.fey@beck-heun.de>
+ * @author Jonas Gröger <jonas.groeger@gmail.com>
*/
$lang['account_suffix'] = 'Ihr Account-Suffix. Z. B. <code>@my.domain.org</code>';
$lang['base_dn'] = 'Ihr Base-DN. Z. B. <code>DC=my,DC=domain,DC=org</code>';
@@ -12,6 +14,7 @@ $lang['domain_controllers'] = 'Eine Komma-separierte Liste von Domänen-Contr
$lang['admin_username'] = 'Ein priviligierter Active Directory-Benutzer mit Zugriff zu allen anderen Benutzerdaten. Optional, aber wird benötigt für Aktionen wie z. B. dass Senden von Benachrichtigungs-Mails.';
$lang['admin_password'] = 'Das Passwort des obigen Benutzers.';
$lang['sso'] = 'Soll Single-Sign-On via Kerberos oder NTLM benutzt werden?';
+$lang['sso_charset'] = 'Der Zeichensatz, mit dem der Server den Kerberos- oder NTLM-Benutzernamen versendet. Leer lassen für UTF-8 oder latin-1. Benötigt die iconv-Erweiterung.';
$lang['real_primarygroup'] = 'Soll die echte primäre Gruppe aufgelöst werden anstelle der Annahme "Domain Users" (langsamer)';
$lang['use_ssl'] = 'SSL-Verbindung benutzen? Falls ja, TLS unterhalb nicht aktivieren.';
$lang['use_tls'] = 'TLS-Verbindung benutzen? Falls ja, SSL oberhalb nicht aktivieren.';
diff --git a/lib/plugins/authad/lang/el/settings.php b/lib/plugins/authad/lang/el/settings.php
new file mode 100644
index 000000000..9bf23ea1c
--- /dev/null
+++ b/lib/plugins/authad/lang/el/settings.php
@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author chris taklis <ctaklis@gmail.com>
+ */
+$lang['admin_password'] = 'Ο κωδικός του παραπάνω χρήστη.';
diff --git a/lib/plugins/authad/lang/es/settings.php b/lib/plugins/authad/lang/es/settings.php
index 9d0aa80ac..98b78056b 100644
--- a/lib/plugins/authad/lang/es/settings.php
+++ b/lib/plugins/authad/lang/es/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author monica <may.dorado@gmail.com>
+ * @author Antonio Bueno <atnbueno@gmail.com>
*/
$lang['account_suffix'] = 'Su cuenta, sufijo. Ejem. <code> @ my.domain.org </ code>';
$lang['base_dn'] = 'Su base DN. Ejem. <code>DC=my,DC=dominio,DC=org</code>';
@@ -11,3 +12,4 @@ $lang['domain_controllers'] = 'Una lista separada por coma de los controlador
$lang['admin_username'] = 'Un usuario con privilegios de Active Directory con acceso a los datos de cualquier otro usuario. Opcional, pero es necesario para determinadas acciones como el envío de suscripciones de correos electrónicos.';
$lang['admin_password'] = 'La contraseña del usuario anterior.';
$lang['sso'] = 'En caso de inicio de sesión usará ¿Kerberos o NTLM?';
+$lang['sso_charset'] = 'La codificación con que tu servidor web pasará el nombre de usuario Kerberos o NTLM. Si es UTF-8 o latin-1 dejar en blanco. Requiere la extensión iconv.';
diff --git a/lib/plugins/authad/lang/fi/settings.php b/lib/plugins/authad/lang/fi/settings.php
index d3aa13e07..e2f432f36 100644
--- a/lib/plugins/authad/lang/fi/settings.php
+++ b/lib/plugins/authad/lang/fi/settings.php
@@ -1,6 +1,9 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Otto Vainio <otto@valjakko.net>
*/
+$lang['debug'] = 'Näytä lisää debug-koodia virheistä?';
+$lang['expirywarn'] = 'Montako päivää etukäteen varoitetaan salasanan vanhenemissta. 0 poistaa.';
diff --git a/lib/plugins/authad/lang/hu/settings.php b/lib/plugins/authad/lang/hu/settings.php
index 1510e1756..05acbdc2d 100644
--- a/lib/plugins/authad/lang/hu/settings.php
+++ b/lib/plugins/authad/lang/hu/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Marton Sebok <sebokmarton@gmail.com>
+ * @author Marina Vladi <deldadam@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>.';
@@ -11,6 +12,7 @@ $lang['domain_controllers'] = 'Tartománykezelők listája vesszővel elvála
$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['sso_charset'] = 'A webkiszolgáló karakterkészlete megfelel a Kerberos- és NTLM-felhasználóneveknek. Üres UTF-8 és Latin-1-hez. Szükséges az iconv bővítmény.';
$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!';
diff --git a/lib/plugins/authad/lang/ko/settings.php b/lib/plugins/authad/lang/ko/settings.php
index 2914bf47b..b104371fe 100644
--- a/lib/plugins/authad/lang/ko/settings.php
+++ b/lib/plugins/authad/lang/ko/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Myeongjin <aranet100@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['account_suffix'] = '계정 접미어. 예를 들어 <code>@my.domain.org</code>';
$lang['base_dn'] = '기본 DN. 예를 들어 <code>DC=my,DC=domain,DC=org</code>';
@@ -11,7 +12,8 @@ $lang['domain_controllers'] = '도메인 컨트롤러의 쉼표로 구분한
$lang['admin_username'] = '다른 모든 사용자의 데이터에 접근할 수 있는 권한이 있는 Active Directory 사용자. 선택적이지만 구독 메일을 보내는 등의 특정 작업에 필요합니다.';
$lang['admin_password'] = '위 사용자의 비밀번호.';
$lang['sso'] = 'Kerberos나 NTLM을 통해 Single-Sign-On을 사용해야 합니까?';
-$lang['real_primarygroup'] = '실제 기본 그룹은 "도메인 사용자"를 가정하는 대신 해결될 것입니다 (느림)';
+$lang['sso_charset'] = '당신의 웹서버의 문자집합은 Kerberos나 NTLM 사용자 이름으로 전달됩니다. UTF-8이나 라린-1이 비어 있습니다. icov 확장 기능이 필요합니다.';
+$lang['real_primarygroup'] = '실제 기본 그룹은 "도메인 사용자"를 가정하는 대신 해결될 것입니다. (느림)';
$lang['use_ssl'] = 'SSL 연결을 사용합니까? 사용한다면 아래 TLS을 활성화하지 마세요.';
$lang['use_tls'] = 'TLS 연결을 사용합니까? 사용한다면 위 SSL을 활성화하지 마세요.';
$lang['debug'] = '오류에 대한 추가적인 디버그 정보를 보이겠습니까?';
diff --git a/lib/plugins/authad/lang/nl/settings.php b/lib/plugins/authad/lang/nl/settings.php
index 69d67be9a..591d72941 100644
--- a/lib/plugins/authad/lang/nl/settings.php
+++ b/lib/plugins/authad/lang/nl/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Remon <no@email.local>
+ * @author Gerrit Uitslag <klapinklapin@gmail.com>
*/
$lang['account_suffix'] = 'Je account domeinnaam. Bijv <code>@mijn.domein.org</code>';
$lang['base_dn'] = 'Je basis DN. Bijv. <code>DC=mijn,DC=domein,DC=org</code>';
@@ -11,6 +12,7 @@ $lang['domain_controllers'] = 'Eeen kommagescheiden lijst van domeinservers.
$lang['admin_username'] = 'Een geprivilegeerde Active Directory gebruiker die bij alle gebruikersgegevens kan komen. Dit is optioneel maar kan nodig zijn voor bepaalde acties, zoals het versturen van abonnementsmailtjes.';
$lang['admin_password'] = 'Het wachtwoord van bovenstaande gebruiker.';
$lang['sso'] = 'Wordt voor Single-Sign-on Kerberos of NTLM gebruikt?';
+$lang['sso_charset'] = 'Het tekenset waarin je webserver de Kerberos of NTLM gebruikersnaam doorsturen. Leeglaten voor UTF-8 of latin-1. Vereist de iconv extensie.';
$lang['real_primarygroup'] = 'Moet de echte primaire groep worden opgezocht in plaats van het aannemen van "Domeingebruikers" (langzamer)';
$lang['use_ssl'] = 'SSL verbinding gebruiken? Zo ja, activeer dan niet de TLS optie hieronder.';
$lang['use_tls'] = 'TLS verbinding gebruiken? Zo ja, activeer dan niet de SSL verbinding hierboven.';
diff --git a/lib/plugins/authad/lang/pl/settings.php b/lib/plugins/authad/lang/pl/settings.php
index 9113c0e51..ad051b0ac 100644
--- a/lib/plugins/authad/lang/pl/settings.php
+++ b/lib/plugins/authad/lang/pl/settings.php
@@ -1,9 +1,12 @@
<?php
+
/**
- * Polish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Tomasz Bosak <bosak.tomasz@gmail.com>
*/
$lang['account_suffix'] = 'Przyrostek twojej nazwy konta np. <code>@my.domain.org</code>';
+$lang['base_dn'] = 'Twoje bazowe DN. Na przykład: <code>DC=my,DC=domain,DC=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.';
diff --git a/lib/plugins/authad/lang/pt-br/settings.php b/lib/plugins/authad/lang/pt-br/settings.php
index 76fb419a6..cdc748055 100644
--- a/lib/plugins/authad/lang/pt-br/settings.php
+++ b/lib/plugins/authad/lang/pt-br/settings.php
@@ -5,6 +5,7 @@
*
* @author Victor Westmann <victor.westmann@gmail.com>
* @author Frederico Guimarães <frederico@teia.bio.br>
+ * @author Juliano Marconi Lanigra <juliano.marconi@gmail.com>
*/
$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>';
@@ -12,6 +13,7 @@ $lang['domain_controllers'] = 'Uma lista de controles de domínios separada p
$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['sso_charset'] = 'A codificação de caracteres que seu servidor web passará o nome de usuário Kerberos ou NTLM. Vazio para UTF-8 ou latin-1. Requere a extensão iconv.';
$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.';
diff --git a/lib/plugins/authad/lang/ru/settings.php b/lib/plugins/authad/lang/ru/settings.php
index f849c201a..e662300d7 100644
--- a/lib/plugins/authad/lang/ru/settings.php
+++ b/lib/plugins/authad/lang/ru/settings.php
@@ -5,5 +5,12 @@
*
* @author Ivan I. Udovichenko (sendtome@mymailbox.pp.ua)
* @author Aleksandr Selivanov <alexgearbox@gmail.com>
+ * @author Artur <ncuxxx@gmail.com>
+ * @author Erli Moen <evseev.jr@gmail.com>
*/
+$lang['domain_controllers'] = 'Список DNS-серверов, разделенных запятой. Например:<code>srv1.domain.org,srv2.domain.org</code>';
$lang['admin_password'] = 'Пароль для указанного пользователя.';
+$lang['sso'] = 'Использовать SSO (Single-Sign-On) через Kerberos или NTLM?';
+$lang['use_ssl'] = 'Использовать SSL? Если да, то не включайте TLS.';
+$lang['use_tls'] = 'Использовать TLS? Если да, то не включайте SSL.';
+$lang['debug'] = 'Выводить дополнительную информацию при ошибках?';
diff --git a/lib/plugins/authad/lang/sk/settings.php b/lib/plugins/authad/lang/sk/settings.php
index 55f266dd6..b7d822f7e 100644
--- a/lib/plugins/authad/lang/sk/settings.php
+++ b/lib/plugins/authad/lang/sk/settings.php
@@ -6,10 +6,15 @@
* @author Martin Michalek <michalek.dev@gmail.com>
*/
$lang['account_suffix'] = 'Prípona používateľského účtu. Napr. <code>@my.domain.org</code>';
+$lang['base_dn'] = 'Vaše base DN. Napr. <code>DC=my,DC=domain,DC=org</code>';
+$lang['domain_controllers'] = 'Zoznam doménových radičov oddelených čiarkou. Napr. <code>srv1.domain.org,srv2.domain.org</code>';
$lang['admin_username'] = 'Privilegovaný používateľ Active Directory s prístupom ku všetkým dátam ostatných používateľov. Nepovinné nastavenie, ale potrebné pre určité akcie ako napríklad zasielanie mailov o zmenách.';
$lang['admin_password'] = 'Heslo vyššie uvedeného používateľa.';
$lang['sso'] = 'Použiť Single-Sign-On cez Kerberos alebo NTLM?';
+$lang['sso_charset'] = 'Znaková sada, v ktorej bude webserver prenášať meno Kerberos or NTLM používateľa. Prázne pole znamená UTF-8 alebo latin-1. Vyžaduje iconv rozšírenie.';
+$lang['real_primarygroup'] = 'Použiť skutočnú primárnu skupinu používateľa namiesto "Doménoví používatelia" (pomalšie).';
$lang['use_ssl'] = 'Použiť SSL pripojenie? Ak áno, nepovoľte TLS nižšie.';
$lang['use_tls'] = 'Použiť TLS pripojenie? Ak áno, nepovoľte SSL vyššie.';
$lang['debug'] = 'Zobraziť doplňujúce ladiace informácie pri chybe?';
+$lang['expirywarn'] = 'Počet dní pred uplynutím platnosti hesla, počas ktorých používateľ dostáva upozornenie. 0 deaktivuje túto voľbu.';
$lang['additional'] = 'Zoznam dodatočných AD atribútov oddelených čiarkou získaných z údajov používateľa. Používané niektorými pluginmi.';
diff --git a/lib/plugins/authad/lang/zh/settings.php b/lib/plugins/authad/lang/zh/settings.php
index 84bdc1e5c..52ba2131b 100644
--- a/lib/plugins/authad/lang/zh/settings.php
+++ b/lib/plugins/authad/lang/zh/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author lainme <lainme993@gmail.com>
+ * @author oott123 <ip.192.168.1.1@qq.com>
*/
$lang['account_suffix'] = '您的账户后缀。例如 <code>@my.domain.org</code>';
$lang['base_dn'] = '您的基本分辨名。例如 <code>DC=my,DC=domain,DC=org</code>';
@@ -11,6 +12,7 @@ $lang['domain_controllers'] = '逗号分隔的域名控制器列表。例如
$lang['admin_username'] = '一个活动目录的特权用户,可以查看其他所有用户的数据。可选,但对某些活动例如发送订阅邮件是必须的。';
$lang['admin_password'] = '上述用户的密码。';
$lang['sso'] = '是否使用经由 Kerberos 和 NTLM 的 Single-Sign-On?';
+$lang['sso_charset'] = '服务器传入 Kerberos 或者 NTLM 用户名的编码。留空为 UTF-8 或 latin-1 。此功能需要服务器支持iconv扩展。';
$lang['real_primarygroup'] = ' 是否解析真实的主要组,而不是假设为“域用户” (较慢)';
$lang['use_ssl'] = '使用 SSL 连接?如果是,不要激活下面的 TLS。';
$lang['use_tls'] = '使用 TLS 连接?如果是 ,不要激活上面的 SSL。';
diff --git a/lib/plugins/authldap/auth.php b/lib/plugins/authldap/auth.php
index de1332282..31e2c5135 100644
--- a/lib/plugins/authldap/auth.php
+++ b/lib/plugins/authldap/auth.php
@@ -166,7 +166,7 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin {
// be accessible anonymously, so we try to rebind the current user here
list($loginuser, $loginsticky, $loginpass) = auth_getCookie();
if($loginuser && $loginpass) {
- $loginpass = PMA_blowfish_decrypt($loginpass, auth_cookiesalt(!$loginsticky));
+ $loginpass = auth_decrypt($loginpass, auth_cookiesalt(!$loginsticky, true));
$this->checkPass($loginuser, $loginpass);
}
}
diff --git a/lib/plugins/authldap/lang/ar/settings.php b/lib/plugins/authldap/lang/ar/settings.php
new file mode 100644
index 000000000..aaef7763f
--- /dev/null
+++ b/lib/plugins/authldap/lang/ar/settings.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author alhajr <alhajr300@gmail.com>
+ */
+$lang['port'] = 'LDAP المنفذ الملقم إذا لم يعط أي عنوان URL كامل أعلاه';
+$lang['version'] = 'إصدار نسخة البروتوكول الستخدامه. قد تحتاج لتعيين هذه القيمة إلى <code>3</code>';
+$lang['starttls'] = 'استخدام اتصالات TLS؟';
+$lang['referrals'] = 'يتبع الإحالات؟';
+$lang['deref'] = 'كيفية إلغاء مرجعية الأسماء المستعارة؟';
+$lang['bindpw'] = 'كلمة مرور المستخدم أعلاه';
diff --git a/lib/plugins/authldap/lang/bg/settings.php b/lib/plugins/authldap/lang/bg/settings.php
index 644672ca7..165216de8 100644
--- a/lib/plugins/authldap/lang/bg/settings.php
+++ b/lib/plugins/authldap/lang/bg/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Bulgarian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Kiril <neohidra@gmail.com>
*/
$lang['server'] = 'Вашият LDAP сървър. Име на хоста (<code>localhost</code>) или целият URL адрес (<code>ldap://сървър.tld:389</code>)';
@@ -16,4 +17,4 @@ $lang['referrals'] = 'Да бъдат ли следвани преп
$lang['bindpw'] = 'Парола за горния потребител';
$lang['userscope'] = 'Ограничаване на обхвата за търсене на потребители';
$lang['groupscope'] = 'Ограничаване на обхвата за търсене на потребителски групи';
-$lang['debug'] = 'Показване на допълнителна debug информация при грешка'; \ No newline at end of file
+$lang['debug'] = 'Показване на допълнителна debug информация при грешка';
diff --git a/lib/plugins/authldap/lang/da/settings.php b/lib/plugins/authldap/lang/da/settings.php
index a3558aa5c..b736504a5 100644
--- a/lib/plugins/authldap/lang/da/settings.php
+++ b/lib/plugins/authldap/lang/da/settings.php
@@ -4,6 +4,12 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Jens Hyllegaard <jens.hyllegaard@gmail.com>
+ * @author soer9648 <soer9648@eucl.dk>
*/
$lang['server'] = 'Din LDAP server. Enten værtsnavn (<code>localhost</code>) eller fuld kvalificeret URL (<code>ldap://server.tld:389</code>)';
+$lang['port'] = 'LDAP server port, hvis der ikke er angivet en komplet URL ovenfor.';
+$lang['usertree'] = 'Hvor findes brugerkonti. F.eks. <code>ou=Personer, dc=server, dc=tld</code>';
+$lang['grouptree'] = 'Hvor findes brugergrupper. F.eks. <code>ou=Grupper, dc=server, dc=tld</code>';
+$lang['starttls'] = 'Benyt TLS forbindelser?';
+$lang['bindpw'] = 'Kodeord til ovenstående bruger';
$lang['debug'] = 'Vis yderligere debug output ved fejl';
diff --git a/lib/plugins/authldap/lang/es/settings.php b/lib/plugins/authldap/lang/es/settings.php
new file mode 100644
index 000000000..f8c3ad014
--- /dev/null
+++ b/lib/plugins/authldap/lang/es/settings.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Antonio Bueno <atnbueno@gmail.com>
+ */
+$lang['starttls'] = 'Usar conexiones TLS?';
+$lang['debug'] = 'Mostrar información adicional para depuración de errores';
+$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/fi/settings.php b/lib/plugins/authldap/lang/fi/settings.php
index d3aa13e07..b15d8c676 100644
--- a/lib/plugins/authldap/lang/fi/settings.php
+++ b/lib/plugins/authldap/lang/fi/settings.php
@@ -1,6 +1,11 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Otto Vainio <otto@valjakko.net>
*/
+$lang['starttls'] = 'Käytä TLS yhteyttä';
+$lang['bindpw'] = 'Ylläolevan käyttäjän salasana';
+$lang['userscope'] = 'Etsi vain käyttäjiä';
+$lang['groupscope'] = 'Etsi vain ryhmiä';
diff --git a/lib/plugins/authldap/lang/he/settings.php b/lib/plugins/authldap/lang/he/settings.php
new file mode 100644
index 000000000..357a58c56
--- /dev/null
+++ b/lib/plugins/authldap/lang/he/settings.php
@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author matt carroll <matt.carroll@gmail.com>
+ */
+$lang['starttls'] = 'השתמש בחיבורי TLS';
diff --git a/lib/plugins/authldap/lang/it/settings.php b/lib/plugins/authldap/lang/it/settings.php
index 023159489..eba7cde6e 100644
--- a/lib/plugins/authldap/lang/it/settings.php
+++ b/lib/plugins/authldap/lang/it/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Edmondo Di Tucci <snarchio@gmail.com>
+ * @author Claudio Lanconelli <lancos@libero.it>
*/
$lang['server'] = 'Il tuo server LDAP. Inserire o l\'hostname (<code>localhost</code>) oppure un URL completo (<code>ldap://server.tld:389</code>)';
$lang['port'] = 'Porta del server LDAP se non è stato fornito un URL completo più sopra.';
@@ -13,3 +14,6 @@ $lang['userfilter'] = 'Filtro per cercare l\'account utente LDAP. Eg.
$lang['groupfilter'] = 'Filtro per cercare i gruppi LDAP. Eg. <code>(&amp;(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))</code>';
$lang['version'] = 'Versione protocollo da usare. Pu<code>3</code>';
$lang['starttls'] = 'Usare la connessione TSL?';
+$lang['userscope'] = 'Limita il contesto di ricerca per la ricerca degli utenti';
+$lang['groupscope'] = 'Limita il contesto di ricerca per la ricerca dei gruppi';
+$lang['debug'] = 'In caso di errori mostra ulteriori informazioni di debug';
diff --git a/lib/plugins/authldap/lang/ko/settings.php b/lib/plugins/authldap/lang/ko/settings.php
index 5c5341b31..ae8dc7ab6 100644
--- a/lib/plugins/authldap/lang/ko/settings.php
+++ b/lib/plugins/authldap/lang/ko/settings.php
@@ -17,8 +17,8 @@ $lang['referrals'] = '참고(referrals)를 허용하겠습니까? ';
$lang['deref'] = '어떻게 별명을 간접 참고하겠습니까?';
$lang['binddn'] = '익명 바인드가 충분하지 않으면 선택적인 바인드 사용자의 DN. 예를 들어 <code>cn=admin, dc=my, dc=home</code>';
$lang['bindpw'] = '위 사용자의 비밀번호';
-$lang['userscope'] = '사용자 찾기에 대한 찾기 범위 제한';
-$lang['groupscope'] = '그룹 찾기에 대한 찾기 범위 제한';
+$lang['userscope'] = '사용자 검색에 대한 검색 범위 제한';
+$lang['groupscope'] = '그룹 검색에 대한 검색 범위 제한';
$lang['groupkey'] = '(표준 AD 그룹 대신) 사용자 속성에서 그룹 구성원. 예를 들어 부서나 전화에서 그룹';
$lang['debug'] = '오류에 대한 추가적인 디버그 정보를 보이기';
$lang['deref_o_0'] = 'LDAP_DEREF_NEVER';
diff --git a/lib/plugins/authldap/lang/pl/settings.php b/lib/plugins/authldap/lang/pl/settings.php
index 44641f514..084521e0d 100644
--- a/lib/plugins/authldap/lang/pl/settings.php
+++ b/lib/plugins/authldap/lang/pl/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Polish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
*/
$lang['starttls'] = 'Użyć połączeń TLS?';
$lang['bindpw'] = 'Hasło powyższego użytkownika';
diff --git a/lib/plugins/authldap/lang/ru/settings.php b/lib/plugins/authldap/lang/ru/settings.php
index 70ad7b6f4..2b93e0fd4 100644
--- a/lib/plugins/authldap/lang/ru/settings.php
+++ b/lib/plugins/authldap/lang/ru/settings.php
@@ -5,5 +5,7 @@
*
* @author Ivan I. Udovichenko (sendtome@mymailbox.pp.ua)
* @author Aleksandr Selivanov <alexgearbox@gmail.com>
+ * @author Erli Moen <evseev.jr@gmail.com>
*/
+$lang['deref'] = 'Как расшифровывать псевдонимы?';
$lang['bindpw'] = 'Пароль для указанного пользователя.';
diff --git a/lib/plugins/authldap/lang/sk/settings.php b/lib/plugins/authldap/lang/sk/settings.php
index 48bd37395..c44f07e97 100644
--- a/lib/plugins/authldap/lang/sk/settings.php
+++ b/lib/plugins/authldap/lang/sk/settings.php
@@ -13,7 +13,13 @@ $lang['userfilter'] = 'LDAP filter pre vyhľadávanie používateľsk
$lang['groupfilter'] = 'LDAP filter pre vyhľadávanie skupín. Napr. <code>(&amp;(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))</code>';
$lang['version'] = 'Použitá verzia protokolu. Možno bude potrebné nastaviť na hodnotu <code>3</code>';
$lang['starttls'] = 'Použiť TLS pripojenie?';
+$lang['referrals'] = 'Majú byť nasledované odkazy na používateľov (referrals)?';
+$lang['deref'] = 'Ako previesť aliasy?';
+$lang['binddn'] = 'DN prípadného priradenia používateľa, ak anonymné priradenie nie je dostatočné. Napr. <code>cn=admin, dc=my, dc=home</code>';
$lang['bindpw'] = 'Heslo vyššie uvedeného používateľa';
+$lang['userscope'] = 'Obmedzenie oblasti pri vyhľadávaní používateľa';
+$lang['groupscope'] = 'Obmedzenie oblasti pri vyhľadávaní skupiny';
+$lang['groupkey'] = 'Príslušnost k skupine určená z daného atribútu používateľa (namiesto štandardnej AD skupiny) napr. skupiny podľa oddelenia alebo telefónneho čísla';
$lang['debug'] = 'Zobraziť doplňujúce ladiace informácie pri chybe';
$lang['deref_o_0'] = 'LDAP_DEREF_NEVER';
$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING';
diff --git a/lib/plugins/authldap/lang/zh-tw/settings.php b/lib/plugins/authldap/lang/zh-tw/settings.php
index d2513eeff..7e35ef632 100644
--- a/lib/plugins/authldap/lang/zh-tw/settings.php
+++ b/lib/plugins/authldap/lang/zh-tw/settings.php
@@ -1,5 +1,4 @@
<?php
-
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
@@ -20,3 +19,8 @@ $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/zh/settings.php b/lib/plugins/authldap/lang/zh/settings.php
index 77c2c6952..cdaf3dc64 100644
--- a/lib/plugins/authldap/lang/zh/settings.php
+++ b/lib/plugins/authldap/lang/zh/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author lainme <lainme993@gmail.com>
+ * @author oott123 <ip.192.168.1.1@qq.com>
*/
$lang['server'] = '您的 LDAP 服务器。填写主机名 (<code>localhost</code>) 或者完整的 URL (<code>ldap://server.tld:389</code>)';
$lang['port'] = 'LDAP 服务器端口 (如果上面没有给出完整的 URL)';
@@ -14,6 +15,7 @@ $lang['groupfilter'] = '用于搜索组的 LDAP 筛选器。例如 <co
$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'] = '限制用户搜索的范围';
diff --git a/lib/plugins/authmysql/lang/bg/settings.php b/lib/plugins/authmysql/lang/bg/settings.php
index fcc7f625d..cd6370218 100644
--- a/lib/plugins/authmysql/lang/bg/settings.php
+++ b/lib/plugins/authmysql/lang/bg/settings.php
@@ -1,8 +1,10 @@
<?php
+
/**
- * Bulgarian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Kiril <neohidra@gmail.com>
+ * @author Ivan Peltekov <ivan.peltekov@abv.bg>
*/
$lang['server'] = 'Вашият MySQL сървър';
$lang['user'] = 'MySQL потребителско име';
@@ -10,8 +12,8 @@ $lang['password'] = 'Парола за горния потреби
$lang['database'] = 'Име на базата от данни';
$lang['charset'] = 'Набор от знаци, който се ползва в базата от данни';
$lang['debug'] = 'Показване на допълнителна debug информация';
-
-
-$lang['debug_o_0'] = 'не';
-$lang['debug_o_1'] = 'само при грешка';
-$lang['debug_o_2'] = 'за всяко SQL запитване'; \ No newline at end of file
+$lang['checkPass'] = 'SQL заявка за проверка на паролите';
+$lang['getUserInfo'] = 'SQL заявка за извличане на информация за потребителя н';
+$lang['debug_o_0'] = 'не';
+$lang['debug_o_1'] = 'само при грешка';
+$lang['debug_o_2'] = 'за всяко SQL запитване';
diff --git a/lib/plugins/authmysql/lang/da/settings.php b/lib/plugins/authmysql/lang/da/settings.php
index 207d0ff60..1e38cb6b4 100644
--- a/lib/plugins/authmysql/lang/da/settings.php
+++ b/lib/plugins/authmysql/lang/da/settings.php
@@ -2,10 +2,25 @@
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- *
+ *
* @author Jens Hyllegaard <jens.hyllegaard@gmail.com>
+ * @author soer9648 <soer9648@eucl.dk>
*/
$lang['server'] = 'Din MySQL server';
+$lang['user'] = 'MySQL brugernavn';
+$lang['password'] = 'Kodeord til ovenstående bruger';
+$lang['database'] = 'Database der skal benyttes';
+$lang['charset'] = 'Tegnsæt benyttet i database';
+$lang['checkPass'] = 'SQL-sætning til at kontrollere kodeord';
+$lang['getUserInfo'] = 'SQL-sætning til at hente brugerinformation';
+$lang['getUsers'] = 'SQL-sætning til at liste alle brugere';
+$lang['addUser'] = 'SQL-sætning til at tilføje en ny bruger';
+$lang['addGroup'] = 'SQL-sætning til at tilføje en ny gruppe';
+$lang['addUserGroup'] = 'SQL-sætning til at tilføje en bruger til en eksisterende gruppe';
+$lang['delGroup'] = 'SQL-sætning til at fjerne en gruppe';
+$lang['delUser'] = 'SQL-sætning til at slette en bruger';
+$lang['delUserRefs'] = 'SQL-sætning til at fjerne en bruger fra alle grupper';
+$lang['updateUser'] = 'SQL-sætning til at opdatere en brugerprofil';
$lang['debug'] = 'Vis yderligere debug output';
$lang['debug_o_0'] = 'ingen';
$lang['debug_o_1'] = 'kun ved fejl';
diff --git a/lib/plugins/authmysql/lang/es/settings.php b/lib/plugins/authmysql/lang/es/settings.php
new file mode 100644
index 000000000..64d422102
--- /dev/null
+++ b/lib/plugins/authmysql/lang/es/settings.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Antonio Bueno <atnbueno@gmail.com>
+ */
+$lang['server'] = 'Tu servidor MySQL';
+$lang['user'] = 'Nombre de usuario MySQL';
+$lang['database'] = 'Base de datos a usar';
+$lang['charset'] = 'Codificación usada en la base de datos';
+$lang['debug'] = 'Mostrar información adicional para depuración de errores';
diff --git a/lib/plugins/authmysql/lang/hu/settings.php b/lib/plugins/authmysql/lang/hu/settings.php
index 4edceae1e..5936203fa 100644
--- a/lib/plugins/authmysql/lang/hu/settings.php
+++ b/lib/plugins/authmysql/lang/hu/settings.php
@@ -4,39 +4,40 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Marton Sebok <sebokmarton@gmail.com>
+ * @author Marina Vladi <deldadam@gmail.com>
*/
$lang['server'] = 'MySQL-szerver';
$lang['user'] = 'MySQL felhasználónév';
-$lang['password'] = 'Ehhez a jelszó';
+$lang['password'] = 'Fenti felhasználó jelszava';
$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'] = 'Hibakeresési üzenetek megjelenítése';
+$lang['forwardClearPass'] = 'A jelszó nyílt szövegként történő átadása az alábbi SQL-utasításoknak a passcrypt opció használata helyett';
+$lang['TablesToLock'] = 'Az íráskor zárolni kívánt 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'] = 'UPDATE-klauzula a felhasználó azonosítójának frissítéséhez';
+$lang['UpdatePass'] = 'UPDATE-klauzula a felhasználó jelszavának frissítéséhez';
+$lang['UpdateEmail'] = 'UPDATE-klauzula a felhasználó e-mail címének frissítéséhez';
+$lang['UpdateName'] = 'UPDATE-klauzula a felhasználó teljes nevének frissítéséhez';
+$lang['UpdateTarget'] = 'LIMIT-klauzula a felhasználó kiválasztásához az adatok frissítésekor';
+$lang['delUserGroup'] = 'SQL-utasítás felhasználó adott csoportból történő törléséhez ';
+$lang['getGroupID'] = 'SQL-utasítás adott 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/it/settings.php b/lib/plugins/authmysql/lang/it/settings.php
index 10ae72f87..e493ec7e9 100644
--- a/lib/plugins/authmysql/lang/it/settings.php
+++ b/lib/plugins/authmysql/lang/it/settings.php
@@ -1,5 +1,8 @@
<?php
+
/**
- * Italian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Claudio Lanconelli <lancos@libero.it>
*/
+$lang['debug'] = 'Mostra ulteriori informazioni di debug';
diff --git a/lib/plugins/authmysql/lang/ja/settings.php b/lib/plugins/authmysql/lang/ja/settings.php
index 0dc5f1ad8..e5d5689df 100644
--- a/lib/plugins/authmysql/lang/ja/settings.php
+++ b/lib/plugins/authmysql/lang/ja/settings.php
@@ -11,7 +11,7 @@ $lang['password'] = 'MySQL 接続用ユーザーのパスワード'
$lang['database'] = '使用するデータベース名';
$lang['charset'] = 'データベースの文字コード';
$lang['debug'] = 'デバック情報を表示する';
-$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 %{pass} を平文とする(DokiWiki側で暗号化しない)';
+$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 &#x25;{pass} を平文とする(DokiWiki側で暗号化しない)';
$lang['TablesToLock'] = '書き込み時にロックするテーブル(コンマ区切りで列挙)';
$lang['checkPass'] = 'パスワードの照合に用いる SQL ステートメント';
$lang['getUserInfo'] = 'ユーザー情報の取得に用いる SQL ステートメント';
diff --git a/lib/plugins/authmysql/lang/ko/settings.php b/lib/plugins/authmysql/lang/ko/settings.php
index 2175c1eea..b3479ad41 100644
--- a/lib/plugins/authmysql/lang/ko/settings.php
+++ b/lib/plugins/authmysql/lang/ko/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Myeongjin <aranet100@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['server'] = 'MySQL 서버';
$lang['user'] = 'MySQL 사용자 이름';
@@ -17,10 +18,10 @@ $lang['checkPass'] = '비밀번호를 확인하기 위한 SQL 문';
$lang['getUserInfo'] = '사용자 정보를 가져오기 위한 SQL 문';
$lang['getGroups'] = '사용자의 그룹 구성원을 가져오기 위한 SQL 문';
$lang['getUsers'] = '모든 사용자를 나타낼 SQL 문';
-$lang['FilterLogin'] = '로그인 이름 별로 사용자를 필터하기 위한 SQL 조항';
-$lang['FilterName'] = '전체 이름 별로 사용자를 필터하기 위한 SQL 조항';
-$lang['FilterEmail'] = '이메일 주소 별로 사용자를 필터하기 위한 SQL 조항';
-$lang['FilterGroup'] = '그룹 구성원 별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterLogin'] = '로그인 이름별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterName'] = '전체 이름별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterEmail'] = '이메일 주소별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterGroup'] = '그룹 구성원별로 사용자를 필터하기 위한 SQL 조항';
$lang['SortOrder'] = '사용자를 정렬할 SQL 조항';
$lang['addUser'] = '새 사용자를 추가할 SQL 문';
$lang['addGroup'] = '새 그룹을 추가할 SQL 문';
diff --git a/lib/plugins/authmysql/lang/pl/settings.php b/lib/plugins/authmysql/lang/pl/settings.php
index 93528cf34..5ae6bf168 100644
--- a/lib/plugins/authmysql/lang/pl/settings.php
+++ b/lib/plugins/authmysql/lang/pl/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Polish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
*/
$lang['server'] = 'Twój server MySQL';
$lang['user'] = 'Nazwa użytkownika MySQL';
diff --git a/lib/plugins/authmysql/lang/sk/settings.php b/lib/plugins/authmysql/lang/sk/settings.php
index 8c52f905e..d7e8cb286 100644
--- a/lib/plugins/authmysql/lang/sk/settings.php
+++ b/lib/plugins/authmysql/lang/sk/settings.php
@@ -34,5 +34,9 @@ $lang['UpdateLogin'] = 'SQL podmienka pre aktualizáciu prihlasovacieh
$lang['UpdatePass'] = 'SQL podmienka pre aktualizáciu hesla používateľa';
$lang['UpdateEmail'] = 'SQL podmienka pre aktualizáciu emailovej adresy používateľa';
$lang['UpdateName'] = 'SQL podmienka pre aktualizáciu mena a priezviska používateľa';
+$lang['UpdateTarget'] = 'Podmienka identifikácie používateľa pri aktualizácii';
$lang['delUserGroup'] = 'SQL príkaz pre vyradenie používateľa z danej skupiny';
$lang['getGroupID'] = 'SQL príkaz pre získanie primárneho kľúča skupiny';
+$lang['debug_o_0'] = 'žiadne';
+$lang['debug_o_1'] = 'iba pri chybách';
+$lang['debug_o_2'] = 'všetky SQL dopyty';
diff --git a/lib/plugins/authpgsql/lang/bg/settings.php b/lib/plugins/authpgsql/lang/bg/settings.php
index 0defdc4ff..bd6ae1cee 100644
--- a/lib/plugins/authpgsql/lang/bg/settings.php
+++ b/lib/plugins/authpgsql/lang/bg/settings.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Bulgarian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Kiril <neohidra@gmail.com>
*/
$lang['server'] = 'Вашият PostgreSQL сървър';
@@ -9,4 +10,4 @@ $lang['port'] = 'Порт за PostgreSQL сървъра';
$lang['user'] = 'PostgreSQL потребител';
$lang['password'] = 'Парола за горния потребител';
$lang['database'] = 'Име на базата от данни';
-$lang['debug'] = 'Показване на допълнителна debug информация'; \ No newline at end of file
+$lang['debug'] = 'Показване на допълнителна debug информация';
diff --git a/lib/plugins/authpgsql/lang/da/settings.php b/lib/plugins/authpgsql/lang/da/settings.php
index 76c08a734..007174815 100644
--- a/lib/plugins/authpgsql/lang/da/settings.php
+++ b/lib/plugins/authpgsql/lang/da/settings.php
@@ -4,7 +4,19 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Jens Hyllegaard <jens.hyllegaard@gmail.com>
+ * @author soer9648 <soer9648@eucl.dk>
*/
$lang['server'] = 'Din PostgresSQL server';
$lang['port'] = 'Din PostgresSQL servers port';
+$lang['password'] = 'Kodeord til ovenstående bruger';
+$lang['database'] = 'Database der skal benyttes';
$lang['debug'] = 'Vis yderligere debug output';
+$lang['checkPass'] = 'SQL-sætning til at kontrollere kodeord';
+$lang['getUsers'] = 'SQL-sætning til at liste alle brugere';
+$lang['addUser'] = 'SQL-sætning til at tilføje en ny bruger';
+$lang['addGroup'] = 'SQL-sætning til at tilføje en ny gruppe';
+$lang['addUserGroup'] = 'SQL-sætning til at tilføje en bruger til en eksisterende gruppe';
+$lang['delGroup'] = 'SQL-sætning til at fjerne en gruppe';
+$lang['delUser'] = 'SQL-sætning til at slette en bruger';
+$lang['delUserRefs'] = 'SQL-sætning til at fjerne en bruger fra alle grupper';
+$lang['updateUser'] = 'SQL-sætning til at opdatere en brugerprofil';
diff --git a/lib/plugins/authpgsql/lang/hu/settings.php b/lib/plugins/authpgsql/lang/hu/settings.php
index ff62a7016..213fc8751 100644
--- a/lib/plugins/authpgsql/lang/hu/settings.php
+++ b/lib/plugins/authpgsql/lang/hu/settings.php
@@ -4,35 +4,36 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Marton Sebok <sebokmarton@gmail.com>
+ * @author Marina Vladi <deldadam@gmail.com>
*/
-$lang['server'] = 'PostgreSQL-szerver';
-$lang['port'] = 'PostgreSQL-port';
-$lang['user'] = 'PostgreSQL felhasználónév';
-$lang['password'] = 'Ehhez a jelszó';
+$lang['server'] = 'PostgreSQL-kiszolgáló';
+$lang['port'] = 'PostgreSQL-kiszolgáló portja';
+$lang['user'] = 'PostgreSQL-felhasználónév';
+$lang['password'] = 'Fenti felhasználó jelszava';
$lang['database'] = 'Adatbázis';
-$lang['debug'] = 'Debug-üzenetek megjelenítése?';
+$lang['debug'] = 'Hibakeresési ü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';
+$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-klauzula a felhasználók név alapú szűréséhez';
+$lang['FilterEmail'] = 'SQL-klauzula a felhasználók e-mail cím alapú szűréséhez';
+$lang['FilterGroup'] = 'SQL-klauzula a felhasználók csoporttagság alapú szűréséhez';
+$lang['SortOrder'] = 'SQL-klauzula a felhasználók rendezéséhez';
+$lang['addUser'] = 'SQL-klauzula új felhasználó hozzáadásához';
+$lang['addGroup'] = 'SQL-klauzula új csoport hozzáadásához';
+$lang['addUserGroup'] = 'SQL-utasítás felhasználó meglévő csoporthoz való hozzáadásához';
+$lang['delGroup'] = 'SQL-utasítás csoport törléséhez';
+$lang['getUserID'] = 'SQL-utasítás felhasználó elsődleges kulcsának lekérdezéséhez';
+$lang['delUser'] = 'SQL-utasítás felhasználó törléséhez';
+$lang['delUserRefs'] = 'SQL-utasítás felhasználó összes csoportból való törléséhez';
+$lang['updateUser'] = 'SQL-utasítás felhasználó profiljának frissítéséhez';
+$lang['UpdateLogin'] = 'UPDATE-klauzula felhasználók azonosítójának frissítéséhez';
+$lang['UpdatePass'] = 'UPDATE-klauzula felhasználók jelszavának frissítéséhez';
+$lang['UpdateEmail'] = 'UPDATE-klauzula felhasználók e-mailcí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/ja/settings.php b/lib/plugins/authpgsql/lang/ja/settings.php
index 2ce63a34a..d7a5f6cf2 100644
--- a/lib/plugins/authpgsql/lang/ja/settings.php
+++ b/lib/plugins/authpgsql/lang/ja/settings.php
@@ -11,7 +11,7 @@ $lang['user'] = 'PostgreSQL 接続用ユーザー名';
$lang['password'] = 'PostgreSQL 接続用ユーザーのパスワード';
$lang['database'] = '使用するデータベース名';
$lang['debug'] = 'デバック情報を表示する';
-$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 %{pass} を平文とする(DokiWiki側で暗号化しない)';
+$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 &#x25;{pass} を平文とする(DokiWiki側で暗号化しない)';
$lang['checkPass'] = 'パスワードの照合に用いる SQL ステートメント';
$lang['getUserInfo'] = 'ユーザー情報の取得に用いる SQL ステートメント';
$lang['getGroups'] = 'ユーザーが所属する全てのグループの取得に用いる SQL ステートメント';
diff --git a/lib/plugins/authpgsql/lang/ko/settings.php b/lib/plugins/authpgsql/lang/ko/settings.php
index bdd8c2718..bdf38b3c7 100644
--- a/lib/plugins/authpgsql/lang/ko/settings.php
+++ b/lib/plugins/authpgsql/lang/ko/settings.php
@@ -4,6 +4,7 @@
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Myeongjin <aranet100@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['server'] = 'PostgreSQL 서버';
$lang['port'] = 'PostgreSQL 서버의 포트';
@@ -16,10 +17,10 @@ $lang['checkPass'] = '비밀번호를 확인하기 위한 SQL 문';
$lang['getUserInfo'] = '사용자 정보를 가져오기 위한 SQL 문';
$lang['getGroups'] = '사용자의 그룹 구성원을 가져오기 위한 SQL 문';
$lang['getUsers'] = '모든 사용자를 나타낼 SQL 문';
-$lang['FilterLogin'] = '로그인 이름 별로 사용자를 필터하기 위한 SQL 조항';
-$lang['FilterName'] = '전체 이름 별로 사용자를 필터하기 위한 SQL 조항';
-$lang['FilterEmail'] = '이메일 주소 별로 사용자를 필터하기 위한 SQL 조항';
-$lang['FilterGroup'] = '그룹 구성원 별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterLogin'] = '로그인 이름별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterName'] = '전체 이름별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterEmail'] = '이메일 주소별로 사용자를 필터하기 위한 SQL 조항';
+$lang['FilterGroup'] = '그룹 구성원별로 사용자를 필터하기 위한 SQL 조항';
$lang['SortOrder'] = '사용자를 정렬할 SQL 조항';
$lang['addUser'] = '새 사용자를 추가할 SQL 문';
$lang['addGroup'] = '새 그룹을 추가할 SQL 문';
diff --git a/lib/plugins/authpgsql/lang/sk/settings.php b/lib/plugins/authpgsql/lang/sk/settings.php
index 9d656415d..861d1237d 100644
--- a/lib/plugins/authpgsql/lang/sk/settings.php
+++ b/lib/plugins/authpgsql/lang/sk/settings.php
@@ -33,5 +33,6 @@ $lang['UpdateLogin'] = 'SQL podmienka pre aktualizáciu prihlasovacieh
$lang['UpdatePass'] = 'SQL podmienka pre aktualizáciu hesla používateľa';
$lang['UpdateEmail'] = 'SQL podmienka pre aktualizáciu emailovej adresy používateľa';
$lang['UpdateName'] = 'SQL podmienka pre aktualizáciu mena a priezviska používateľa';
+$lang['UpdateTarget'] = 'Podmienka identifikácie používateľa pri aktualizácii';
$lang['delUserGroup'] = 'SQL príkaz pre vyradenie používateľa z danej skupiny';
$lang['getGroupID'] = 'SQL príkaz pre získanie primárneho kľúča skupiny';
diff --git a/lib/plugins/config/lang/ko/lang.php b/lib/plugins/config/lang/ko/lang.php
index ac52090e3..0cdaca90d 100644
--- a/lib/plugins/config/lang/ko/lang.php
+++ b/lib/plugins/config/lang/ko/lang.php
@@ -71,7 +71,7 @@ $lang['deaccent'] = '문서 이름을 지우는 방법';
$lang['useheading'] = '문서 이름으로 첫 문단 제목 사용';
$lang['sneaky_index'] = '기본적으로 도쿠위키는 색인 목록에 모든 이름공간을 보여줍니다.
이 옵션을 설정하면 사용자가 읽기 권한을 가지고 있지 않은 이름공간은 보여주지 않습니다. 접근 가능한 하위 이름공간을 보이지 않게 설정하면 자동으로 설정됩니다. 특정 ACL 설정은 색인 사용이 불가능하게 할 수도 있습니다.';
-$lang['hidepages'] = '사이트맵과 기타 자동 색인과 같은 찾기에서 정규 표현식과 일치하는 문서 숨기기';
+$lang['hidepages'] = '검색, 사이트맵과 기타 자동 색인에서 정규 표현식과 일치하는 문서 숨기기';
$lang['useacl'] = '접근 제어 목록 (ACL) 사용';
$lang['autopasswd'] = '자동으로 만들어진 비밀번호';
$lang['authtype'] = '인증 백-엔드';
@@ -137,7 +137,7 @@ $lang['gzip_output'] = 'xhml 내용 gzip 압축 사용';
$lang['compress'] = '최적화된 CSS, 자바스크립트 출력';
$lang['cssdatauri'] = '그림이 렌더링될 최대 용량 크기를 CSS에 규정해야 HTTP 요청 헤더 오버헤드 크기를 감소시킬 수 있습니다. 이 기술은 IE 7 이하에서는 작동하지 않습니다! <code>400</code>에서 <code>600</code> 정도면 좋은 효율을 가져옵니다. <code>0</code>로 지정할 경우 비활성화 됩니다.';
$lang['send404'] = '존재하지 않는 페이지에 대해 "HTTP 404/페이지를 찾을 수 없습니다" 응답';
-$lang['broken_iua'] = '설치된 시스템에서 ignore_user_abort 기능에 문제가 있습니까? 문제가 있다면 색인이 정상적으로 동작하지 않습니다. 이 기능이 IIS+PHP/CGI에서 문제가 있는 것으로 알려졌습니다. 자세한 정보는 <a href="http://bugs.dokuwiki.org/?do=details&amp;task_id=852">버그 852</a>를 참고하시기 바랍니다.';
+$lang['broken_iua'] = '설치된 시스템에서 ignore_user_abort 기능에 문제가 있습니까? 문제가 있다면 검색 색인이 정상적으로 동작하지 않습니다. 이 기능이 IIS+PHP/CGI에서 문제가 있는 것으로 알려졌습니다. 자세한 정보는 <a href="http://bugs.dokuwiki.org/?do=details&amp;task_id=852">버그 852</a>를 참고하시기 바랍니다.';
$lang['xsendfile'] = '웹 서버가 정적 파일을 제공하도록 X-Sendfile 헤더를 사용하겠습니까? 웹 서버가 이 기능을 지원해야 합니다.';
$lang['renderer_xhtml'] = '주 (xhtml) 위키 출력 처리기';
$lang['renderer__core'] = '%s (도쿠위키 내부)';
diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php
index a5a11cda1..05f8470f7 100644
--- a/lib/plugins/config/settings/config.class.php
+++ b/lib/plugins/config/settings/config.class.php
@@ -330,8 +330,7 @@ if (!class_exists('configuration')) {
foreach ($this->get_plugin_list() as $plugin) {
$plugin_dir = plugin_directory($plugin);
if (@file_exists(DOKU_PLUGIN.$plugin_dir.$file)){
- $conf = array();
- @include(DOKU_PLUGIN.$plugin_dir.$file);
+ $conf = $this->_read_config(DOKU_PLUGIN.$plugin_dir.$file);
foreach ($conf as $key => $value){
$default['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.$key] = $value;
}
@@ -340,8 +339,7 @@ if (!class_exists('configuration')) {
// the same for the active template
if (@file_exists(tpl_incdir().$file)){
- $conf = array();
- @include(tpl_incdir().$file);
+ $conf = $this->_read_config(tpl_incdir().$file);
foreach ($conf as $key => $value){
$default['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.$key] = $value;
}
diff --git a/lib/plugins/plugin/classes/ap_download.class.php b/lib/plugins/plugin/classes/ap_download.class.php
index 3cc455867..b1be11506 100644
--- a/lib/plugins/plugin/classes/ap_download.class.php
+++ b/lib/plugins/plugin/classes/ap_download.class.php
@@ -24,7 +24,7 @@ class ap_download extends ap_manage {
ptln('<h2>'.$this->lang['downloading'].'</h2>');
if ($this->manager->error) {
- ptln('<div class="error">'.str_replace("\n","<br />",$this->manager->error).'</div>');
+ ptln('<div class="error">'.str_replace("\n","<br />",hsc($this->manager->error)).'</div>');
} else if (count($this->downloaded) == 1) {
ptln('<p>'.sprintf($this->lang['downloaded'],$this->downloaded[0]).'</p>');
} else if (count($this->downloaded)) { // more than one plugin in the download
diff --git a/lib/plugins/plugin/lang/bg/lang.php b/lib/plugins/plugin/lang/bg/lang.php
index 09ac35229..0e6a4cd28 100644
--- a/lib/plugins/plugin/lang/bg/lang.php
+++ b/lib/plugins/plugin/lang/bg/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * bulgarian language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Nikolay Vladimirov <nikolay@vladimiroff.com>
* @author Viktor Usunov <usun0v@mail.bg>
* @author Kiril <neohidra@gmail.com>
diff --git a/lib/plugins/plugin/lang/fi/lang.php b/lib/plugins/plugin/lang/fi/lang.php
index 923029a6f..f51746faa 100644
--- a/lib/plugins/plugin/lang/fi/lang.php
+++ b/lib/plugins/plugin/lang/fi/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author otto@valjakko.net
* @author Otto Vainio <otto@valjakko.net>
* @author Teemu Mattila <ghcsystems@gmail.com>
diff --git a/lib/plugins/plugin/lang/hu/admin_plugin.txt b/lib/plugins/plugin/lang/hu/admin_plugin.txt
index afa08d349..cf4a3b316 100644
--- a/lib/plugins/plugin/lang/hu/admin_plugin.txt
+++ b/lib/plugins/plugin/lang/hu/admin_plugin.txt
@@ -1,4 +1,4 @@
====== Bővítménykezelő ======
-Ezen az oldalon a Dokuwiki [[doku>plugins|bővítményeivel]] kapcsolatos teendőket láthatod el. A webszervernek tudni kell írnia a //plugin// könyvtárat, hogy új bővítményeket tudj ezen a felületen keresztül letölteni és telepíteni.
+Ezen az oldalon a Dokuwiki [[doku>plugins|bővítményeivel]] kapcsolatos teendőket láthatod el. A webkiszolgálónak tudnia kell írni a //plugin// könyvtárba az új bővítmények letöltéséhez és telepítéséhez.
diff --git a/lib/plugins/plugin/lang/hu/lang.php b/lib/plugins/plugin/lang/hu/lang.php
index b8fa2cdbe..7fb237a32 100644
--- a/lib/plugins/plugin/lang/hu/lang.php
+++ b/lib/plugins/plugin/lang/hu/lang.php
@@ -10,6 +10,7 @@
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
* @author Marton Sebok <sebokmarton@gmail.com>
+ * @author Marina Vladi <deldadam@gmail.com>
*/
$lang['menu'] = 'Bővítménykezelő';
$lang['download'] = 'Új bővítmény letöltése és telepítése';
@@ -20,19 +21,19 @@ $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'] = 'Cím';
+$lang['url'] = '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 frissítése sikeres';
+$lang['updated'] = 'A(z) %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ítva.';
+$lang['deleted'] = 'A(z) %s bővítményt eltávolítva.';
$lang['downloading'] = 'Letöltés...';
-$lang['downloaded'] = 'A %s bővítmény telepítése sikeres.';
+$lang['downloaded'] = 'A(z) %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:';
diff --git a/lib/plugins/plugin/lang/id/lang.php b/lib/plugins/plugin/lang/id/lang.php
index f3a1fe4e6..2653b075e 100644
--- a/lib/plugins/plugin/lang/id/lang.php
+++ b/lib/plugins/plugin/lang/id/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Indonesian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Irwan Butar Butar <irwansah.putra@gmail.com>
* @author Yustinus Waruwu <juswaruwu@gmail.com>
*/
diff --git a/lib/plugins/plugin/lang/ko/lang.php b/lib/plugins/plugin/lang/ko/lang.php
index 6ef9cd69a..4cd1ae3c7 100644
--- a/lib/plugins/plugin/lang/ko/lang.php
+++ b/lib/plugins/plugin/lang/ko/lang.php
@@ -9,6 +9,7 @@
* @author Seung-Chul Yoo <dryoo@live.com>
* @author erial2@gmail.com
* @author Myeongjin <aranet100@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['menu'] = '플러그인 관리';
$lang['download'] = '새 플러그인을 다운로드하고 설치';
diff --git a/lib/plugins/plugin/lang/no/lang.php b/lib/plugins/plugin/lang/no/lang.php
index 829d29387..2b890f972 100644
--- a/lib/plugins/plugin/lang/no/lang.php
+++ b/lib/plugins/plugin/lang/no/lang.php
@@ -1,13 +1,14 @@
<?php
+
/**
- * Norwegianlanguage file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Thomas Nygreen <nygreen@gmail.com>
* @author Arild Burud <arildb@met.no>
* @author Torkill Bruland <torkar-b@online.no>
* @author Rune M. Andersen <rune.andersen@gmail.com>
* @author Jakob Vad Nielsen (me@jakobnielsen.net)
- * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
+ * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
* @author Knut Staring <knutst@gmail.com>
* @author Lisa Ditlefsen <lisa@vervesearch.com>
* @author Erik Pedersen <erik.pedersen@shaw.ca>
diff --git a/lib/plugins/plugin/lang/pl/lang.php b/lib/plugins/plugin/lang/pl/lang.php
index faaa69630..eae91f33e 100644
--- a/lib/plugins/plugin/lang/pl/lang.php
+++ b/lib/plugins/plugin/lang/pl/lang.php
@@ -1,8 +1,8 @@
<?php
+
/**
- * polish language file
- *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Michał Tkacz <mehow@autocom.pl>
* @author Grzegorz Żur <grzegorz.zur@gmail.com>
* @author Mariusz Kujawski <marinespl@gmail.com>
diff --git a/lib/plugins/plugin/lang/zh/lang.php b/lib/plugins/plugin/lang/zh/lang.php
index f69410503..b39c6b063 100644
--- a/lib/plugins/plugin/lang/zh/lang.php
+++ b/lib/plugins/plugin/lang/zh/lang.php
@@ -15,6 +15,7 @@
* @author caii, patent agent in China <zhoucaiqi@gmail.com>
* @author lainme993@gmail.com
* @author Shuo-Ting Jian <shoting@gmail.com>
+ * @author anjianshi <anjianshi@gmail.com>
*/
$lang['menu'] = '插件管理器';
$lang['download'] = '下载并安装新的插件';
@@ -26,7 +27,7 @@ $lang['btn_settings'] = '设置';
$lang['btn_download'] = '下载';
$lang['btn_enable'] = '保存';
$lang['url'] = 'URL';
-$lang['installed'] = '已安装:';
+$lang['installed'] = '安装时间:';
$lang['lastupdate'] = '最后更新于:';
$lang['source'] = '来源:';
$lang['unknown'] = '未知';
diff --git a/lib/plugins/popularity/lang/bg/lang.php b/lib/plugins/popularity/lang/bg/lang.php
index ba731c0fc..963b50e84 100644
--- a/lib/plugins/popularity/lang/bg/lang.php
+++ b/lib/plugins/popularity/lang/bg/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Bulgarian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Viktor Usunov <usun0v@mail.bg>
* @author Kiril <neohidra@gmail.com>
*/
diff --git a/lib/plugins/popularity/lang/fi/lang.php b/lib/plugins/popularity/lang/fi/lang.php
index d7c230742..ec0fc4071 100644
--- a/lib/plugins/popularity/lang/fi/lang.php
+++ b/lib/plugins/popularity/lang/fi/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Otto Vainio <otto@valjakko.net>
* @author Teemu Mattila <ghcsystems@gmail.com>
* @author Sami Olmari <sami@olmari.fi>
diff --git a/lib/plugins/popularity/lang/ko/lang.php b/lib/plugins/popularity/lang/ko/lang.php
index f52e0007a..f8cf4525d 100644
--- a/lib/plugins/popularity/lang/ko/lang.php
+++ b/lib/plugins/popularity/lang/ko/lang.php
@@ -9,6 +9,7 @@
* @author Seung-Chul Yoo <dryoo@live.com>
* @author erial2@gmail.com
* @author Myeongjin <aranet100@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['name'] = '인기도 조사 (불러오는 데 시간이 걸릴 수 있습니다)';
$lang['submit'] = '자료 보내기';
diff --git a/lib/plugins/popularity/lang/no/lang.php b/lib/plugins/popularity/lang/no/lang.php
index df38f6e0e..dfa99d824 100644
--- a/lib/plugins/popularity/lang/no/lang.php
+++ b/lib/plugins/popularity/lang/no/lang.php
@@ -1,10 +1,11 @@
<?php
+
/**
- * Norwegian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Rune M. Andersen <rune.andersen@gmail.com>
* @author Jakob Vad Nielsen (me@jakobnielsen.net)
- * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
+ * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
* @author Knut Staring <knutst@gmail.com>
* @author Lisa Ditlefsen <lisa@vervesearch.com>
* @author Erik Pedersen <erik.pedersen@shaw.ca>
diff --git a/lib/plugins/popularity/lang/pl/lang.php b/lib/plugins/popularity/lang/pl/lang.php
index 76a9464bd..045574a69 100644
--- a/lib/plugins/popularity/lang/pl/lang.php
+++ b/lib/plugins/popularity/lang/pl/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Polish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Grzegorz Żur <grzegorz.zur@gmail.com>
* @author Mariusz Kujawski <marinespl@gmail.com>
* @author Maciej Kurczewski <pipijajko@gmail.com>
diff --git a/lib/plugins/revert/lang/ar/lang.php b/lib/plugins/revert/lang/ar/lang.php
index 27de54f16..71f411c52 100644
--- a/lib/plugins/revert/lang/ar/lang.php
+++ b/lib/plugins/revert/lang/ar/lang.php
@@ -7,6 +7,7 @@
* @author Usama Akkad <uahello@gmail.com>
* @author uahello@gmail.com
* @author Ahmad Abd-Elghany <tolpa1@gmail.com>
+ * @author alhajr <alhajr300@gmail.com>
*/
$lang['menu'] = 'مدير الاسترجاع';
$lang['filter'] = 'ابحث في الصفحات المتأذاة';
diff --git a/lib/plugins/revert/lang/bg/lang.php b/lib/plugins/revert/lang/bg/lang.php
index 0819de01a..5062a12ad 100644
--- a/lib/plugins/revert/lang/bg/lang.php
+++ b/lib/plugins/revert/lang/bg/lang.php
@@ -1,6 +1,8 @@
<?php
+
/**
- * bulgarian language file
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Nikolay Vladimirov <nikolay@vladimiroff.com>
* @author Viktor Usunov <usun0v@mail.bg>
* @author Kiril <neohidra@gmail.com>
diff --git a/lib/plugins/revert/lang/fi/lang.php b/lib/plugins/revert/lang/fi/lang.php
index fdf9bb81c..d14f527f9 100644
--- a/lib/plugins/revert/lang/fi/lang.php
+++ b/lib/plugins/revert/lang/fi/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author otto@valjakko.net
* @author Otto Vainio <otto@valjakko.net>
* @author Teemu Mattila <ghcsystems@gmail.com>
diff --git a/lib/plugins/revert/lang/hu/lang.php b/lib/plugins/revert/lang/hu/lang.php
index d16764a35..278af1864 100644
--- a/lib/plugins/revert/lang/hu/lang.php
+++ b/lib/plugins/revert/lang/hu/lang.php
@@ -10,9 +10,10 @@
* @author Sándor TIHANYI <stihanyi+dw@gmail.com>
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
* @author Marton Sebok <sebokmarton@gmail.com>
+ * @author Marina Vladi <deldadam@gmail.com>
*/
-$lang['menu'] = 'Visszaállítás kezelő (anti-SPAM)';
-$lang['filter'] = 'SPAM tartalmú oldalak keresése';
+$lang['menu'] = 'Visszaállítás-kezelő (anti-SPAM)';
+$lang['filter'] = 'SPAM-tartalmú oldalak keresése';
$lang['revert'] = 'Kiválasztott oldalak visszaállítása';
$lang['reverted'] = '%s a következő változatra lett visszaállítva: %s';
$lang['removed'] = '%s törölve';
diff --git a/lib/plugins/revert/lang/ko/intro.txt b/lib/plugins/revert/lang/ko/intro.txt
index 7aa618ba6..565aa4bbe 100644
--- a/lib/plugins/revert/lang/ko/intro.txt
+++ b/lib/plugins/revert/lang/ko/intro.txt
@@ -1,3 +1,3 @@
====== 되돌리기 관리자 ======
-스팸 공격으로부터 자동으로 되돌리는데 이 페이지가 도움이 될 수 있습니다. 스팸 공격받은 문서 목록을 찾으려면 문자열을 입력하고(예를 들어 스팸 URL) 나서 찾은 문서가 스팸 공격을 받았는지 확인하고 되돌리세요. \ No newline at end of file
+스팸 공격으로부터 자동으로 되돌리는데 이 페이지가 도움이 될 수 있습니다. 스팸에 공격 받은 문서 목록을 찾으려면 검색어를 입력하고(예를 들어 스팸 URL) 나서 찾은 문서가 스팸 공격을 받았는지 확인하고 되돌리세요. \ No newline at end of file
diff --git a/lib/plugins/revert/lang/ko/lang.php b/lib/plugins/revert/lang/ko/lang.php
index e63706960..5666100e9 100644
--- a/lib/plugins/revert/lang/ko/lang.php
+++ b/lib/plugins/revert/lang/ko/lang.php
@@ -11,7 +11,7 @@
* @author Myeongjin <aranet100@gmail.com>
*/
$lang['menu'] = '되돌리기 관리자';
-$lang['filter'] = '스팸 문서 찾기';
+$lang['filter'] = '스팸 문서 검색';
$lang['revert'] = '선택한 문서 되돌리기';
$lang['reverted'] = '%s 판을 %s 판으로 되돌림';
$lang['removed'] = '%s 제거됨';
diff --git a/lib/plugins/revert/lang/no/lang.php b/lib/plugins/revert/lang/no/lang.php
index 299b12ea7..c58300dc0 100644
--- a/lib/plugins/revert/lang/no/lang.php
+++ b/lib/plugins/revert/lang/no/lang.php
@@ -1,13 +1,14 @@
<?php
+
/**
- * Norwegianlanguage file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Thomas Nygreen <nygreen@gmail.com>
* @author Arild Burud <arildb@met.no>
* @author Torkill Bruland <torkar-b@online.no>
* @author Rune M. Andersen <rune.andersen@gmail.com>
* @author Jakob Vad Nielsen (me@jakobnielsen.net)
- * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
+ * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
* @author Knut Staring <knutst@gmail.com>
* @author Lisa Ditlefsen <lisa@vervesearch.com>
* @author Erik Pedersen <erik.pedersen@shaw.ca>
@@ -15,6 +16,8 @@
* @author Rune Rasmussen syntaxerror.no@gmail.com
* @author Jon Bøe <jonmagneboe@hotmail.com>
* @author Egil Hansen <egil@rosetta.no>
+ * @author Thomas Juberg <Thomas.Juberg@Gmail.com>
+ * @author Boris <boris@newton-media.no>
*/
$lang['menu'] = 'Tilbakestillingsbehandler';
$lang['filter'] = 'Søk etter søppelmeldinger';
diff --git a/lib/plugins/revert/lang/pl/lang.php b/lib/plugins/revert/lang/pl/lang.php
index 462841292..d2d53b87e 100644
--- a/lib/plugins/revert/lang/pl/lang.php
+++ b/lib/plugins/revert/lang/pl/lang.php
@@ -1,6 +1,8 @@
<?php
+
/**
- * polish language file
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Grzegorz Żur <grzegorz.zur@gmail.com>
* @author Mariusz Kujawski <marinespl@gmail.com>
* @author Maciej Kurczewski <pipijajko@gmail.com>
diff --git a/lib/plugins/revert/lang/sv/lang.php b/lib/plugins/revert/lang/sv/lang.php
index c30f82d93..e605a17d4 100644
--- a/lib/plugins/revert/lang/sv/lang.php
+++ b/lib/plugins/revert/lang/sv/lang.php
@@ -18,6 +18,7 @@
* @author Smorkster Andersson smorkster@gmail.com
* @author Henrik <henrik@idealis.se>
* @author Tor Härnqvist <tor.harnqvist@gmail.com>
+ * @author Hans Iwan Bratt <hibratt@gmail.com>
*/
$lang['menu'] = 'Hantera återställningar';
$lang['filter'] = 'Sök efter spamsidor';
diff --git a/lib/plugins/usermanager/_test/csv_export.test.php b/lib/plugins/usermanager/_test/csv_export.test.php
new file mode 100644
index 000000000..667fc71dc
--- /dev/null
+++ b/lib/plugins/usermanager/_test/csv_export.test.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @group plugin_usermanager
+ * @group admin_plugins
+ * @group plugins
+ * @group bundled_plugins
+ */
+require_once(dirname(__FILE__).'/mocks.class.php');
+
+class plugin_usermanager_csv_export_test extends DokuWikiTest {
+
+ protected $usermanager;
+
+ function setUp() {
+ $this->usermanager = new admin_mock_usermanager();
+ parent::setUp();
+ }
+
+ /**
+ * based on standard test user/conf setup
+ *
+ * users per _test/conf/users.auth.php
+ * expected to be: testuser:179ad45c6ce2cb97cf1029e212046e81:Arthur Dent:arthur@example.com
+ */
+ function test_export() {
+ $expected = 'User,"Real Name",Email,Groups
+testuser,"Arthur Dent",arthur@example.com,
+';
+ $this->assertEquals($expected, $this->usermanager->tryExport());
+ }
+
+ /**
+ * when configured to use a different locale, the column headings in the first line of the
+ * exported csv data should reflect the langauge strings of that locale
+ */
+ function test_export_withlocale(){
+ global $conf;
+ $old_conf = $conf;
+ $conf['lang'] = 'de';
+
+ $this->usermanager->localised = false;
+ $this->usermanager->setupLocale();
+
+ $conf = $old_conf;
+
+ $expected = 'Benutzername,"Voller Name",E-Mail,Gruppen
+testuser,"Arthur Dent",arthur@example.com,
+';
+ $this->assertEquals($expected, $this->usermanager->tryExport());
+ }
+/*
+ function test_export_withfilter(){
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+*/
+}
diff --git a/lib/plugins/usermanager/_test/csv_import.test.php b/lib/plugins/usermanager/_test/csv_import.test.php
new file mode 100644
index 000000000..3968356bc
--- /dev/null
+++ b/lib/plugins/usermanager/_test/csv_import.test.php
@@ -0,0 +1,185 @@
+<?php
+
+/**
+ * @group plugin_usermanager
+ * @group admin_plugins
+ * @group plugins
+ * @group bundled_plugins
+ */
+
+require_once(dirname(__FILE__).'/mocks.class.php');
+
+/**
+ * !!!!! NOTE !!!!!
+ *
+ * At present, users imported in individual tests remain in the user list for subsequent tests
+ */
+class plugin_usermanager_csv_import_test extends DokuWikiTest {
+
+ private $old_files;
+ protected $usermanager;
+ protected $importfile;
+
+ function setUp() {
+ $this->importfile = tempnam(TMP_DIR, 'csv');
+
+ $this->old_files = $_FILES;
+ $_FILES = array(
+ 'import' => array(
+ 'name' => 'import.csv',
+ 'tmp_name' => $this->importfile,
+ 'type' => 'text/plain',
+ 'size' => 1,
+ 'error' => 0,
+ ),
+ );
+
+ $this->usermanager = new admin_mock_usermanager();
+ parent::setUp();
+ }
+
+ function tearDown() {
+ $_FILES = $this->old_files;
+ parent::tearDown();
+ }
+
+ function doImportTest($importCsv, $expectedResult, $expectedNewUsers, $expectedFailures) {
+ global $auth;
+ $before_users = $auth->retrieveUsers();
+
+ io_savefile($this->importfile, $importCsv);
+ $result = $this->usermanager->tryImport();
+
+ $after_users = $auth->retrieveUsers();
+ $import_count = count($after_users) - count($before_users);
+ $new_users = array_diff_key($after_users, $before_users);
+ $diff_users = array_diff_assoc($after_users, $before_users);
+
+ $expectedCount = count($expectedNewUsers);
+
+ $this->assertEquals($expectedResult, $result); // import result as expected
+ $this->assertEquals($expectedCount, $import_count); // number of new users matches expected number imported
+ $this->assertEquals($expectedNewUsers, $this->stripPasswords($new_users)); // new user data matches imported user data
+ $this->assertEquals($expectedCount, $this->countPasswords($new_users)); // new users have a password
+ $this->assertEquals($expectedCount, $this->usermanager->mock_email_notifications_sent); // new users notified of their passwords
+ $this->assertEquals($new_users, $diff_users); // no other users were harmed in the testing of this import
+ $this->assertEquals($expectedFailures, $this->usermanager->getImportFailures()); // failures as expected
+ }
+
+ function test_cantImport(){
+ global $auth;
+ $oldauth = $auth;
+
+ $auth = new auth_mock_authplain();
+ $auth->setCanDo('addUser', false);
+
+ $csv = 'User,"Real Name",Email,Groups
+importuser,"Ford Prefect",ford@example.com,user
+';
+
+ $this->doImportTest($csv, false, array(), array());
+
+ $auth = $oldauth;
+ }
+
+ function test_import() {
+ $csv = 'User,"Real Name",Email,Groups
+importuser,"Ford Prefect",ford@example.com,user
+';
+ $expected = array(
+ 'importuser' => array(
+ 'name' => 'Ford Prefect',
+ 'mail' => 'ford@example.com',
+ 'grps' => array('user'),
+ ),
+ );
+
+ $this->doImportTest($csv, true, $expected, array());
+ }
+
+ function test_importExisting() {
+ $csv = 'User,"Real Name",Email,Groups
+importuser,"Ford Prefect",ford@example.com,user
+';
+ $failures = array(
+ '2' => array(
+ 'error' => $this->usermanager->lang['import_error_create'],
+ 'user' => array(
+ 'importuser',
+ 'Ford Prefect',
+ 'ford@example.com',
+ 'user',
+ ),
+ 'orig' => 'importuser,"Ford Prefect",ford@example.com,user'.NL,
+ ),
+ );
+
+ $this->doImportTest($csv, true, array(), $failures);
+ }
+
+ function test_importUtf8() {
+ $csv = 'User,"Real Name",Email,Groups
+importutf8,"Førd Prefect",ford@example.com,user
+';
+ $expected = array(
+ 'importutf8' => array(
+ 'name' => 'Førd Prefect',
+ 'mail' => 'ford@example.com',
+ 'grps' => array('user'),
+ ),
+ );
+
+ $this->doImportTest($csv, true, $expected, array());
+ }
+
+ /**
+ * utf8: u+00F8 (ø) <=> 0xF8 :iso-8859-1
+ */
+ function test_importIso8859() {
+ $csv = 'User,"Real Name",Email,Groups
+importiso8859,"F'.chr(0xF8).'rd Prefect",ford@example.com,user
+';
+ $expected = array(
+ 'importiso8859' => array(
+ 'name' => 'Førd Prefect',
+ 'mail' => 'ford@example.com',
+ 'grps' => array('user'),
+ ),
+ );
+
+ $this->doImportTest($csv, true, $expected, array());
+ }
+
+ /**
+ * Verify usermanager::str_getcsv() behaves identically to php 5.3's str_getcsv()
+ * within the context/parameters required by _import()
+ *
+ * @requires PHP 5.3
+ * @deprecated remove when dokuwiki requires 5.3+
+ * also associated usermanager & mock usermanager access methods
+ */
+ function test_getcsvcompatibility() {
+ $line = 'importuser,"Ford Prefect",ford@example.com,user'.NL;
+
+ $this->assertEquals(str_getcsv($line), $this->usermanager->access_str_getcsv($line));
+ }
+
+ private function stripPasswords($array){
+ foreach ($array as $user => $data) {
+ unset($array[$user]['pass']);
+ }
+ return $array;
+ }
+
+ private function countPasswords($array){
+ $count = 0;
+ foreach ($array as $user => $data) {
+ if (!empty($data['pass'])) {
+ $count++;
+ }
+ }
+ return $count;
+ }
+
+}
+
diff --git a/lib/plugins/usermanager/_test/mocks.class.php b/lib/plugins/usermanager/_test/mocks.class.php
new file mode 100644
index 000000000..91c74768c
--- /dev/null
+++ b/lib/plugins/usermanager/_test/mocks.class.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * test wrapper to allow access to private/protected functions/properties
+ *
+ * NB: for plugin introspection methods, getPluginType() & getPluginName() to work
+ * this class name needs to start "admin_" and end "_usermanager". Internally
+ * these methods are used in setting up the class, e.g. for language strings
+ */
+class admin_mock_usermanager extends admin_plugin_usermanager {
+
+ public $mock_email_notifications = true;
+ public $mock_email_notifications_sent = 0;
+
+ public function getImportFailures() {
+ return $this->_import_failures;
+ }
+
+ public function tryExport() {
+ ob_start();
+ $this->_export();
+ return ob_get_clean();
+ }
+
+ public function tryImport() {
+ return $this->_import();
+ }
+
+ /**
+ * @deprecated remove when dokuwiki requires php 5.3+
+ * also associated unit test & usermanager methods
+ */
+ public function access_str_getcsv($line){
+ return $this->str_getcsv($line);
+ }
+
+ // no need to send email notifications (mostly)
+ protected function _notifyUser($user, $password, $status_alert=true) {
+ if ($this->mock_email_notifications) {
+ $this->mock_email_notifications_sent++;
+ return true;
+ } else {
+ return parent::_notifyUser($user, $password, $status_alert);
+ }
+ }
+
+ protected function _isUploadedFile($file) {
+ return file_exists($file);
+ }
+}
+
+class auth_mock_authplain extends auth_plugin_authplain {
+
+ public function setCanDo($op, $canDo) {
+ $this->cando[$op] = $canDo;
+ }
+
+}
diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php
index c4d71cb22..156037f09 100644
--- a/lib/plugins/usermanager/admin.php
+++ b/lib/plugins/usermanager/admin.php
@@ -814,6 +814,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
fputcsv($fd, $line);
}
fclose($fd);
+ if (defined('DOKU_UNITTEST')){ return; }
+
die;
}
@@ -822,7 +824,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
*
* csv file should have 4 columns, user_id, full name, email, groups (comma separated)
*
- * @return bool whether succesful
+ * @return bool whether successful
*/
protected function _import() {
// check we are allowed to add users
@@ -830,7 +832,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
if (!$this->_auth->canDo('addUser')) return false;
// check file uploaded ok.
- if (empty($_FILES['import']['size']) || !empty($FILES['import']['error']) && is_uploaded_file($FILES['import']['tmp_name'])) {
+ if (empty($_FILES['import']['size']) || !empty($_FILES['import']['error']) && $this->_isUploadedFile($_FILES['import']['tmp_name'])) {
msg($this->lang['import_error_upload'],-1);
return false;
}
@@ -845,7 +847,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
if (!utf8_check($csv)) {
$csv = utf8_encode($csv);
}
- $raw = str_getcsv($csv);
+ $raw = $this->_getcsv($csv);
$error = ''; // clean out any errors from the previous line
// data checks...
if (1 == ++$line) {
@@ -867,6 +869,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
$import_success_count++;
} else {
$import_fail_count++;
+ array_splice($raw, 1, 1); // remove the spliced in password
$this->_import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv);
}
}
@@ -940,7 +943,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
*
* @param array $user data of user
* @param string &$error reference catched error message
- * @return bool whether succesful
+ * @return bool whether successful
*/
protected function _addImportUser($user, & $error){
if (!$this->_auth->triggerUserMod('create', $user)) {
@@ -973,4 +976,37 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
die;
}
+ /**
+ * wrapper for is_uploaded_file to facilitate overriding by test suite
+ */
+ protected function _isUploadedFile($file) {
+ return is_uploaded_file($file);
+ }
+
+ /**
+ * wrapper for str_getcsv() to simplify maintaining compatibility with php 5.2
+ *
+ * @deprecated remove when dokuwiki php requirement increases to 5.3+
+ * also associated unit test & mock access method
+ */
+ protected function _getcsv($csv) {
+ return function_exists('str_getcsv') ? str_getcsv($csv) : $this->str_getcsv($csv);
+ }
+
+ /**
+ * replacement str_getcsv() function for php < 5.3
+ * loosely based on www.php.net/str_getcsv#88311
+ *
+ * @deprecated remove when dokuwiki php requirement increases to 5.3+
+ */
+ protected function str_getcsv($str) {
+ $fp = fopen("php://temp/maxmemory:1048576", 'r+'); // 1MiB
+ fputs($fp, $str);
+ rewind($fp);
+
+ $data = fgetcsv($fp);
+
+ fclose($fp);
+ return $data;
+ }
}
diff --git a/lib/plugins/usermanager/lang/bg/lang.php b/lib/plugins/usermanager/lang/bg/lang.php
index 9ed27f42a..9700385f8 100644
--- a/lib/plugins/usermanager/lang/bg/lang.php
+++ b/lib/plugins/usermanager/lang/bg/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * bulgarian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Nikolay Vladimirov <nikolay@vladimiroff.com>
* @author Viktor Usunov <usun0v@mail.bg>
* @author Kiril <neohidra@gmail.com>
diff --git a/lib/plugins/usermanager/lang/da/lang.php b/lib/plugins/usermanager/lang/da/lang.php
index 6b615b51d..47d7efea2 100644
--- a/lib/plugins/usermanager/lang/da/lang.php
+++ b/lib/plugins/usermanager/lang/da/lang.php
@@ -12,6 +12,7 @@
* @author rasmus@kinnerup.com
* @author Michael Pedersen subben@gmail.com
* @author Mikael Lyngvig <mikael@lyngvig.org>
+ * @author soer9648 <soer9648@eucl.dk>
*/
$lang['menu'] = 'Brugerstyring';
$lang['noauth'] = '(Brugervalidering er ikke tilgængelig)';
@@ -34,6 +35,11 @@ $lang['search'] = 'Søg';
$lang['search_prompt'] = 'Udfør søgning';
$lang['clear'] = 'Nulstil søgefilter';
$lang['filter'] = 'Filter';
+$lang['export_all'] = 'Eksportér Alle Brugere (CSV)';
+$lang['export_filtered'] = 'Eksportér Filtrerede Brugerliste (CSV)';
+$lang['import'] = 'Importér Nye Brugere';
+$lang['line'] = 'Linje nr.';
+$lang['error'] = 'Fejlmeddelelse';
$lang['summary'] = 'Viser brugerne %1$d-%2$d ud af %3$d fundne. %4$d brugere totalt.';
$lang['nonefound'] = 'Ingen brugere fundet. %d brugere totalt.';
$lang['delete_ok'] = '%d brugere slettet';
@@ -54,3 +60,15 @@ $lang['add_ok'] = 'Bruger tilføjet uden fejl.';
$lang['add_fail'] = 'Tilføjelse af bruger mislykkedes';
$lang['notify_ok'] = 'Meddelelse sendt';
$lang['notify_fail'] = 'Meddelelse kunne ikke sendes';
+$lang['import_userlistcsv'] = 'Brugerlistefil (CSV):';
+$lang['import_header'] = 'Nyeste Import - Fejl';
+$lang['import_success_count'] = 'Bruger-Import: %d brugere fundet, %d importeret med succes.';
+$lang['import_failure_count'] = 'Bruger-Import: %d fejlet. Fejl er listet nedenfor.';
+$lang['import_error_fields'] = 'Utilstrækkelige felter, fandt %d, påkrævet 4.';
+$lang['import_error_baduserid'] = 'Bruger-id mangler';
+$lang['import_error_badname'] = 'Ugyldigt navn';
+$lang['import_error_badmail'] = 'Ugyldig email-adresse';
+$lang['import_error_upload'] = 'Import Fejlet. CSV-filen kunne ikke uploades eller er tom.';
+$lang['import_error_readfail'] = 'Import Fejlet. Ikke muligt at læse uploadede fil.';
+$lang['import_error_create'] = 'Ikke muligt at oprette brugeren';
+$lang['import_notify_fail'] = 'Notifikationsmeddelelse kunne ikke sendes for importerede bruger %s, med emailen %s.';
diff --git a/lib/plugins/usermanager/lang/de/lang.php b/lib/plugins/usermanager/lang/de/lang.php
index 21be74f71..4b297b0dc 100644
--- a/lib/plugins/usermanager/lang/de/lang.php
+++ b/lib/plugins/usermanager/lang/de/lang.php
@@ -20,6 +20,8 @@
* @author Matthias Schulte <dokuwiki@lupo49.de>
* @author Sven <Svenluecke48@gmx.d>
* @author christian studer <cstuder@existenz.ch>
+ * @author Ben Fey <benedikt.fey@beck-heun.de>
+ * @author Jonas Gröger <jonas.groeger@gmail.com>
*/
$lang['menu'] = 'Benutzerverwaltung';
$lang['noauth'] = '(Authentifizierungssystem nicht verfügbar)';
@@ -67,6 +69,8 @@ $lang['add_ok'] = 'Nutzer erfolgreich angelegt';
$lang['add_fail'] = 'Nutzer konnte nicht angelegt werden';
$lang['notify_ok'] = 'Benachrichtigungsmail wurde versandt';
$lang['notify_fail'] = 'Benachrichtigungsmail konnte nicht versandt werden';
+$lang['import_userlistcsv'] = 'Benutzerliste (CSV-Datei):';
+$lang['import_header'] = 'Letzte Fehler bei Import';
$lang['import_success_count'] = 'User-Import: %d User gefunden, %d erfolgreich importiert.';
$lang['import_failure_count'] = 'User-Import: %d fehlgeschlagen. Fehlgeschlagene User sind nachfolgend aufgelistet.';
$lang['import_error_fields'] = 'Unzureichende Anzahl an Feldern: %d gefunden, benötigt sind 4.';
@@ -77,3 +81,4 @@ $lang['import_error_upload'] = 'Import fehlgeschlagen. Die CSV-Datei konnte ni
$lang['import_error_readfail'] = 'Import fehlgeschlagen. Die hochgeladene Datei konnte nicht gelesen werden.';
$lang['import_error_create'] = 'User konnte nicht angelegt werden';
$lang['import_notify_fail'] = 'Notifikation konnte nicht an den importierten Benutzer %s (E-Mail: %s) gesendet werden.';
+$lang['import_downloadfailures'] = 'Fehler als CSV-Datei zur Korrektur herunterladen';
diff --git a/lib/plugins/usermanager/lang/fi/lang.php b/lib/plugins/usermanager/lang/fi/lang.php
index 1db4bd7fb..de243133a 100644
--- a/lib/plugins/usermanager/lang/fi/lang.php
+++ b/lib/plugins/usermanager/lang/fi/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Finnish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author otto@valjakko.net
* @author Otto Vainio <otto@valjakko.net>
* @author Teemu Mattila <ghcsystems@gmail.com>
diff --git a/lib/plugins/usermanager/lang/fr/lang.php b/lib/plugins/usermanager/lang/fr/lang.php
index 7c24ef900..dd0e64fc4 100644
--- a/lib/plugins/usermanager/lang/fr/lang.php
+++ b/lib/plugins/usermanager/lang/fr/lang.php
@@ -23,6 +23,7 @@
* @author Bruno Veilleux <bruno.vey@gmail.com>
* @author Antoine Turmel <geekshadow@gmail.com>
* @author schplurtz <Schplurtz@laposte.net>
+ * @author Jérôme Brandt <jeromebrandt@gmail.com>
*/
$lang['menu'] = 'Gestion des utilisateurs';
$lang['noauth'] = '(authentification de l\'utilisateur non disponible)';
@@ -70,6 +71,8 @@ $lang['add_ok'] = 'Utilisateur ajouté avec succès';
$lang['add_fail'] = 'Échec de l\'ajout de l\'utilisateur';
$lang['notify_ok'] = 'Courriel de notification expédié';
$lang['notify_fail'] = 'Échec de l\'expédition du courriel de notification';
+$lang['import_userlistcsv'] = 'Liste utilisateur (fichier CSV)';
+$lang['import_header'] = 'Erreurs d\'import les plus récentes';
$lang['import_success_count'] = 'Import d’utilisateurs : %d utilisateurs trouvés, %d utilisateurs importés avec succès.';
$lang['import_failure_count'] = 'Import d\'utilisateurs : %d ont échoué. Les erreurs sont listées ci-dessous.';
$lang['import_error_fields'] = 'Nombre de champs insuffisant, %d trouvé, 4 requis.';
@@ -80,3 +83,4 @@ $lang['import_error_upload'] = 'L\'import a échoué. Le fichier csv n\'a pas
$lang['import_error_readfail'] = 'L\'import a échoué. Impossible de lire le fichier téléchargé.';
$lang['import_error_create'] = 'Impossible de créer l\'utilisateur';
$lang['import_notify_fail'] = 'Impossible d\'expédier une notification à l\'utilisateur importé %s, adresse %s.';
+$lang['import_downloadfailures'] = 'Télécharger les erreurs au format CSV pour correction';
diff --git a/lib/plugins/usermanager/lang/hu/import.txt b/lib/plugins/usermanager/lang/hu/import.txt
index 5a4bc8b1c..f204f6a1e 100644
--- a/lib/plugins/usermanager/lang/hu/import.txt
+++ b/lib/plugins/usermanager/lang/hu/import.txt
@@ -1,9 +1,9 @@
==== Felhasználók tömeges importálása ====
-Egy, legalább 4 oszlopot tartalmazó, felhasználóikat tartalmazó fájl szükséges hozzá.
-Az oszlopok kötelező tartalma, megfelelő sorrendben: felhasználói azonosító, teljes név, e-mailcím és csoportjai.
-A CSV mezőit vesszővel (,) kell elválasztani, a szövegeket idézőjelek ("") közé kell foglalni.
-Mintafájl megtekintéséhez próbáld ki a fenti, "Felhasználók exportálása" funkciót. A fordított törtvonallal (\) lehet kilépni.
-Megegyező felhasználói azonosítók esetén, nem kerülnek feldolgozásra.
+Szükséges egy legalább 4 oszlopot tartalmazó, felhasználókat tartalmazó fájl.
+Az oszlopok kötelező tartalma, sorrendben: felhasználói azonosító, teljes név, e-mailcím és csoport.
+A CSV-mezőket vesszővel (,) kell elválasztani, a szövegeket idézőjelek ("") közé kell tenni. A fordított törtvonal (\) használható feloldójelnek.
+Megfelelő mintafájl megtekintéséhez próbáld ki a "Felhasználók exportálása" funkciót fentebb.
+A duplán szereplő felhasználói azonosítók kihagyásra kerülnek.
-Minden sikeresen importált felhasználó kap egy e-mailt, amiben megtalálja a generált jelszavát. \ No newline at end of file
+Minden sikeresen importált felhasználó számára jelszó készül, amelyet e-mailben kézhez kap. \ No newline at end of file
diff --git a/lib/plugins/usermanager/lang/hu/lang.php b/lib/plugins/usermanager/lang/hu/lang.php
index dd76bfd50..963fcd1fc 100644
--- a/lib/plugins/usermanager/lang/hu/lang.php
+++ b/lib/plugins/usermanager/lang/hu/lang.php
@@ -11,6 +11,7 @@
* @author David Szabo <szabo.david@gyumolcstarhely.hu>
* @author Marton Sebok <sebokmarton@gmail.com>
* @author Serenity87HUN <anikototh87@gmail.com>
+ * @author Marina Vladi <deldadam@gmail.com>
*/
$lang['menu'] = 'Felhasználók kezelése';
$lang['noauth'] = '(A felhasználói azonosítás nem működik.)';
@@ -58,14 +59,14 @@ $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.';
$lang['notify_fail'] = 'Nem sikerült az értesítő levelet elküldeni.';
-$lang['import_userlistcsv'] = 'Felhasználók listája fájl (CSV)';
+$lang['import_userlistcsv'] = 'Felhasználók listájának fájlja (CSV)';
$lang['import_header'] = 'Legutóbbi importálás - Hibák';
$lang['import_success_count'] = 'Felhasználók importálása: %d felhasználót találtunk, ebből %d sikeresen importálva.';
$lang['import_failure_count'] = 'Felhasználók importálása: %d sikertelen. A sikertelenség okait lejjebb találod.';
$lang['import_error_fields'] = 'Túl kevés mezőt adtál meg, %d darabot találtunk, legalább 4-re van szükség.';
$lang['import_error_baduserid'] = 'Felhasználói azonosító hiányzik';
-$lang['import_error_badname'] = 'Nem megfelelő név';
-$lang['import_error_badmail'] = 'Nem megfelelő e-mailcím';
+$lang['import_error_badname'] = 'Helytelen név';
+$lang['import_error_badmail'] = 'Helytelen e-mailcím';
$lang['import_error_upload'] = 'Sikertelen importálás. A csv fájl nem feltölthető vagy üres.';
$lang['import_error_readfail'] = 'Sikertelen importálás. A feltöltött fájl nem olvasható.';
$lang['import_error_create'] = 'Ez a felhasználó nem hozható létre';
diff --git a/lib/plugins/usermanager/lang/id/lang.php b/lib/plugins/usermanager/lang/id/lang.php
index 457ad4963..425b2ff59 100644
--- a/lib/plugins/usermanager/lang/id/lang.php
+++ b/lib/plugins/usermanager/lang/id/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * Indonesian language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Irwan Butar Butar <irwansah.putra@gmail.com>
* @author Yustinus Waruwu <juswaruwu@gmail.com>
*/
diff --git a/lib/plugins/usermanager/lang/it/lang.php b/lib/plugins/usermanager/lang/it/lang.php
index dfacc6545..6c6789442 100644
--- a/lib/plugins/usermanager/lang/it/lang.php
+++ b/lib/plugins/usermanager/lang/it/lang.php
@@ -15,6 +15,7 @@
* @author Jacopo Corbetta <jacopo.corbetta@gmail.com>
* @author Matteo Pasotti <matteo@xquiet.eu>
* @author snarchio@gmail.com
+ * @author Claudio Lanconelli <lancos@libero.it>
*/
$lang['menu'] = 'Gestione Utenti';
$lang['noauth'] = '(autenticazione non disponibile)';
@@ -37,6 +38,8 @@ $lang['search'] = 'Cerca';
$lang['search_prompt'] = 'Esegui ricerca';
$lang['clear'] = 'Azzera filtro di ricerca';
$lang['filter'] = 'Filtro';
+$lang['export_all'] = 'Esporta tutti gli utenti (CSV)';
+$lang['export_filtered'] = 'Esporta elenco utenti filtrati (CSV)';
$lang['summary'] = 'Visualizzazione utenti %1$d-%2$d di %3$d trovati. %4$d utenti totali.';
$lang['nonefound'] = 'Nessun utente trovato. %d utenti totali.';
$lang['delete_ok'] = '%d utenti eliminati';
diff --git a/lib/plugins/usermanager/lang/ja/import.txt b/lib/plugins/usermanager/lang/ja/import.txt
index d4f7d08bf..751e515ac 100644
--- a/lib/plugins/usermanager/lang/ja/import.txt
+++ b/lib/plugins/usermanager/lang/ja/import.txt
@@ -4,7 +4,7 @@
列の順序:ユーザーID、氏名、電子メールアドレス、グループ。
CSVフィールドはカンマ(,)区切り、文字列は引用符("")区切りです。
エスケープにバックスラッシュ(\)を使用できます。
-適切なファイル例は、上記の"エクスポートユーザー"機能で試して下さい。
+適切なファイル例は、上記の"エクスポートユーザー"機能で試して下さい。
重複するユーザーIDは無視されます。
正常にインポートされたユーザー毎に、パスワードを作成し、電子メールで送付します。 \ No newline at end of file
diff --git a/lib/plugins/usermanager/lang/ja/lang.php b/lib/plugins/usermanager/lang/ja/lang.php
index 0830416f3..23109f2a2 100644
--- a/lib/plugins/usermanager/lang/ja/lang.php
+++ b/lib/plugins/usermanager/lang/ja/lang.php
@@ -54,7 +54,7 @@ $lang['edit_usermissing'] = '選択したユーザーは見つかりませ
$lang['user_notify'] = 'ユーザーに通知する';
$lang['note_notify'] = '通知メールは、ユーザーに新たなパスワードが設定された場合のみ送信されます。';
$lang['note_group'] = 'グループを指定しない場合は、既定のグループ(%s)に配属されます。';
-$lang['note_pass'] = 'パスワードを空欄とした場合は、(”ユーザーに通知する”がチェックされていなくとも)自動生成したパスワードの通知がユーザー宛てに送信されます。';
+$lang['note_pass'] = '”ユーザーに通知する”をチェックしてパスワードを空欄にすると、パスワードは自動生成されます。';
$lang['add_ok'] = 'ユーザーを登録しました';
$lang['add_fail'] = 'ユーザーの登録に失敗しました';
$lang['notify_ok'] = '通知メールを送信しました';
diff --git a/lib/plugins/usermanager/lang/ko/lang.php b/lib/plugins/usermanager/lang/ko/lang.php
index 1905fadc2..ac129c95e 100644
--- a/lib/plugins/usermanager/lang/ko/lang.php
+++ b/lib/plugins/usermanager/lang/ko/lang.php
@@ -10,6 +10,7 @@
* @author erial2@gmail.com
* @author Myeongjin <aranet100@gmail.com>
* @author Gerrit Uitslag <klapinklapin@gmail.com>
+ * @author Garam <rowain8@gmail.com>
*/
$lang['menu'] = '사용자 관리자';
$lang['noauth'] = '(사용자 인증이 불가능합니다)';
@@ -28,9 +29,9 @@ $lang['delete_selected'] = '선택 삭제';
$lang['edit'] = '편집';
$lang['edit_prompt'] = '이 사용자 편집';
$lang['modify'] = '바뀜 저장';
-$lang['search'] = '찾기';
-$lang['search_prompt'] = '찾기 실행';
-$lang['clear'] = '찾기 필터 재설정';
+$lang['search'] = '검색';
+$lang['search_prompt'] = '검색 수행';
+$lang['clear'] = '검색 필터 재설정';
$lang['filter'] = '필터';
$lang['export_all'] = '모든 사용자 목록 내보내기 (CSV)';
$lang['export_filtered'] = '필터된 사용자 목록 내보내기 (CSV)';
@@ -52,7 +53,7 @@ $lang['edit_usermissing'] = '선택된 사용자를 찾을 수 없습니다
$lang['user_notify'] = '사용자에게 알림';
$lang['note_notify'] = '사용자에게 새로운 비밀번호를 준 경우에만 알림 이메일이 보내집니다.';
$lang['note_group'] = '새로운 사용자는 어떤 그룹도 설정하지 않은 경우에 기본 그룹(%s)에 추가됩니다.';
-$lang['note_pass'] = '사용자 통지가 지정되어 있을 때 필드에 아무 값도 입력하지 않으면 비밀번호가 자동으로 만들어집니다.';
+$lang['note_pass'] = '사용자 알림이 지정되어 있을 때 필드에 아무 값도 입력하지 않으면 비밀번호가 자동으로 만들어집니다.';
$lang['add_ok'] = '사용자를 성공적으로 추가했습니다';
$lang['add_fail'] = '사용자 추가를 실패했습니다';
$lang['notify_ok'] = '알림 이메일을 성공적으로 보냈습니다';
@@ -68,5 +69,5 @@ $lang['import_error_badmail'] = '잘못된 이메일 주소';
$lang['import_error_upload'] = '가져오기를 실패했습니다. csv 파일을 올릴 수 없거나 비어 있습니다.';
$lang['import_error_readfail'] = '가져오기를 실패했습니다. 올린 파일을 읽을 수 없습니다.';
$lang['import_error_create'] = '사용자를 만들 수 없습니다.';
-$lang['import_notify_fail'] = '알림 메시지를 가져온 %2$s (이메일: %1$s ) 사용자에게 보낼 수 없습니다.';
+$lang['import_notify_fail'] = '알림 메시지를 가져온 %s (이메일: %s) 사용자에게 보낼 수 없습니다.';
$lang['import_downloadfailures'] = '교정을 위한 CSV로 다운로드 실패';
diff --git a/lib/plugins/usermanager/lang/no/lang.php b/lib/plugins/usermanager/lang/no/lang.php
index 7124e4811..83823b2b8 100644
--- a/lib/plugins/usermanager/lang/no/lang.php
+++ b/lib/plugins/usermanager/lang/no/lang.php
@@ -1,13 +1,14 @@
<?php
+
/**
- * Norwegianlanguage file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Thomas Nygreen <nygreen@gmail.com>
* @author Arild Burud <arildb@met.no>
* @author Torkill Bruland <torkar-b@online.no>
* @author Rune M. Andersen <rune.andersen@gmail.com>
* @author Jakob Vad Nielsen (me@jakobnielsen.net)
- * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
+ * @author Kjell Tore Næsgaard <kjell.t.nasgaard@ntnu.no>
* @author Knut Staring <knutst@gmail.com>
* @author Lisa Ditlefsen <lisa@vervesearch.com>
* @author Erik Pedersen <erik.pedersen@shaw.ca>
diff --git a/lib/plugins/usermanager/lang/pl/lang.php b/lib/plugins/usermanager/lang/pl/lang.php
index cfc0ba327..2e063d2bb 100644
--- a/lib/plugins/usermanager/lang/pl/lang.php
+++ b/lib/plugins/usermanager/lang/pl/lang.php
@@ -1,7 +1,8 @@
<?php
+
/**
- * polish language file
- *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
* @author Grzegorz Żur <grzegorz.zur@gmail.com>
* @author Mariusz Kujawski <marinespl@gmail.com>
* @author Maciej Kurczewski <pipijajko@gmail.com>
diff --git a/lib/plugins/usermanager/lang/pt-br/lang.php b/lib/plugins/usermanager/lang/pt-br/lang.php
index 9bb37742a..356d139eb 100644
--- a/lib/plugins/usermanager/lang/pt-br/lang.php
+++ b/lib/plugins/usermanager/lang/pt-br/lang.php
@@ -20,6 +20,7 @@
* @author Victor Westmann <victor.westmann@gmail.com>
* @author Leone Lisboa Magevski <leone1983@gmail.com>
* @author Dário Estevão <darioems@gmail.com>
+ * @author Juliano Marconi Lanigra <juliano.marconi@gmail.com>
*/
$lang['menu'] = 'Gerenciamento de Usuários';
$lang['noauth'] = '(o gerenciamento de usuários não está disponível)';
@@ -43,6 +44,7 @@ $lang['search_prompt'] = 'Executar a pesquisa';
$lang['clear'] = 'Limpar o filtro de pesquisa';
$lang['filter'] = 'Filtro';
$lang['export_all'] = 'Exportar Todos Usuários (CSV)';
+$lang['export_filtered'] = 'Exportar lista de Usuários Filtrados (CSV)';
$lang['import'] = 'Importar Novos Usuários';
$lang['line'] = 'Linha Nº.';
$lang['error'] = 'Mensagem de Erro';
@@ -66,6 +68,8 @@ $lang['add_ok'] = 'O usuário foi adicionado com sucesso';
$lang['add_fail'] = 'O usuário não foi adicionado';
$lang['notify_ok'] = 'O e-mail de notificação foi enviado';
$lang['notify_fail'] = 'Não foi possível enviar o e-mail de notificação';
+$lang['import_userlistcsv'] = 'Arquivo de lista de usuários (CSV):';
+$lang['import_header'] = 'Importações Mais Recentes - Falhas';
$lang['import_success_count'] = 'Importação de Usuário: %d usuário (s) encontrado (s), %d importado (s) com sucesso.';
$lang['import_failure_count'] = 'Importação de Usuário: %d falhou. As falhas estão listadas abaixo.';
$lang['import_error_fields'] = 'Campos insuficientes, encontrado (s) %d, necessário 4.';
@@ -75,3 +79,5 @@ $lang['import_error_badmail'] = 'Endereço de email errado';
$lang['import_error_upload'] = 'Falha na Importação: O arquivo csv não pode ser carregado ou está vazio.';
$lang['import_error_readfail'] = 'Falha na Importação: Habilitar para ler o arquivo a ser carregado.';
$lang['import_error_create'] = 'Habilitar para criar o usuário.';
+$lang['import_notify_fail'] = 'Mensagem de notificação não pode ser enviada para o usuário importado, %s com email %s.';
+$lang['import_downloadfailures'] = 'Falhas no Download como CSV para correção';
diff --git a/lib/plugins/usermanager/lang/zh-tw/import.txt b/lib/plugins/usermanager/lang/zh-tw/import.txt
new file mode 100644
index 000000000..a6bb5f6ef
--- /dev/null
+++ b/lib/plugins/usermanager/lang/zh-tw/import.txt
@@ -0,0 +1,9 @@
+===== 批次匯入使用者 =====
+
+需提供 CSV 格式的使用者列表檔案(UTF-8 編碼)。
+每列至少 4 欄,依序為:帳號、姓名、電郵、群組。
+各欄以半形逗號 (,) 分隔,有半形逗號的字串可用半形雙引號 ("") 分開,引號可用反斜線 (\) 跳脫。
+重複的使用者帳號會自動忽略。
+如需要範例檔案,可用上面的「匯出使用者」取得。
+
+系統會為成功匯入的使用者產生密碼並寄信通知。
diff --git a/lib/plugins/usermanager/lang/zh-tw/lang.php b/lib/plugins/usermanager/lang/zh-tw/lang.php
index c7126bd1a..3fb6b6712 100644
--- a/lib/plugins/usermanager/lang/zh-tw/lang.php
+++ b/lib/plugins/usermanager/lang/zh-tw/lang.php
@@ -9,21 +9,26 @@
* @author Wayne San <waynesan@zerozone.tw>
* @author Li-Jiun Huang <ljhuang.tw@gmai.com>
* @author Cheng-Wei Chien <e.cwchien@gmail.com>
- * @author Danny Lin <danny0838@pchome.com.tw>
* @author Shuo-Ting Jian <shoting@gmail.com>
* @author syaoranhinata@gmail.com
* @author Ichirou Uchiki <syaoranhinata@gmail.com>
* @author tsangho <ou4222@gmail.com>
+ * @author Danny Lin <danny0838@gmail.com>
*/
$lang['menu'] = '帳號管理器';
+
+// custom language strings for the plugin
$lang['noauth'] = '(帳號認證尚未開放)';
$lang['nosupport'] = '(尚不支援帳號管理)';
+
$lang['badauth'] = '錯誤的認證機制';
+
$lang['user_id'] = '帳號';
$lang['user_pass'] = '密碼';
$lang['user_name'] = '名稱';
$lang['user_mail'] = '電郵';
$lang['user_groups'] = '群組';
+
$lang['field'] = '欄位';
$lang['value'] = '設定值';
$lang['add'] = '增加';
@@ -36,8 +41,12 @@ $lang['search'] = '搜尋';
$lang['search_prompt'] = '開始搜尋';
$lang['clear'] = '重設篩選條件';
$lang['filter'] = '篩選條件 (Filter)';
-$lang['import'] = '匯入新的用戶';
+$lang['export_all'] = '匯出所有使用者 (CSV)';
+$lang['export_filtered'] = '匯出篩選後的使用者列表 (CSV)';
+$lang['import'] = '匯入新使用者';
+$lang['line'] = '列號';
$lang['error'] = '錯誤訊息';
+
$lang['summary'] = '顯示帳號 %1$d-%2$d,共 %3$d 筆符合。共有 %4$d 個帳號。';
$lang['nonefound'] = '找不到帳號。共有 %d 個帳號。';
$lang['delete_ok'] = '已刪除 %d 個帳號';
@@ -45,10 +54,13 @@ $lang['delete_fail'] = '%d 個帳號無法刪除。';
$lang['update_ok'] = '已更新該帳號';
$lang['update_fail'] = '無法更新該帳號';
$lang['update_exists'] = '無法變更帳號名稱 (%s) ,因為有同名帳號存在。其他修改則已套用。';
+
$lang['start'] = '開始';
$lang['prev'] = '上一頁';
$lang['next'] = '下一頁';
$lang['last'] = '最後一頁';
+
+// added after 2006-03-09 release
$lang['edit_usermissing'] = '找不到選取的帳號,可能已被刪除或改為其他名稱。';
$lang['user_notify'] = '通知使用者';
$lang['note_notify'] = '通知信只會在指定使用者新密碼時寄送。';
@@ -58,4 +70,18 @@ $lang['add_ok'] = '已新增使用者';
$lang['add_fail'] = '無法新增使用者';
$lang['notify_ok'] = '通知信已寄出';
$lang['notify_fail'] = '通知信無法寄出';
-$lang['import_error_readfail'] = '會入錯誤,無法讀取已經上傳的檔案';
+
+// import & errors
+$lang['import_userlistcsv'] = '使用者列表檔案 (CSV): ';
+$lang['import_header'] = '最近一次匯入 - 失敗';
+$lang['import_success_count'] = '使用者匯入:找到 %d 個使用者,已成功匯入 %d 個。';
+$lang['import_failure_count'] = '使用者匯入:%d 個匯入失敗,列出於下。';
+$lang['import_error_fields'] = '欄位不足,需要 4 個,找到 %d 個。';
+$lang['import_error_baduserid'] = '使用者帳號遺失';
+$lang['import_error_badname'] = '名稱不正確';
+$lang['import_error_badmail'] = '電郵位址不正確';
+$lang['import_error_upload'] = '匯入失敗,CSV 檔案內容空白或無法匯入。';
+$lang['import_error_readfail'] = '匯入錯誤,無法讀取上傳的檔案';
+$lang['import_error_create'] = '無法建立使用者';
+$lang['import_notify_fail'] = '通知訊息無法寄給已匯入的使用者 %s(電郵 %s)';
+$lang['import_downloadfailures'] = '下載失敗項的 CSV 檔案以供修正';
diff --git a/lib/plugins/usermanager/lang/zh/lang.php b/lib/plugins/usermanager/lang/zh/lang.php
index 25eb1a294..b833c6ce4 100644
--- a/lib/plugins/usermanager/lang/zh/lang.php
+++ b/lib/plugins/usermanager/lang/zh/lang.php
@@ -17,6 +17,7 @@
* @author Shuo-Ting Jian <shoting@gmail.com>
* @author Rachel <rzhang0802@gmail.com>
* @author Yangyu Huang <yangyu.huang@gmail.com>
+ * @author oott123 <ip.192.168.1.1@qq.com>
*/
$lang['menu'] = '用户管理器';
$lang['noauth'] = '(用户认证不可用)';
@@ -76,3 +77,4 @@ $lang['import_error_upload'] = '导入失败。CSV 文件无法上传或是空
$lang['import_error_readfail'] = '导入失败。无法读取上传的文件。';
$lang['import_error_create'] = '不能创建新用户';
$lang['import_notify_fail'] = '通知消息无法发送到导入的用户 %s,电子邮件地址是 %s。';
+$lang['import_downloadfailures'] = '下载CSV的错误信息以修正。';
diff --git a/lib/scripts/jquery/jquery-migrate.js b/lib/scripts/jquery/jquery-migrate.js
index e99f954e6..942cb8b4d 100644
--- a/lib/scripts/jquery/jquery-migrate.js
+++ b/lib/scripts/jquery/jquery-migrate.js
@@ -1,511 +1,511 @@
-/*!
- * jQuery Migrate - v1.1.1 - 2013-02-16
- * https://github.com/jquery/jquery-migrate
- * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
- */
-(function( jQuery, window, undefined ) {
-// See http://bugs.jquery.com/ticket/13335
-// "use strict";
-
-
-var warnedAbout = {};
-
-// List of warnings already given; public read only
-jQuery.migrateWarnings = [];
-
-// Set to true to prevent console output; migrateWarnings still maintained
-// jQuery.migrateMute = false;
-
-// Show a message on the console so devs know we're active
-if ( !jQuery.migrateMute && window.console && console.log ) {
- console.log("JQMIGRATE: Logging is active");
-}
-
-// Set to false to disable traces that appear with warnings
-if ( jQuery.migrateTrace === undefined ) {
- jQuery.migrateTrace = true;
-}
-
-// Forget any warnings we've already given; public
-jQuery.migrateReset = function() {
- warnedAbout = {};
- jQuery.migrateWarnings.length = 0;
-};
-
-function migrateWarn( msg) {
- if ( !warnedAbout[ msg ] ) {
- warnedAbout[ msg ] = true;
- jQuery.migrateWarnings.push( msg );
- if ( window.console && console.warn && !jQuery.migrateMute ) {
- console.warn( "JQMIGRATE: " + msg );
- if ( jQuery.migrateTrace && console.trace ) {
- console.trace();
- }
- }
- }
-}
-
-function migrateWarnProp( obj, prop, value, msg ) {
- if ( Object.defineProperty ) {
- // On ES5 browsers (non-oldIE), warn if the code tries to get prop;
- // allow property to be overwritten in case some other plugin wants it
- try {
- Object.defineProperty( obj, prop, {
- configurable: true,
- enumerable: true,
- get: function() {
- migrateWarn( msg );
- return value;
- },
- set: function( newValue ) {
- migrateWarn( msg );
- value = newValue;
- }
- });
- return;
- } catch( err ) {
- // IE8 is a dope about Object.defineProperty, can't warn there
- }
- }
-
- // Non-ES5 (or broken) browser; just set the property
- jQuery._definePropertyBroken = true;
- obj[ prop ] = value;
-}
-
-if ( document.compatMode === "BackCompat" ) {
- // jQuery has never supported or tested Quirks Mode
- migrateWarn( "jQuery is not compatible with Quirks Mode" );
-}
-
-
-var attrFn = jQuery( "<input/>", { size: 1 } ).attr("size") && jQuery.attrFn,
- oldAttr = jQuery.attr,
- valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
- function() { return null; },
- valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
- function() { return undefined; },
- rnoType = /^(?:input|button)$/i,
- rnoAttrNodeType = /^[238]$/,
- rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
- ruseDefault = /^(?:checked|selected)$/i;
-
-// jQuery.attrFn
-migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" );
-
-jQuery.attr = function( elem, name, value, pass ) {
- var lowerName = name.toLowerCase(),
- nType = elem && elem.nodeType;
-
- if ( pass ) {
- // Since pass is used internally, we only warn for new jQuery
- // versions where there isn't a pass arg in the formal params
- if ( oldAttr.length < 4 ) {
- migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
- }
- if ( elem && !rnoAttrNodeType.test( nType ) &&
- (attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {
- return jQuery( elem )[ name ]( value );
- }
- }
-
- // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
- // for disconnected elements we don't warn on $( "<button>", { type: "button" } ).
- if ( name === "type" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {
- migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
- }
-
- // Restore boolHook for boolean property/attribute synchronization
- if ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {
- jQuery.attrHooks[ lowerName ] = {
- get: function( elem, name ) {
- // Align boolean attributes with corresponding properties
- // Fall back to attribute presence where some booleans are not supported
- var attrNode,
- property = jQuery.prop( elem, name );
- return property === true || typeof property !== "boolean" &&
- ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
-
- name.toLowerCase() :
- undefined;
- },
- set: function( elem, value, name ) {
- var propName;
- if ( value === false ) {
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else {
- // value is true since we know at this point it's type boolean and not false
- // Set boolean attributes to the same name and set the DOM property
- propName = jQuery.propFix[ name ] || name;
- if ( propName in elem ) {
- // Only set the IDL specifically if it already exists on the element
- elem[ propName ] = true;
- }
-
- elem.setAttribute( name, name.toLowerCase() );
- }
- return name;
- }
- };
-
- // Warn only for attributes that can remain distinct from their properties post-1.9
- if ( ruseDefault.test( lowerName ) ) {
- migrateWarn( "jQuery.fn.attr('" + lowerName + "') may use property instead of attribute" );
- }
- }
-
- return oldAttr.call( jQuery, elem, name, value );
-};
-
-// attrHooks: value
-jQuery.attrHooks.value = {
- get: function( elem, name ) {
- var nodeName = ( elem.nodeName || "" ).toLowerCase();
- if ( nodeName === "button" ) {
- return valueAttrGet.apply( this, arguments );
- }
- if ( nodeName !== "input" && nodeName !== "option" ) {
- migrateWarn("jQuery.fn.attr('value') no longer gets properties");
- }
- return name in elem ?
- elem.value :
- null;
- },
- set: function( elem, value ) {
- var nodeName = ( elem.nodeName || "" ).toLowerCase();
- if ( nodeName === "button" ) {
- return valueAttrSet.apply( this, arguments );
- }
- if ( nodeName !== "input" && nodeName !== "option" ) {
- migrateWarn("jQuery.fn.attr('value', val) no longer sets properties");
- }
- // Does not return so that setAttribute is also used
- elem.value = value;
- }
-};
-
-
-var matched, browser,
- oldInit = jQuery.fn.init,
- oldParseJSON = jQuery.parseJSON,
- // Note this does NOT include the #9521 XSS fix from 1.7!
- rquickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;
-
-// $(html) "looks like html" rule change
-jQuery.fn.init = function( selector, context, rootjQuery ) {
- var match;
-
- if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
- (match = rquickExpr.exec( selector )) && match[1] ) {
- // This is an HTML string according to the "old" rules; is it still?
- if ( selector.charAt( 0 ) !== "<" ) {
- migrateWarn("$(html) HTML strings must start with '<' character");
- }
- // Now process using loose rules; let pre-1.8 play too
- if ( context && context.context ) {
- // jQuery object as context; parseHTML expects a DOM object
- context = context.context;
- }
- if ( jQuery.parseHTML ) {
- return oldInit.call( this, jQuery.parseHTML( jQuery.trim(selector), context, true ),
- context, rootjQuery );
- }
- }
- return oldInit.apply( this, arguments );
-};
-jQuery.fn.init.prototype = jQuery.fn;
-
-// Let $.parseJSON(falsy_value) return null
-jQuery.parseJSON = function( json ) {
- if ( !json && json !== null ) {
- migrateWarn("jQuery.parseJSON requires a valid JSON string");
- return null;
- }
- return oldParseJSON.apply( this, arguments );
-};
-
-jQuery.uaMatch = function( ua ) {
- ua = ua.toLowerCase();
-
- var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
- /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
- /(msie) ([\w.]+)/.exec( ua ) ||
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
- [];
-
- return {
- browser: match[ 1 ] || "",
- version: match[ 2 ] || "0"
- };
-};
-
-// Don't clobber any existing jQuery.browser in case it's different
-if ( !jQuery.browser ) {
- matched = jQuery.uaMatch( navigator.userAgent );
- browser = {};
-
- if ( matched.browser ) {
- browser[ matched.browser ] = true;
- browser.version = matched.version;
- }
-
- // Chrome is Webkit, but Webkit is also Safari.
- if ( browser.chrome ) {
- browser.webkit = true;
- } else if ( browser.webkit ) {
- browser.safari = true;
- }
-
- jQuery.browser = browser;
-}
-
-// Warn if the code tries to get jQuery.browser
-migrateWarnProp( jQuery, "browser", jQuery.browser, "jQuery.browser is deprecated" );
-
-jQuery.sub = function() {
- function jQuerySub( selector, context ) {
- return new jQuerySub.fn.init( selector, context );
- }
- jQuery.extend( true, jQuerySub, this );
- jQuerySub.superclass = this;
- jQuerySub.fn = jQuerySub.prototype = this();
- jQuerySub.fn.constructor = jQuerySub;
- jQuerySub.sub = this.sub;
- jQuerySub.fn.init = function init( selector, context ) {
- if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
- context = jQuerySub( context );
- }
-
- return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
- };
- jQuerySub.fn.init.prototype = jQuerySub.fn;
- var rootjQuerySub = jQuerySub(document);
- migrateWarn( "jQuery.sub() is deprecated" );
- return jQuerySub;
-};
-
-
-// Ensure that $.ajax gets the new parseJSON defined in core.js
-jQuery.ajaxSetup({
- converters: {
- "text json": jQuery.parseJSON
- }
-});
-
-
-var oldFnData = jQuery.fn.data;
-
-jQuery.fn.data = function( name ) {
- var ret, evt,
- elem = this[0];
-
- // Handles 1.7 which has this behavior and 1.8 which doesn't
- if ( elem && name === "events" && arguments.length === 1 ) {
- ret = jQuery.data( elem, name );
- evt = jQuery._data( elem, name );
- if ( ( ret === undefined || ret === evt ) && evt !== undefined ) {
- migrateWarn("Use of jQuery.fn.data('events') is deprecated");
- return evt;
- }
- }
- return oldFnData.apply( this, arguments );
-};
-
-
-var rscriptType = /\/(java|ecma)script/i,
- oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
-
-jQuery.fn.andSelf = function() {
- migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
- return oldSelf.apply( this, arguments );
-};
-
-// Since jQuery.clean is used internally on older versions, we only shim if it's missing
-if ( !jQuery.clean ) {
- jQuery.clean = function( elems, context, fragment, scripts ) {
- // Set context per 1.8 logic
- context = context || document;
- context = !context.nodeType && context[0] || context;
- context = context.ownerDocument || context;
-
- migrateWarn("jQuery.clean() is deprecated");
-
- var i, elem, handleScript, jsTags,
- ret = [];
-
- jQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );
-
- // Complex logic lifted directly from jQuery 1.8
- if ( fragment ) {
- // Special handling of each script element
- handleScript = function( elem ) {
- // Check if we consider it executable
- if ( !elem.type || rscriptType.test( elem.type ) ) {
- // Detach the script and store it in the scripts array (if provided) or the fragment
- // Return truthy to indicate that it has been handled
- return scripts ?
- scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
- fragment.appendChild( elem );
- }
- };
-
- for ( i = 0; (elem = ret[i]) != null; i++ ) {
- // Check if we're done after handling an executable script
- if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
- // Append to fragment and handle embedded scripts
- fragment.appendChild( elem );
- if ( typeof elem.getElementsByTagName !== "undefined" ) {
- // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
- jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
-
- // Splice the scripts into ret after their former ancestor and advance our index beyond them
- ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
- i += jsTags.length;
- }
- }
- }
- }
-
- return ret;
- };
-}
-
-var eventAdd = jQuery.event.add,
- eventRemove = jQuery.event.remove,
- eventTrigger = jQuery.event.trigger,
- oldToggle = jQuery.fn.toggle,
- oldLive = jQuery.fn.live,
- oldDie = jQuery.fn.die,
- ajaxEvents = "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
- rajaxEvent = new RegExp( "\\b(?:" + ajaxEvents + ")\\b" ),
- rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
- hoverHack = function( events ) {
- if ( typeof( events ) !== "string" || jQuery.event.special.hover ) {
- return events;
- }
- if ( rhoverHack.test( events ) ) {
- migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
- }
- return events && events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
- };
-
-// Event props removed in 1.9, put them back if needed; no practical way to warn them
-if ( jQuery.event.props && jQuery.event.props[ 0 ] !== "attrChange" ) {
- jQuery.event.props.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
-}
-
-// Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
-if ( jQuery.event.dispatch ) {
- migrateWarnProp( jQuery.event, "handle", jQuery.event.dispatch, "jQuery.event.handle is undocumented and deprecated" );
-}
-
-// Support for 'hover' pseudo-event and ajax event warnings
-jQuery.event.add = function( elem, types, handler, data, selector ){
- if ( elem !== document && rajaxEvent.test( types ) ) {
- migrateWarn( "AJAX events should be attached to document: " + types );
- }
- eventAdd.call( this, elem, hoverHack( types || "" ), handler, data, selector );
-};
-jQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){
- eventRemove.call( this, elem, hoverHack( types ) || "", handler, selector, mappedTypes );
-};
-
-jQuery.fn.error = function() {
- var args = Array.prototype.slice.call( arguments, 0);
- migrateWarn("jQuery.fn.error() is deprecated");
- args.splice( 0, 0, "error" );
- if ( arguments.length ) {
- return this.bind.apply( this, args );
- }
- // error event should not bubble to window, although it does pre-1.7
- this.triggerHandler.apply( this, args );
- return this;
-};
-
-jQuery.fn.toggle = function( fn, fn2 ) {
-
- // Don't mess with animation or css toggles
- if ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {
- return oldToggle.apply( this, arguments );
- }
- migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");
-
- // Save reference to arguments for access in closure
- var args = arguments,
- guid = fn.guid || jQuery.guid++,
- i = 0,
- toggler = function( event ) {
- // Figure out which function to execute
- var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
- jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
-
- // Make sure that clicks stop
- event.preventDefault();
-
- // and execute the function
- return args[ lastToggle ].apply( this, arguments ) || false;
- };
-
- // link all the functions, so any of them can unbind this click handler
- toggler.guid = guid;
- while ( i < args.length ) {
- args[ i++ ].guid = guid;
- }
-
- return this.click( toggler );
-};
-
-jQuery.fn.live = function( types, data, fn ) {
- migrateWarn("jQuery.fn.live() is deprecated");
- if ( oldLive ) {
- return oldLive.apply( this, arguments );
- }
- jQuery( this.context ).on( types, this.selector, data, fn );
- return this;
-};
-
-jQuery.fn.die = function( types, fn ) {
- migrateWarn("jQuery.fn.die() is deprecated");
- if ( oldDie ) {
- return oldDie.apply( this, arguments );
- }
- jQuery( this.context ).off( types, this.selector || "**", fn );
- return this;
-};
-
-// Turn global events into document-triggered events
-jQuery.event.trigger = function( event, data, elem, onlyHandlers ){
- if ( !elem && !rajaxEvent.test( event ) ) {
- migrateWarn( "Global events are undocumented and deprecated" );
- }
- return eventTrigger.call( this, event, data, elem || document, onlyHandlers );
-};
-jQuery.each( ajaxEvents.split("|"),
- function( _, name ) {
- jQuery.event.special[ name ] = {
- setup: function() {
- var elem = this;
-
- // The document needs no shimming; must be !== for oldIE
- if ( elem !== document ) {
- jQuery.event.add( document, name + "." + jQuery.guid, function() {
- jQuery.event.trigger( name, null, elem, true );
- });
- jQuery._data( this, name, jQuery.guid++ );
- }
- return false;
- },
- teardown: function() {
- if ( this !== document ) {
- jQuery.event.remove( document, name + "." + jQuery._data( this, name ) );
- }
- return false;
- }
- };
- }
-);
-
-
-})( jQuery, window );
+/*!
+ * jQuery Migrate - v1.1.1 - 2013-02-16
+ * https://github.com/jquery/jquery-migrate
+ * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
+ */
+(function( jQuery, window, undefined ) {
+// See http://bugs.jquery.com/ticket/13335
+// "use strict";
+
+
+var warnedAbout = {};
+
+// List of warnings already given; public read only
+jQuery.migrateWarnings = [];
+
+// Set to true to prevent console output; migrateWarnings still maintained
+// jQuery.migrateMute = false;
+
+// Show a message on the console so devs know we're active
+if ( !jQuery.migrateMute && window.console && console.log ) {
+ console.log("JQMIGRATE: Logging is active");
+}
+
+// Set to false to disable traces that appear with warnings
+if ( jQuery.migrateTrace === undefined ) {
+ jQuery.migrateTrace = true;
+}
+
+// Forget any warnings we've already given; public
+jQuery.migrateReset = function() {
+ warnedAbout = {};
+ jQuery.migrateWarnings.length = 0;
+};
+
+function migrateWarn( msg) {
+ if ( !warnedAbout[ msg ] ) {
+ warnedAbout[ msg ] = true;
+ jQuery.migrateWarnings.push( msg );
+ if ( window.console && console.warn && !jQuery.migrateMute ) {
+ console.warn( "JQMIGRATE: " + msg );
+ if ( jQuery.migrateTrace && console.trace ) {
+ console.trace();
+ }
+ }
+ }
+}
+
+function migrateWarnProp( obj, prop, value, msg ) {
+ if ( Object.defineProperty ) {
+ // On ES5 browsers (non-oldIE), warn if the code tries to get prop;
+ // allow property to be overwritten in case some other plugin wants it
+ try {
+ Object.defineProperty( obj, prop, {
+ configurable: true,
+ enumerable: true,
+ get: function() {
+ migrateWarn( msg );
+ return value;
+ },
+ set: function( newValue ) {
+ migrateWarn( msg );
+ value = newValue;
+ }
+ });
+ return;
+ } catch( err ) {
+ // IE8 is a dope about Object.defineProperty, can't warn there
+ }
+ }
+
+ // Non-ES5 (or broken) browser; just set the property
+ jQuery._definePropertyBroken = true;
+ obj[ prop ] = value;
+}
+
+if ( document.compatMode === "BackCompat" ) {
+ // jQuery has never supported or tested Quirks Mode
+ migrateWarn( "jQuery is not compatible with Quirks Mode" );
+}
+
+
+var attrFn = jQuery( "<input/>", { size: 1 } ).attr("size") && jQuery.attrFn,
+ oldAttr = jQuery.attr,
+ valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
+ function() { return null; },
+ valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
+ function() { return undefined; },
+ rnoType = /^(?:input|button)$/i,
+ rnoAttrNodeType = /^[238]$/,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ ruseDefault = /^(?:checked|selected)$/i;
+
+// jQuery.attrFn
+migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" );
+
+jQuery.attr = function( elem, name, value, pass ) {
+ var lowerName = name.toLowerCase(),
+ nType = elem && elem.nodeType;
+
+ if ( pass ) {
+ // Since pass is used internally, we only warn for new jQuery
+ // versions where there isn't a pass arg in the formal params
+ if ( oldAttr.length < 4 ) {
+ migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
+ }
+ if ( elem && !rnoAttrNodeType.test( nType ) &&
+ (attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {
+ return jQuery( elem )[ name ]( value );
+ }
+ }
+
+ // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
+ // for disconnected elements we don't warn on $( "<button>", { type: "button" } ).
+ if ( name === "type" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {
+ migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
+ }
+
+ // Restore boolHook for boolean property/attribute synchronization
+ if ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {
+ jQuery.attrHooks[ lowerName ] = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" &&
+ ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+ };
+
+ // Warn only for attributes that can remain distinct from their properties post-1.9
+ if ( ruseDefault.test( lowerName ) ) {
+ migrateWarn( "jQuery.fn.attr('" + lowerName + "') may use property instead of attribute" );
+ }
+ }
+
+ return oldAttr.call( jQuery, elem, name, value );
+};
+
+// attrHooks: value
+jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "button" ) {
+ return valueAttrGet.apply( this, arguments );
+ }
+ if ( nodeName !== "input" && nodeName !== "option" ) {
+ migrateWarn("jQuery.fn.attr('value') no longer gets properties");
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "button" ) {
+ return valueAttrSet.apply( this, arguments );
+ }
+ if ( nodeName !== "input" && nodeName !== "option" ) {
+ migrateWarn("jQuery.fn.attr('value', val) no longer sets properties");
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+};
+
+
+var matched, browser,
+ oldInit = jQuery.fn.init,
+ oldParseJSON = jQuery.parseJSON,
+ // Note this does NOT include the #9521 XSS fix from 1.7!
+ rquickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;
+
+// $(html) "looks like html" rule change
+jQuery.fn.init = function( selector, context, rootjQuery ) {
+ var match;
+
+ if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
+ (match = rquickExpr.exec( selector )) && match[1] ) {
+ // This is an HTML string according to the "old" rules; is it still?
+ if ( selector.charAt( 0 ) !== "<" ) {
+ migrateWarn("$(html) HTML strings must start with '<' character");
+ }
+ // Now process using loose rules; let pre-1.8 play too
+ if ( context && context.context ) {
+ // jQuery object as context; parseHTML expects a DOM object
+ context = context.context;
+ }
+ if ( jQuery.parseHTML ) {
+ return oldInit.call( this, jQuery.parseHTML( jQuery.trim(selector), context, true ),
+ context, rootjQuery );
+ }
+ }
+ return oldInit.apply( this, arguments );
+};
+jQuery.fn.init.prototype = jQuery.fn;
+
+// Let $.parseJSON(falsy_value) return null
+jQuery.parseJSON = function( json ) {
+ if ( !json && json !== null ) {
+ migrateWarn("jQuery.parseJSON requires a valid JSON string");
+ return null;
+ }
+ return oldParseJSON.apply( this, arguments );
+};
+
+jQuery.uaMatch = function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+};
+
+// Don't clobber any existing jQuery.browser in case it's different
+if ( !jQuery.browser ) {
+ matched = jQuery.uaMatch( navigator.userAgent );
+ browser = {};
+
+ if ( matched.browser ) {
+ browser[ matched.browser ] = true;
+ browser.version = matched.version;
+ }
+
+ // Chrome is Webkit, but Webkit is also Safari.
+ if ( browser.chrome ) {
+ browser.webkit = true;
+ } else if ( browser.webkit ) {
+ browser.safari = true;
+ }
+
+ jQuery.browser = browser;
+}
+
+// Warn if the code tries to get jQuery.browser
+migrateWarnProp( jQuery, "browser", jQuery.browser, "jQuery.browser is deprecated" );
+
+jQuery.sub = function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ migrateWarn( "jQuery.sub() is deprecated" );
+ return jQuerySub;
+};
+
+
+// Ensure that $.ajax gets the new parseJSON defined in core.js
+jQuery.ajaxSetup({
+ converters: {
+ "text json": jQuery.parseJSON
+ }
+});
+
+
+var oldFnData = jQuery.fn.data;
+
+jQuery.fn.data = function( name ) {
+ var ret, evt,
+ elem = this[0];
+
+ // Handles 1.7 which has this behavior and 1.8 which doesn't
+ if ( elem && name === "events" && arguments.length === 1 ) {
+ ret = jQuery.data( elem, name );
+ evt = jQuery._data( elem, name );
+ if ( ( ret === undefined || ret === evt ) && evt !== undefined ) {
+ migrateWarn("Use of jQuery.fn.data('events') is deprecated");
+ return evt;
+ }
+ }
+ return oldFnData.apply( this, arguments );
+};
+
+
+var rscriptType = /\/(java|ecma)script/i,
+ oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
+
+jQuery.fn.andSelf = function() {
+ migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
+ return oldSelf.apply( this, arguments );
+};
+
+// Since jQuery.clean is used internally on older versions, we only shim if it's missing
+if ( !jQuery.clean ) {
+ jQuery.clean = function( elems, context, fragment, scripts ) {
+ // Set context per 1.8 logic
+ context = context || document;
+ context = !context.nodeType && context[0] || context;
+ context = context.ownerDocument || context;
+
+ migrateWarn("jQuery.clean() is deprecated");
+
+ var i, elem, handleScript, jsTags,
+ ret = [];
+
+ jQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );
+
+ // Complex logic lifted directly from jQuery 1.8
+ if ( fragment ) {
+ // Special handling of each script element
+ handleScript = function( elem ) {
+ // Check if we consider it executable
+ if ( !elem.type || rscriptType.test( elem.type ) ) {
+ // Detach the script and store it in the scripts array (if provided) or the fragment
+ // Return truthy to indicate that it has been handled
+ return scripts ?
+ scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
+ fragment.appendChild( elem );
+ }
+ };
+
+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
+ // Check if we're done after handling an executable script
+ if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
+ // Append to fragment and handle embedded scripts
+ fragment.appendChild( elem );
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
+ jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
+
+ // Splice the scripts into ret after their former ancestor and advance our index beyond them
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ i += jsTags.length;
+ }
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var eventAdd = jQuery.event.add,
+ eventRemove = jQuery.event.remove,
+ eventTrigger = jQuery.event.trigger,
+ oldToggle = jQuery.fn.toggle,
+ oldLive = jQuery.fn.live,
+ oldDie = jQuery.fn.die,
+ ajaxEvents = "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
+ rajaxEvent = new RegExp( "\\b(?:" + ajaxEvents + ")\\b" ),
+ rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
+ hoverHack = function( events ) {
+ if ( typeof( events ) !== "string" || jQuery.event.special.hover ) {
+ return events;
+ }
+ if ( rhoverHack.test( events ) ) {
+ migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
+ }
+ return events && events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+// Event props removed in 1.9, put them back if needed; no practical way to warn them
+if ( jQuery.event.props && jQuery.event.props[ 0 ] !== "attrChange" ) {
+ jQuery.event.props.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
+}
+
+// Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
+if ( jQuery.event.dispatch ) {
+ migrateWarnProp( jQuery.event, "handle", jQuery.event.dispatch, "jQuery.event.handle is undocumented and deprecated" );
+}
+
+// Support for 'hover' pseudo-event and ajax event warnings
+jQuery.event.add = function( elem, types, handler, data, selector ){
+ if ( elem !== document && rajaxEvent.test( types ) ) {
+ migrateWarn( "AJAX events should be attached to document: " + types );
+ }
+ eventAdd.call( this, elem, hoverHack( types || "" ), handler, data, selector );
+};
+jQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){
+ eventRemove.call( this, elem, hoverHack( types ) || "", handler, selector, mappedTypes );
+};
+
+jQuery.fn.error = function() {
+ var args = Array.prototype.slice.call( arguments, 0);
+ migrateWarn("jQuery.fn.error() is deprecated");
+ args.splice( 0, 0, "error" );
+ if ( arguments.length ) {
+ return this.bind.apply( this, args );
+ }
+ // error event should not bubble to window, although it does pre-1.7
+ this.triggerHandler.apply( this, args );
+ return this;
+};
+
+jQuery.fn.toggle = function( fn, fn2 ) {
+
+ // Don't mess with animation or css toggles
+ if ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {
+ return oldToggle.apply( this, arguments );
+ }
+ migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");
+
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+};
+
+jQuery.fn.live = function( types, data, fn ) {
+ migrateWarn("jQuery.fn.live() is deprecated");
+ if ( oldLive ) {
+ return oldLive.apply( this, arguments );
+ }
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+};
+
+jQuery.fn.die = function( types, fn ) {
+ migrateWarn("jQuery.fn.die() is deprecated");
+ if ( oldDie ) {
+ return oldDie.apply( this, arguments );
+ }
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+};
+
+// Turn global events into document-triggered events
+jQuery.event.trigger = function( event, data, elem, onlyHandlers ){
+ if ( !elem && !rajaxEvent.test( event ) ) {
+ migrateWarn( "Global events are undocumented and deprecated" );
+ }
+ return eventTrigger.call( this, event, data, elem || document, onlyHandlers );
+};
+jQuery.each( ajaxEvents.split("|"),
+ function( _, name ) {
+ jQuery.event.special[ name ] = {
+ setup: function() {
+ var elem = this;
+
+ // The document needs no shimming; must be !== for oldIE
+ if ( elem !== document ) {
+ jQuery.event.add( document, name + "." + jQuery.guid, function() {
+ jQuery.event.trigger( name, null, elem, true );
+ });
+ jQuery._data( this, name, jQuery.guid++ );
+ }
+ return false;
+ },
+ teardown: function() {
+ if ( this !== document ) {
+ jQuery.event.remove( document, name + "." + jQuery._data( this, name ) );
+ }
+ return false;
+ }
+ };
+ }
+);
+
+
+})( jQuery, window );
diff --git a/lib/scripts/jquery/jquery-migrate.min.js b/lib/scripts/jquery/jquery-migrate.min.js
index 759f35e85..ff9113df3 100644
--- a/lib/scripts/jquery/jquery-migrate.min.js
+++ b/lib/scripts/jquery/jquery-migrate.min.js
@@ -1,3 +1,2 @@
-/*! jQuery Migrate v1.1.1 | (c) 2005, 2013 jQuery Foundation, Inc. and other contributors | jquery.org/license */
+/*! jQuery Migrate v1.1.1 | (c) 2005, 2013 jQuery Foundation, Inc. and other contributors | jquery.org/license */
jQuery.migrateMute===void 0&&(jQuery.migrateMute=!0),function(e,t,n){function r(n){o[n]||(o[n]=!0,e.migrateWarnings.push(n),t.console&&console.warn&&!e.migrateMute&&(console.warn("JQMIGRATE: "+n),e.migrateTrace&&console.trace&&console.trace()))}function a(t,a,o,i){if(Object.defineProperty)try{return Object.defineProperty(t,a,{configurable:!0,enumerable:!0,get:function(){return r(i),o},set:function(e){r(i),o=e}}),n}catch(s){}e._definePropertyBroken=!0,t[a]=o}var o={};e.migrateWarnings=[],!e.migrateMute&&t.console&&console.log&&console.log("JQMIGRATE: Logging is active"),e.migrateTrace===n&&(e.migrateTrace=!0),e.migrateReset=function(){o={},e.migrateWarnings.length=0},"BackCompat"===document.compatMode&&r("jQuery is not compatible with Quirks Mode");var i=e("<input/>",{size:1}).attr("size")&&e.attrFn,s=e.attr,u=e.attrHooks.value&&e.attrHooks.value.get||function(){return null},c=e.attrHooks.value&&e.attrHooks.value.set||function(){return n},l=/^(?:input|button)$/i,d=/^[238]$/,p=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,f=/^(?:checked|selected)$/i;a(e,"attrFn",i||{},"jQuery.attrFn is deprecated"),e.attr=function(t,a,o,u){var c=a.toLowerCase(),g=t&&t.nodeType;return u&&(4>s.length&&r("jQuery.fn.attr( props, pass ) is deprecated"),t&&!d.test(g)&&(i?a in i:e.isFunction(e.fn[a])))?e(t)[a](o):("type"===a&&o!==n&&l.test(t.nodeName)&&t.parentNode&&r("Can't change the 'type' of an input or button in IE 6/7/8"),!e.attrHooks[c]&&p.test(c)&&(e.attrHooks[c]={get:function(t,r){var a,o=e.prop(t,r);return o===!0||"boolean"!=typeof o&&(a=t.getAttributeNode(r))&&a.nodeValue!==!1?r.toLowerCase():n},set:function(t,n,r){var a;return n===!1?e.removeAttr(t,r):(a=e.propFix[r]||r,a in t&&(t[a]=!0),t.setAttribute(r,r.toLowerCase())),r}},f.test(c)&&r("jQuery.fn.attr('"+c+"') may use property instead of attribute")),s.call(e,t,a,o))},e.attrHooks.value={get:function(e,t){var n=(e.nodeName||"").toLowerCase();return"button"===n?u.apply(this,arguments):("input"!==n&&"option"!==n&&r("jQuery.fn.attr('value') no longer gets properties"),t in e?e.value:null)},set:function(e,t){var a=(e.nodeName||"").toLowerCase();return"button"===a?c.apply(this,arguments):("input"!==a&&"option"!==a&&r("jQuery.fn.attr('value', val) no longer sets properties"),e.value=t,n)}};var g,h,v=e.fn.init,m=e.parseJSON,y=/^(?:[^<]*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;e.fn.init=function(t,n,a){var o;return t&&"string"==typeof t&&!e.isPlainObject(n)&&(o=y.exec(t))&&o[1]&&("<"!==t.charAt(0)&&r("$(html) HTML strings must start with '<' character"),n&&n.context&&(n=n.context),e.parseHTML)?v.call(this,e.parseHTML(e.trim(t),n,!0),n,a):v.apply(this,arguments)},e.fn.init.prototype=e.fn,e.parseJSON=function(e){return e||null===e?m.apply(this,arguments):(r("jQuery.parseJSON requires a valid JSON string"),null)},e.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||0>e.indexOf("compatible")&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e.browser||(g=e.uaMatch(navigator.userAgent),h={},g.browser&&(h[g.browser]=!0,h.version=g.version),h.chrome?h.webkit=!0:h.webkit&&(h.safari=!0),e.browser=h),a(e,"browser",e.browser,"jQuery.browser is deprecated"),e.sub=function(){function t(e,n){return new t.fn.init(e,n)}e.extend(!0,t,this),t.superclass=this,t.fn=t.prototype=this(),t.fn.constructor=t,t.sub=this.sub,t.fn.init=function(r,a){return a&&a instanceof e&&!(a instanceof t)&&(a=t(a)),e.fn.init.call(this,r,a,n)},t.fn.init.prototype=t.fn;var n=t(document);return r("jQuery.sub() is deprecated"),t},e.ajaxSetup({converters:{"text json":e.parseJSON}});var b=e.fn.data;e.fn.data=function(t){var a,o,i=this[0];return!i||"events"!==t||1!==arguments.length||(a=e.data(i,t),o=e._data(i,t),a!==n&&a!==o||o===n)?b.apply(this,arguments):(r("Use of jQuery.fn.data('events') is deprecated"),o)};var j=/\/(java|ecma)script/i,w=e.fn.andSelf||e.fn.addBack;e.fn.andSelf=function(){return r("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()"),w.apply(this,arguments)},e.clean||(e.clean=function(t,a,o,i){a=a||document,a=!a.nodeType&&a[0]||a,a=a.ownerDocument||a,r("jQuery.clean() is deprecated");var s,u,c,l,d=[];if(e.merge(d,e.buildFragment(t,a).childNodes),o)for(c=function(e){return!e.type||j.test(e.type)?i?i.push(e.parentNode?e.parentNode.removeChild(e):e):o.appendChild(e):n},s=0;null!=(u=d[s]);s++)e.nodeName(u,"script")&&c(u)||(o.appendChild(u),u.getElementsByTagName!==n&&(l=e.grep(e.merge([],u.getElementsByTagName("script")),c),d.splice.apply(d,[s+1,0].concat(l)),s+=l.length));return d});var Q=e.event.add,x=e.event.remove,k=e.event.trigger,N=e.fn.toggle,C=e.fn.live,S=e.fn.die,T="ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",M=RegExp("\\b(?:"+T+")\\b"),H=/(?:^|\s)hover(\.\S+|)\b/,A=function(t){return"string"!=typeof t||e.event.special.hover?t:(H.test(t)&&r("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'"),t&&t.replace(H,"mouseenter$1 mouseleave$1"))};e.event.props&&"attrChange"!==e.event.props[0]&&e.event.props.unshift("attrChange","attrName","relatedNode","srcElement"),e.event.dispatch&&a(e.event,"handle",e.event.dispatch,"jQuery.event.handle is undocumented and deprecated"),e.event.add=function(e,t,n,a,o){e!==document&&M.test(t)&&r("AJAX events should be attached to document: "+t),Q.call(this,e,A(t||""),n,a,o)},e.event.remove=function(e,t,n,r,a){x.call(this,e,A(t)||"",n,r,a)},e.fn.error=function(){var e=Array.prototype.slice.call(arguments,0);return r("jQuery.fn.error() is deprecated"),e.splice(0,0,"error"),arguments.length?this.bind.apply(this,e):(this.triggerHandler.apply(this,e),this)},e.fn.toggle=function(t,n){if(!e.isFunction(t)||!e.isFunction(n))return N.apply(this,arguments);r("jQuery.fn.toggle(handler, handler...) is deprecated");var a=arguments,o=t.guid||e.guid++,i=0,s=function(n){var r=(e._data(this,"lastToggle"+t.guid)||0)%i;return e._data(this,"lastToggle"+t.guid,r+1),n.preventDefault(),a[r].apply(this,arguments)||!1};for(s.guid=o;a.length>i;)a[i++].guid=o;return this.click(s)},e.fn.live=function(t,n,a){return r("jQuery.fn.live() is deprecated"),C?C.apply(this,arguments):(e(this.context).on(t,this.selector,n,a),this)},e.fn.die=function(t,n){return r("jQuery.fn.die() is deprecated"),S?S.apply(this,arguments):(e(this.context).off(t,this.selector||"**",n),this)},e.event.trigger=function(e,t,n,a){return n||M.test(e)||r("Global events are undocumented and deprecated"),k.call(this,e,t,n||document,a)},e.each(T.split("|"),function(t,n){e.event.special[n]={setup:function(){var t=this;return t!==document&&(e.event.add(document,n+"."+e.guid,function(){e.event.trigger(n,null,t,!0)}),e._data(this,n,e.guid++)),!1},teardown:function(){return this!==document&&e.event.remove(document,n+"."+e._data(this,n)),!1}}})}(jQuery,window);
-//@ sourceMappingURL=dist/jquery-migrate.min.map \ No newline at end of file
diff --git a/lib/scripts/jquery/jquery.min.js b/lib/scripts/jquery/jquery.min.js
index 006e95310..686ae4bf3 100644
--- a/lib/scripts/jquery/jquery.min.js
+++ b/lib/scripts/jquery/jquery.min.js
@@ -1,5 +1,4 @@
/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
-//@ sourceMappingURL=jquery.min.map
*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
-}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window); \ No newline at end of file
+}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
diff --git a/lib/tpl/dokuwiki/detail.php b/lib/tpl/dokuwiki/detail.php
index c602830f7..ec846f6fd 100644
--- a/lib/tpl/dokuwiki/detail.php
+++ b/lib/tpl/dokuwiki/detail.php
@@ -110,26 +110,23 @@ header('X-UA-Compatible: IE=edge,chrome=1');
<ul>
<?php
$data = array();
+ $data['view'] = 'detail';
// 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));
- $data['mediaManager'] = '<li><a href="'.$mmURL.'" class="mediaManager"><span>'.$lang['img_manager'].'</span></a></li>';
+ $data['items']['mediaManager'] = '<li><a href="'.$mmURL.'" class="mediaManager"><span>'.$lang['img_manager'].'</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>';
+ $data['items']['img_backto'] = '<li><a href="'.wl($ID).'" class="back"><span>'.$lang['img_backto'].' '.$ID.'</span></a></li>';
// the page tools can be amended 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['template'] here
- $hook = 'TEMPLATE_'.strtoupper($conf['template']).'_PAGETOOLS_DISPLAY';
- $evt = new Doku_Event($hook, $data);
+ $evt = new Doku_Event('TEMPLATE_PAGETOOLS_DISPLAY', $data);
if($evt->advise_before()){
- foreach($evt->data as $k => $html) echo $html;
+ foreach($evt->data['items'] as $k => $html) echo $html;
}
$evt->advise_after();
unset($data);
diff --git a/lib/tpl/dokuwiki/main.php b/lib/tpl/dokuwiki/main.php
index f6ca4ed86..3bc46406a 100644
--- a/lib/tpl/dokuwiki/main.php
+++ b/lib/tpl/dokuwiki/main.php
@@ -75,22 +75,21 @@ $showSidebar = $hasSidebar && ($ACT=='show');
<ul>
<?php
$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>')
+ 'view' => 'main',
+ 'items' => 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 amended 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['template'] here
- $hook = 'TEMPLATE_'.strtoupper($conf['template']).'_PAGETOOLS_DISPLAY';
- $evt = new Doku_Event($hook, $data);
+ $evt = new Doku_Event('TEMPLATE_PAGETOOLS_DISPLAY', $data);
if($evt->advise_before()){
- foreach($evt->data as $k => $html) echo $html;
+ foreach($evt->data['items'] as $k => $html) echo $html;
}
$evt->advise_after();
unset($data);
diff --git a/lib/tpl/dokuwiki/style.ini b/lib/tpl/dokuwiki/style.ini
index 897b6e6da..cc23c169f 100644
--- a/lib/tpl/dokuwiki/style.ini
+++ b/lib/tpl/dokuwiki/style.ini
@@ -2,7 +2,8 @@
; for limitations of the ini format used here
; To extend this file or make changes to it, it is recommended to create
-; a style.local.ini file to prevent losing any changes after an upgrade.
+; a local conf/tpl/<template-folder-name>/style.ini file to prevent losing
+; any changes after an upgrade.
; Please don't forget to copy the section your changes should be under
; (i.e. [stylesheets] or [replacements]) into that file as well.