1<?php 2 3use dokuwiki\Extension\SyntaxPlugin; 4 5/** 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Andreas Gohr <andi@splitbrain.org> 8 */ 9class syntax_plugin_aclinfo extends SyntaxPlugin 10{ 11 /** @inheritdoc */ 12 public function getType() 13 { 14 return 'substition'; 15 } 16 17 /** @inheritdoc */ 18 public function getPType() 19 { 20 return 'block'; 21 } 22 23 /** @inheritdoc */ 24 public function getSort() 25 { 26 return 155; 27 } 28 29 /** @inheritdoc */ 30 public function connectTo($mode) 31 { 32 $this->Lexer->addSpecialPattern('~~ACLINFO!?[^~]*?~~', $mode, 'plugin_aclinfo'); 33 } 34 35 /** @inheritdoc */ 36 public function handle($match, $state, $pos, Doku_Handler $handler) 37 { 38 $match = substr($match, 10, -2); 39 return [$match]; 40 } 41 42 /** @inheritdoc */ 43 public function render($format, Doku_Renderer $R, $data) 44 { 45 global $INFO; 46 if ($format != 'xhtml') return false; 47 48 if (!$data[0]) { 49 $page = $INFO['id']; 50 } else { 51 $page = $data[0]; 52 } 53 54 $perms = $this->aclCheck($page); 55 $R->doc .= '<div class="plugin_aclinfo">'; 56 $R->listu_open(); 57 foreach ($perms as $who => $p) { 58 $R->listitem_open(1); 59 $R->listcontent_open(); 60 $R->cdata(sprintf($this->getLang('perm' . $p), urldecode($who))); 61 $R->listcontent_close(); 62 $R->listitem_close(); 63 } 64 $R->listu_close(); 65 $R->doc .= '</div>'; 66 return true; 67 } 68 69 /** 70 * Parse the ACL setup and return the permissions for the given page ID. 71 * 72 * @param string $id The page ID to check 73 * @return array 74 */ 75 protected function aclCheck($id) 76 { 77 global $AUTH_ACL; 78 79 $id = cleanID($id); 80 $ns = getNS($id); 81 $perms = []; 82 83 //check exact match first 84 $matches = preg_grep('/^' . preg_quote($id, '/') . '\s+/', $AUTH_ACL); 85 $perms = array_merge($perms, $this->processAclMatches($matches)); 86 87 //still here? do the namespace checks 88 if ($ns) { 89 $path = $ns . ':\*'; 90 } else { 91 $path = '\*'; //root document 92 } 93 94 do { 95 $matches = preg_grep('/^' . $path . '\s+/', $AUTH_ACL); 96 $perms = array_merge($perms, $this->processAclMatches($matches)); 97 98 //get next higher namespace 99 $ns = getNS($ns); 100 101 if ($path != '\*') { 102 $path = $ns . ':\*'; 103 if ($path == ':\*') $path = '\*'; 104 } else { 105 //we did this already 106 //break here 107 break; 108 } 109 } while (1); //this should never loop endless 110 111 return $perms; 112 } 113 114 /** 115 * Process ACL matches and return parsed permissions. 116 * 117 * @param array $matches Array of ACL lines to process 118 * @return array Parsed permissions array 119 */ 120 protected function processAclMatches(array $matches) 121 { 122 $perms = []; 123 foreach ($matches as $match) { 124 $match = preg_replace('/#.*$/', '', $match); //ignore comments 125 $acl = preg_split('/\s+/', $match); 126 if ($acl[2] > AUTH_DELETE) $acl[2] = AUTH_DELETE; //no admins in the ACL! 127 if (!isset($perms[$acl[1]])) $perms[$acl[1]] = $acl[2]; 128 } 129 return $perms; 130 } 131} 132