diff --git a/_test/tests/inc/remoteapicore.test.php b/_test/tests/inc/remoteapicore.test.php index ed7e7c606955da8638ca06f1d1aeb88aeef30a1c..a83a4eb26cc835f7204bf55e21b2b40aa80a7e24 100644 --- a/_test/tests/inc/remoteapicore.test.php +++ b/_test/tests/inc/remoteapicore.test.php @@ -5,12 +5,12 @@ */ class remoteapicore_test extends DokuWikiTest { - var $userinfo; - var $oldAuthAcl; + protected $userinfo; + protected $oldAuthAcl; /** @var RemoteAPI */ - var $remote; + protected $remote; - function setUp() { + public function setUp() { parent::setUp(); global $conf; global $USERINFO; @@ -27,7 +27,7 @@ class remoteapicore_test extends DokuWikiTest { $this->remote = new RemoteAPI(); } - function tearDown() { + public function tearDown() { global $USERINFO; global $AUTH_ACL; @@ -36,10 +36,8 @@ class remoteapicore_test extends DokuWikiTest { } - function test_core() { - $remoteApi = new RemoteApi(); - - $this->assertEquals(getVersion(), $remoteApi->call('dokuwiki.getVersion')); + public function test_core() { + $this->assertEquals(getVersion(), $this->remote->call('dokuwiki.getVersion')); // $params = array('user', 'passwrd'); // $this->assertEquals(, $remoteApi->call('dokuwiki.login')); //TODO @@ -71,7 +69,7 @@ class remoteapicore_test extends DokuWikiTest { 'skipacl' => 1 // is ignored ) ); - $this->assertEquals($expected, $remoteApi->call('dokuwiki.getPagelist', $params)); + $this->assertEquals($expected, $this->remote->call('dokuwiki.getPagelist', $params)); idx_addPage('wiki:syntax'); //full text search depends on index $expected = array( @@ -90,10 +88,10 @@ You can use up to five different levels of', ) ); $params = array('Sectioning'); - $this->assertEquals($expected, $remoteApi->call('dokuwiki.search', $params)); + $this->assertEquals($expected, $this->remote->call('dokuwiki.search', $params)); $timeexpect = time(); - $timeactual = $remoteApi->call('dokuwiki.getTime'); + $timeactual = $this->remote->call('dokuwiki.getTime'); $this->assertTrue(($timeexpect <= $timeactual) && ($timeactual <= $timeexpect + 1)); $expected = array( @@ -108,7 +106,7 @@ You can use up to five different levels of', 'unlock' => array() ) ); - $this->assertEquals($expected, $remoteApi->call('dokuwiki.setLocks', $params)); + $this->assertEquals($expected, $this->remote->call('dokuwiki.setLocks', $params)); $expected = array( 'locked' => array(), @@ -122,10 +120,10 @@ You can use up to five different levels of', 'unlock' => array('wiki:dokuwiki', 'wiki:syntax', 'nonexisting', 'nonexisting2') ) ); - $this->assertEquals($expected, $remoteApi->call('dokuwiki.setLocks', $params)); + $this->assertEquals($expected, $this->remote->call('dokuwiki.setLocks', $params)); global $conf; - $this->assertEquals($conf['title'], $remoteApi->call('dokuwiki.getTitle')); + $this->assertEquals($conf['title'], $this->remote->call('dokuwiki.getTitle')); $file3 = wikiFN('nice_page'); $content = "====Title====\nText"; @@ -137,14 +135,14 @@ You can use up to five different levels of', 'sum' => 'Summary of nice text' ) ); - $this->assertEquals(true, $remoteApi->call('wiki.putPage', $params)); //TODO check exceptions + $this->assertEquals(true, $this->remote->call('wiki.putPage', $params)); //TODO check exceptions $this->assertEquals($content, rawWiki('nice_page')); $rev[1] = filemtime(wikiFN('nice_page')); //stored for later sleep(1); // wait for new revision ID $params = array('nice_page'); - $this->assertEquals($content, $remoteApi->call('wiki.getPage', $params)); + $this->assertEquals($content, $this->remote->call('wiki.getPage', $params)); $morecontent = "\nOther text."; $secondcontent = $content . $morecontent; @@ -153,30 +151,30 @@ You can use up to five different levels of', $morecontent, array() ); - $this->assertEquals(true, $remoteApi->call('dokuwiki.appendPage', $params_append)); + $this->assertEquals(true, $this->remote->call('dokuwiki.appendPage', $params_append)); $this->assertEquals($secondcontent, rawWiki('nice_page')); $params = array('nice_page', ''); - $this->assertEquals($secondcontent, $remoteApi->call('wiki.getPageVersion', $params)); + $this->assertEquals($secondcontent, $this->remote->call('wiki.getPageVersion', $params)); $params = array('nice_page', $rev[1]); - $this->assertEquals($content, $remoteApi->call('wiki.getPageVersion', $params)); + $this->assertEquals($content, $this->remote->call('wiki.getPageVersion', $params)); $params = array('nice_page', 1234); - $this->assertEquals('', $remoteApi->call('wiki.getPageVersion', $params), 'Not existing revision'); + $this->assertEquals('', $this->remote->call('wiki.getPageVersion', $params), 'Not existing revision'); $params = array('notexisting', 1234); - $this->assertEquals('', $remoteApi->call('wiki.getPageVersion', $params), 'Not existing page'); + $this->assertEquals('', $this->remote->call('wiki.getPageVersion', $params), 'Not existing page'); $html1 = "\n<h3 class=\"sectionedit1\" id=\"title\">Title</h3>\n<div class=\"level3\">\n\n<p>\nText\n"; $html2 = "Other text.\n"; $html3 = "</p>\n\n</div>\n"; $params = array('nice_page'); - $this->assertEquals($html1 . $html2 . $html3, $remoteApi->call('wiki.getPageHTML', $params)); + $this->assertEquals($html1 . $html2 . $html3, $this->remote->call('wiki.getPageHTML', $params)); $params = array('nice_page', ''); - $this->assertEquals($html1 . $html2 . $html3, $remoteApi->call('wiki.getPageHTMLVersion', $params)); + $this->assertEquals($html1 . $html2 . $html3, $this->remote->call('wiki.getPageHTMLVersion', $params)); $params = array('nice_page', $rev[1]); - $this->assertEquals($html1 . $html3, $remoteApi->call('wiki.getPageHTMLVersion', $params)); + $this->assertEquals($html1 . $html3, $this->remote->call('wiki.getPageHTMLVersion', $params)); $params = array('nice_page', 1234); - $this->assertEquals('', $remoteApi->call('wiki.getPageHTMLVersion', $params)); + $this->assertEquals('', $this->remote->call('wiki.getPageHTMLVersion', $params)); $expected = array( array( @@ -192,10 +190,10 @@ You can use up to five different levels of', 'lastModified' => filemtime($file3) ) ); - $this->assertEquals($expected, $remoteApi->call('wiki.getAllPages')); //only indexed pages + $this->assertEquals($expected, $this->remote->call('wiki.getAllPages')); //only indexed pages $params = array('wiki:syntax'); - $this->assertEquals(ft_backlinks('wiki:syntax'), $remoteApi->call('wiki.getBackLinks', $params)); + $this->assertEquals(ft_backlinks('wiki:syntax'), $this->remote->call('wiki.getBackLinks', $params)); $expected = array( 'name' => 'nice_page', @@ -204,7 +202,7 @@ You can use up to five different levels of', 'version' => filemtime($file3) ); $params = array('nice_page'); - $this->assertEquals($expected, $remoteApi->call('wiki.getPageInfo', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getPageInfo', $params)); $expected = array( 'name' => 'nice_page', @@ -213,20 +211,20 @@ You can use up to five different levels of', 'version' => $rev[1] ); $params = array('nice_page', $rev[1]); - $this->assertEquals($expected, $remoteApi->call('wiki.getPageInfoVersion', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getPageInfoVersion', $params)); $rev[2] = filemtime(wikiFN('nice_page')); sleep(1); // wait for new revision ID - $remoteApi->call('dokuwiki.appendPage', $params_append); + $this->remote->call('dokuwiki.appendPage', $params_append); $rev[3] = filemtime(wikiFN('nice_page')); sleep(1); - $remoteApi->call('dokuwiki.appendPage', $params_append); + $this->remote->call('dokuwiki.appendPage', $params_append); $rev[4] = filemtime(wikiFN('nice_page')); sleep(1); - $remoteApi->call('dokuwiki.appendPage', $params_append); + $this->remote->call('dokuwiki.appendPage', $params_append); $rev[5] = filemtime(wikiFN('nice_page')); sleep(1); - $remoteApi->call('dokuwiki.appendPage', $params_append); + $this->remote->call('dokuwiki.appendPage', $params_append); $rev[6] = filemtime(wikiFN('nice_page')); $expected = array( @@ -240,32 +238,32 @@ You can use up to five different levels of', ) ); $params = array(strtotime("-1 year")); - $this->assertEquals($expected, $remoteApi->call('wiki.getRecentChanges', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getRecentChanges', $params)); $params = array('nice_page', 0); - $versions = $remoteApi->call('wiki.getPageVersions', $params); + $versions = $this->remote->call('wiki.getPageVersions', $params); $this->assertEquals($rev[6], $versions[0]['version']); $this->assertEquals($rev[5], $versions[1]['version']); $this->assertEquals($rev[1], $versions[5]['version']); - $this->assertEquals(6, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(6, count($this->remote->call('wiki.getPageVersions', $params))); $params = array('nice_page', 1); - $versions = $remoteApi->call('wiki.getPageVersions', $params); + $versions = $this->remote->call('wiki.getPageVersions', $params); $this->assertEquals($rev[5], $versions[0]['version']); $this->assertEquals($rev[4], $versions[1]['version']); - $this->assertEquals(5, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(5, count($this->remote->call('wiki.getPageVersions', $params))); $conf['recent'] = 3; //set number of page returned $params = array('nice_page', 1); - $this->assertEquals(3, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(3, count($this->remote->call('wiki.getPageVersions', $params))); $params = array('nice_page', $conf['recent']); - $versions = $remoteApi->call('wiki.getPageVersions', $params); + $versions = $this->remote->call('wiki.getPageVersions', $params); $this->assertEquals($rev[3], $versions[0]['version']); //skips current,1st old,2nd old - $this->assertEquals(3, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(3, count($this->remote->call('wiki.getPageVersions', $params))); $params = array('nice_page', 2 * $conf['recent']); - $this->assertEquals(0, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(0, count($this->remote->call('wiki.getPageVersions', $params))); //remove page $file3 = wikiFN('nice_page'); @@ -277,17 +275,17 @@ You can use up to five different levels of', 'minor' => false, ) ); - $this->assertEquals(true, $remoteApi->call('wiki.putPage', $params)); + $this->assertEquals(true, $this->remote->call('wiki.putPage', $params)); $this->assertFalse(file_exists($file3)); $params = array('nice_page', 0); - $this->assertEquals(2, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(2, count($this->remote->call('wiki.getPageVersions', $params))); $params = array('nice_page', 1); - $this->assertEquals(3, count($remoteApi->call('wiki.getPageVersions', $params))); + $this->assertEquals(3, count($this->remote->call('wiki.getPageVersions', $params))); $params = array('nice_page'); - $this->assertEquals(AUTH_UPLOAD, $remoteApi->call('wiki.aclCheck', $params)); + $this->assertEquals(AUTH_UPLOAD, $this->remote->call('wiki.aclCheck', $params)); global $conf; global $AUTH_ACL, $USERINFO; @@ -300,16 +298,14 @@ You can use up to five different levels of', ); $params = array('nice_page'); - $this->assertEquals(AUTH_EDIT, $remoteApi->call('wiki.aclCheck', $params)); + $this->assertEquals(AUTH_EDIT, $this->remote->call('wiki.aclCheck', $params)); - $this->assertEquals(DOKU_API_VERSION, $remoteApi->call('dokuwiki.getXMLRPCAPIVersion')); + $this->assertEquals(DOKU_API_VERSION, $this->remote->call('dokuwiki.getXMLRPCAPIVersion')); - $this->assertEquals(2, $remoteApi->call('wiki.getRPCVersionSupported')); + $this->assertEquals(2, $this->remote->call('wiki.getRPCVersionSupported')); } - function test_core2() { - $remoteApi = new RemoteApi(); - + public function test_core2() { $localdoku = array( 'type' => 'local', 'page' => 'DokuWiki', @@ -336,21 +332,19 @@ You can use up to five different levels of', $localdoku ); $params = array('mailinglist'); - $this->assertEquals($expected, $remoteApi->call('wiki.listLinks', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.listLinks', $params)); } - function test_coreattachments() { + public function test_coreattachments() { global $conf; global $AUTH_ACL, $USERINFO; - $remoteApi = new RemoteApi(); - $filecontent = io_readFile(mediaFN('wiki:dokuwiki-128.png'), false); $params = array('test:dokuwiki-128_2.png', $filecontent, array('ow' => false)); - $this->assertEquals('test:dokuwiki-128_2.png', $remoteApi->call('wiki.putAttachment', $params)); //prints a success div + $this->assertEquals('test:dokuwiki-128_2.png', $this->remote->call('wiki.putAttachment', $params)); //prints a success div $params = array('test:dokuwiki-128_2.png'); - $this->assertEquals($filecontent, $remoteApi->call('wiki.getAttachment', $params)); + $this->assertEquals($filecontent, $this->remote->call('wiki.getAttachment', $params)); $rev = filemtime(mediaFN('test:dokuwiki-128_2.png')); $expected = array( @@ -358,7 +352,7 @@ You can use up to five different levels of', 'size' => 27895, ); $params = array('test:dokuwiki-128_2.png'); - $this->assertEquals($expected, $remoteApi->call('wiki.getAttachmentInfo', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getAttachmentInfo', $params)); $params = array(strtotime("-5 year")); $expected = array( @@ -371,7 +365,7 @@ You can use up to five different levels of', 'size' => 27895 //actual size, not size change ) ); - $this->assertEquals($expected, $remoteApi->call('wiki.getRecentMediaChanges', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getRecentMediaChanges', $params)); sleep(1); $conf['useacl'] = 1; @@ -383,7 +377,7 @@ You can use up to five different levels of', ); $params = array('test:dokuwiki-128_2.png'); - $this->assertEquals(0, $remoteApi->call('wiki.deleteAttachment', $params)); + $this->assertEquals(0, $this->remote->call('wiki.deleteAttachment', $params)); $rev2 = filemtime($conf['media_changelog']); $expected = array( @@ -391,14 +385,14 @@ You can use up to five different levels of', 'size' => 0, ); $params = array('test:dokuwiki-128_2.png'); - $this->assertEquals($expected, $remoteApi->call('wiki.getAttachmentInfo', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getAttachmentInfo', $params)); $expected = array( 'lastModified' => 0, 'size' => 0, ); $params = array('test:nonexisting.png'); - $this->assertEquals($expected, $remoteApi->call('wiki.getAttachmentInfo', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getAttachmentInfo', $params)); $media1 = mediaFN('wiki:dokuwiki-128.png'); $expected = array( @@ -424,7 +418,7 @@ You can use up to five different levels of', 'pattern' => '/128/' //filter ) ); - $this->assertEquals($expected, $remoteApi->call('wiki.getAttachments', $params)); + $this->assertEquals($expected, $this->remote->call('wiki.getAttachments', $params)); } } diff --git a/_test/tests/inc/remoteapicore_aclcheck.test.php b/_test/tests/inc/remoteapicore_aclcheck.test.php new file mode 100644 index 0000000000000000000000000000000000000000..25aff331f5ed26f451495dba543b9aa96dd84baa --- /dev/null +++ b/_test/tests/inc/remoteapicore_aclcheck.test.php @@ -0,0 +1,141 @@ +<?php + +/** + * Class remoteapicore_test + */ +class remoteapicore_aclcheck_test extends DokuWikiTest { + + protected $userinfo; + protected $oldAuthAcl; + /** @var RemoteAPI */ + protected $remote; + + protected $pluginsEnabled = array('auth_plugin_authplain'); + + protected function reloadUsers() { + global $auth; + + /* auth caches data loaded from file, but recreated object forces reload */ + $auth = new auth_plugin_authplain(); + } + + public function setUp() { + global $config_cascade; + global $conf; + global $USERINFO; + global $AUTH_ACL; + + parent::setUp(); + + $name = $config_cascade['plainauth.users']['default']; + copy($name, $name . ".orig"); + $this->reloadUsers(); + + $this->oldAuthAcl = $AUTH_ACL; + $this->userinfo = $USERINFO; + + $conf['remote'] = 1; + $conf['remoteuser'] = '@user'; + $conf['useacl'] = 0; + + $this->remote = new RemoteAPI(); + + } + + public function tearDown() { + global $USERINFO; + global $AUTH_ACL; + global $config_cascade; + + parent::tearDown(); + + $USERINFO = $this->userinfo; + $AUTH_ACL = $this->oldAuthAcl; + + $name = $config_cascade['plainauth.users']['default']; + copy($name . ".orig", $name); + } + + public function test_checkacl() { + global $conf; + global $AUTH_ACL, $USERINFO; + /** @var auth_plugin_authplain $auth */ + global $auth; + + $conf['useacl'] = 1; + $_SERVER['REMOTE_USER'] = 'john'; + $USERINFO['grps'] = array('user'); + $AUTH_ACL = array( + '* @ALL 0', //none + '* @user 2', //edit + '* @more 4', //create + 'nice_page user2 8' //upload + ); + + $params = array('nice_page'); + $this->assertEquals(AUTH_EDIT, $this->remote->call('wiki.aclCheck', $params)); + + $auth->createUser("user1", "54321", "a User", "you@example.com"); + $auth->createUser("user2", "543210", "You", "he@example.com"); + $auth->createUser("mwuser", "12345", "Wiki User", "me@example.com", array('more')); //not in default group + + $params = array( + 'nice_page', + 'user1' + ); + $this->assertEquals(AUTH_EDIT, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'nice_page', + 'mwuser' // member of group 'more' + ); + $this->assertEquals(AUTH_CREATE, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'nice_page', + 'mwuser', + array() //groups not retrieved + ); + $this->assertEquals(AUTH_NONE, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'nice_page', + 'notexistinguser', + array('more') + ); + $this->assertEquals(AUTH_CREATE, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'nice_page', + 'user2' + ); + $this->assertEquals(AUTH_UPLOAD, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'nice_page', + 'user2', + array() //groups not retrieved + ); + $this->assertEquals(AUTH_UPLOAD, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'unknown_page', + 'user2' + ); + $this->assertEquals(AUTH_EDIT, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'unknown_page', + 'user2', + array() //groups not retrieved + ); + $this->assertEquals(AUTH_NONE, $this->remote->call('wiki.aclCheck', $params)); + + $params = array( + 'nice_page', + 'testuser' // superuser set via conf + ); + $this->assertEquals(AUTH_ADMIN, $this->remote->call('wiki.aclCheck', $params)); + } + +} diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index a634e6c4d89c63020617969040f970192b8e8cb6..407e63185b3ec519abcf00a6f5e23023701ca3d2 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -133,9 +133,9 @@ class RemoteAPICore { 'return' => 'array', 'Returns a struct about all recent media changes since given timestamp.' ), 'wiki.aclCheck' => array( - 'args' => array('string'), + 'args' => array('string', 'string', 'array'), 'return' => 'int', - 'doc' => 'Returns the permissions of a given wiki page.' + 'doc' => 'Returns the permissions of a given wiki page. By default, for current user/groups' ), 'wiki.putAttachment' => array( 'args' => array('string', 'file', 'array'), 'return' => 'array', @@ -604,14 +604,31 @@ class RemoteAPICore { } /** - * Returns the permissions of a given wiki page + * Returns the permissions of a given wiki page for the current user or another user * * @param string $id page id + * @param string|null $user username + * @param array|null $groups array of groups * @return int permission level */ - public function aclCheck($id) { + public function aclCheck($id, $user = null, $groups = null) { + /** @var DokuWiki_Auth_Plugin $auth */ + global $auth; + $id = $this->resolvePageId($id); - return auth_quickaclcheck($id); + if($user === null) { + return auth_quickaclcheck($id); + } else { + if($groups === null) { + $userinfo = $auth->getUserData($user); + if($userinfo === false) { + $groups = array(); + } else { + $groups = $userinfo['grps']; + } + } + return auth_aclcheck($id, $user, $groups); + } } /** diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php index f4baec9941aeca5aaad3ec70eb4ac10c05cc5403..6edc6c6215578f1557a37817527b81e9ea525bb2 100644 --- a/lib/plugins/acl/admin.php +++ b/lib/plugins/acl/admin.php @@ -649,7 +649,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { echo '</div></form>'.NL; } - /** * Returns the permission which were set for exactly the given user/group * and page/namespace. Returns null if no exact match is available diff --git a/lib/plugins/acl/remote.php b/lib/plugins/acl/remote.php index 031686f959ab1c568b3a597e6060c02eb7fe04cc..3771d475d44fab17deeeef43cc34e58907df2467 100644 --- a/lib/plugins/acl/remote.php +++ b/lib/plugins/acl/remote.php @@ -12,7 +12,12 @@ class remote_plugin_acl extends DokuWiki_Remote_Plugin { */ public function _getMethods() { return array( - 'addAcl' => array( + 'listAcls' => array( + 'args' => array(), + 'return' => 'Array of ACLs {scope, user, permission}', + 'name' => 'listAcl', + 'doc' => 'Get the list of all ACLs', + ),'addAcl' => array( 'args' => array('string','string','int'), 'return' => 'int', 'name' => 'addAcl', @@ -26,6 +31,22 @@ class remote_plugin_acl extends DokuWiki_Remote_Plugin { ); } + /** + * List all ACL config entries + * + * @throws RemoteAccessDeniedException + * @return dictionary {Scope: ACL}, where ACL = dictionnary {user/group: permissions_int} + */ + public function listAcls(){ + if(!auth_isadmin()) { + throw new RemoteAccessDeniedException('You are not allowed to access ACLs, superuser permission is required', 114); + } + /** @var admin_plugin_acl $apa */ + $apa = plugin_load('admin', 'acl'); + $apa->_init_acl_config(); + return $apa->acl; + } + /** * Add a new entry to ACL config * diff --git a/lib/plugins/authplain/_test/escaping.test.php b/lib/plugins/authplain/_test/escaping.test.php index 7139aa99b0b2bcc684588ef8c0c39f4a518a0539..a38940e1a7da22597887ba1c5d3138df1a395be0 100644 --- a/lib/plugins/authplain/_test/escaping.test.php +++ b/lib/plugins/authplain/_test/escaping.test.php @@ -103,9 +103,11 @@ class helper_plugin_authplain_escaping_test extends DokuWikiTest { $this->assertEquals($escaped, $result[2]); } } - } +/** + * Class auth_plugin_authplainharness + */ class auth_plugin_authplainharness extends auth_plugin_authplain { /** @@ -115,12 +117,16 @@ class auth_plugin_authplainharness extends auth_plugin_authplain { $this->_pregsplit_safe = $bool; } + /** + * @return bool|mixed + */ public function getPregsplit_safe(){ return $this->_pregsplit_safe; } /** * @param string $line + * @return array */ public function splitUserData($line){ return $this->_splitUserData($line);