static function getContentAction() { global $wgTitle, $haclgContLang, $haclgDisableACLTab, $wgUser; if ($wgUser->isAnon()) { return NULL; } if ($wgTitle->getNamespace() == HACL_NS_ACL) { // Display the link to article or category list($peType, $peName) = IACLDefinition::nameOfPE($wgTitle->getText()); if ($peType == IACL::PE_PAGE || $peType == IACL::PE_CATEGORY) { $title = $peType == IACL::PE_PAGE ? Title::newFromText($peName) : Title::makeTitleSafe(NS_CATEGORY, $peName); return array('class' => false, 'text' => wfMsg("hacl_tab_" . IACL::$typeToName[$peType]), 'href' => $title->getLocalUrl()); } } elseif ($wgTitle->exists()) { // Display the link to category or page SD if ($wgTitle->getNamespace() == NS_CATEGORY) { $sd = IACLDefinition::nameOfSD(IACL::PE_CATEGORY, $wgTitle); } else { $sd = IACLDefinition::nameOfSD(IACL::PE_PAGE, $wgTitle); } $etc = haclfDisableTitlePatch(); $sd = Title::newFromText($sd, HACL_NS_ACL); haclfRestoreTitlePatch($etc); // Hide ACL tab if SD does not exist and $haclgDisableACLTab is true if (!$sd || !empty($haclgDisableACLTab) && !$sd->exists() && !$wgUser->getOption('showacltab')) { return NULL; } return array('class' => $sd->exists() ? false : 'new', 'text' => wfMsg('hacl_tab_acl'), 'href' => $sd->getLocalUrl()); } return NULL; }
/** * Resolve protected element name by its ID */ public static function peNameForID($peType, $peID) { $res = NULL; $etc = haclfDisableTitlePatch(); if ($peType == IACL::PE_NAMESPACE) { $res = iaclfCanonicalNsText($peID); } elseif ($peType == IACL::PE_RIGHT || $peType == IACL::PE_CATEGORY) { $t = Title::newFromId($peID); $res = $t ? $t->getText() : NULL; } elseif ($peType == IACL::PE_USER) { $u = User::newFromId($peID); $res = $u ? $u->getName() : NULL; } elseif ($peType == IACL::PE_GROUP) { $t = Title::newFromId($peID); $res = $t ? substr($t->getText(), 6) : NULL; } elseif ($peType == IACL::PE_SPECIAL) { $name = IACLStorage::get('SpecialPage')->specialsForIds($peID); $res = reset($name); } else { $t = Title::newFromId($peID); if ($t) { // Always use canonical namespace names $res = ($t->getNamespace() ? iaclfCanonicalNsText($t->getNamespace()) . ':' : '') . $t->getText(); } } haclfRestoreTitlePatch($etc); return $res; }
/** * Returns the article ID for a given article name. This function has a special * handling for Special pages, which do not have an article ID. IntraACL stores * special IDs for these pages. Their IDs are always negative while the IDs of * normal pages are positive. * * @param string $articleName Name of the article * @param int $defaultNS The default namespace if no namespace is given in the name * @param boolean $force True to force the namespace to be $defaultNS * * @return int * ID of the article: * >0: ID of an article in a normal namespace * =0: Name of the article is invalid * <0: ID of a Special Page * */ function haclfArticleID($articleName, $defaultNS = NS_MAIN, $force = false) { $t = $articleName; if (!is_object($t)) { $etc = haclfDisableTitlePatch(); $t = $force ? Title::makeTitleSafe($defaultNS, $articleName) : Title::newFromText($articleName, $defaultNS); haclfRestoreTitlePatch($etc); } if (!$t || $t->getInterwiki()) { return 0; } if ($t->getNamespace() == NS_SPECIAL) { // Canonicalize special page titles list($base, $par) = SpecialPageFactory::resolveAlias($t->getText()); if (!$base) { // No such special page exists, just take the base text $base = $t->getBaseText(); } return -IACLStorage::get('SpecialPage')->idForSpecial($base); } $id = $t->getArticleID(); if ($id === 0) { $id = $t->getArticleID(Title::GAID_FOR_UPDATE); } return $id; }
function isFound($username, $title) { $opts = $this->authCookie($username); if (!$title instanceof Title) { $etc = haclfDisableTitlePatch(); $title = Title::newFromText($title); haclfRestoreTitlePatch($etc); } $titleText = $title->getText(); $search = preg_replace('!([/\\.\\(\\)\\!\\#\\-:])!', '', $titleText); $url = SpecialPage::getTitleFor('Search')->getFullUrl(array('search' => $search, 'limit' => 10000, 'offset' => 0, 'redirs' => 1, 'ns' . $title->getNamespace() => 1)); list($status, $content) = self::GET($url, $opts); preg_match('#<ul[^<>]*class=[\'"]?mw-search-results[^<>]*>(.*)</ul>#is', $content, $m); if ($m) { preg_match_all('#<li>(.*?)</li>#is', $m[1], $list, PREG_PATTERN_ORDER); $all = array(); if ($list[1]) { foreach ($list[1] as $link) { preg_match('#<a[^<>]*>(.*?)</a\\s*>#is', $link, $m); $link = trim(strip_tags(html_entity_decode($m[1]))); $all[] = $link; if ($link == $titleText) { return true; } } } } return false; }
function haclAutocomplete($t, $n, $limit = 11, $add_checkboxes = false, $item_prefix = false) { global $haclgContLang; if (!$limit) { $limit = 11; } $a = array(); $dbr = wfGetDB(DB_SLAVE); // Users if ($t == 'user') { $r = $dbr->select('user', 'user_name, user_real_name', array('user_name LIKE ' . $dbr->addQuotes('%' . $n . '%') . ' OR user_real_name LIKE ' . $dbr->addQuotes('%' . $n . '%')), __METHOD__, array('ORDER BY' => 'user_name', 'LIMIT' => $limit)); while ($row = $r->fetchRow()) { $a[] = array($row[1] ? $row[0] . ' (' . $row[1] . ')' : $row[0], $row[0]); } } elseif ($t == 'group') { $ip = 'hi_'; $n = str_replace(' ', '_', $n); $r = $dbr->select('page', '*', array('page_namespace' => HACL_NS_ACL, 'page_title LIKE ' . $dbr->addQuotes($haclgContLang->getPetPrefix(IACL::PE_GROUP) . '/%' . $n . '%')), __METHOD__, array('ORDER BY' => 'page_title', 'LIMIT' => $limit)); foreach ($r as $group) { // TODO filter unreadable? $n = str_replace('_', ' ', substr($group->page_title, 6)); $a[] = array($n, $n); } } elseif ($t == 'page') { $ip = 'ti_'; $n = str_replace(' ', '_', $n); $where = array(); // Check if namespace is specified within $n $etc = haclfDisableTitlePatch(); $tt = Title::newFromText($n . 'X'); if ($tt->getNamespace() != NS_MAIN) { $n = substr($tt->getDBkey(), 0, -1); $where['page_namespace'] = $tt->getNamespace(); } haclfRestoreTitlePatch($etc); // Select page titles // FIXME: ??? CAST(page_title AS CHAR CHARACTER SET utf8) $where[] = 'page_title LIKE ' . $dbr->addQuotes($n . '%'); $r = $dbr->select('page', 'page_title, page_namespace', $where, __METHOD__, array('ORDER BY' => 'page_namespace, page_title', 'LIMIT' => $limit)); while ($row = $r->fetchRow()) { $title = Title::newFromText($row[0], $row[1]); // Filter unreadable if ($title->userCan('read')) { // Use canonical titles $t = ($title->getNamespace() ? iaclfCanonicalNsText($title->getNamespace()) . ':' : '') . $title->getText(); $a[] = array($title->getPrefixedText(), $t); } } } elseif ($t == 'namespace') { $ip = 'ti_'; global $wgCanonicalNamespaceNames, $wgContLang, $haclgUnprotectableNamespaceIds; $ns = $wgCanonicalNamespaceNames; $ns[0] = 'Main'; ksort($ns); // Always unlimited $limit = count($ns) + 1; $n = mb_strtolower($n); $nl = mb_strlen($n); foreach ($ns as $k => $v) { $v = str_replace('_', ' ', $v); $name = str_replace('_', ' ', $wgContLang->getNsText($k)); if (!$name) { $name = $v; } if ($k >= 0 && (!$nl || mb_strtolower(mb_substr($v, 0, $nl)) == $n || mb_strtolower(mb_substr($name, 0, $nl)) == $n) && empty($haclgUnprotectableNamespaceIds[$k])) { $a[] = array($name, $v); } } } elseif ($t == 'category') { $ip = 'ti_'; $n = str_replace(' ', '_', $n); $where = array('page_namespace' => NS_CATEGORY, 'page_title LIKE ' . $dbr->addQuotes($n . '%')); $r = $dbr->select('page', 'page_title', $where, __METHOD__, array('ORDER BY' => 'page_title', 'LIMIT' => $limit)); while ($row = $r->fetchRow()) { $title = Title::newFromText($row[0], NS_CATEGORY); // Filter unreadable if ($title->userCan('read')) { $title = $title->getText(); $a[] = array($title, $title); } } } elseif ($t == 'sd') { $ip = 'ri_'; $n = str_replace(' ', '_', $n); $r = $dbr->select('page', '*', array('page_namespace' => HACL_NS_ACL, 'page_title NOT LIKE ' . $dbr->addQuotes($haclgContLang->getPetPrefix(IACL::PE_GROUP) . '/%'), 'page_title LIKE ' . $dbr->addQuotes('%' . $n . '%')), __METHOD__, array('ORDER BY' => 'page_title', 'LIMIT' => $limit)); foreach ($r as $sd) { // TODO filter unreadable? $n = str_replace('_', ' ', $sd->page_title); $a[] = array($n, $n); } } // No items if (!$a) { return '<div class="hacl_tt">' . wfMsg('hacl_autocomplete_no_' . $t . 's') . '</div>'; } // More than (limit-1) items => add '...' at the end of list $max = false; if (count($a) >= $limit) { array_pop($a); $max = true; } $i = 0; $html = ''; $ip = $item_prefix ? $item_prefix . '_' : 'item'; if ($add_checkboxes) { // This is used by Group Editor: display autocomplete list with checkboxes foreach ($a as $item) { $i++; $html .= '<div id="' . $ip . $i . '" class="hacl_ti" title="' . htmlspecialchars($item[1]) . '"><input style="cursor: pointer" type="checkbox" id="c' . $ip . $i . '" /> ' . htmlspecialchars($item[0]) . ' <span id="t' . $ip . $i . '"></span></div>'; } } else { // This is used by ACL Editor: simple autocomplete lists for editboxes foreach ($a as $item) { $i++; $html .= '<div id="' . $ip . $i . '" class="hacl_ti" title="' . htmlspecialchars($item[1]) . '">' . htmlspecialchars($item[0]) . '</div>'; } } if ($max) { $html .= '<div class="hacl_tt">...</div>'; } return $html; }
/** * Displays full graph of IntraACL rights using Graphviz, in SVG format. * Does not reflect the right override method - just displays which rights apply * to different protected elements. * * SD -> (namespace = page cluster) * SD -> page * SD -> category -> each subcategory -> subcluster of a namespace * Included SD -> SD */ public function html_rightgraph(&$q) { global $wgOut, $wgContLang; $patch = haclfDisableTitlePatch(); // FIXME Special pages? // Select ALL SDs $titles = array(); $defs = IACLDefinition::select(array('pe_type != ' . IACL::PE_GROUP)); $cats = array(); foreach ($defs as $def) { $titles[$def['key']] = $def['def_title']; if ($def['pe_type'] == IACL::PE_CATEGORY) { $cats[] = $def['pe_title']; } if ($def['pe_type'] == IACL::PE_CATEGORY || $def['pe_type'] == IACL::PE_PAGE) { $titles[$def['pe_id']] = $def['pe_title']; } } $cattitles = IACLStorage::get('Util')->getAllChildrenCategories($cats); $catkeys = array(); // Fetch article IDs massively using LinkBatch $batch = new LinkBatch(); foreach ($cattitles as $t) { $batch->addObj($t); } $batch->execute(); foreach ($cattitles as $t) { $titles[$t->getArticleId()] = $t; $catkeys[$t->getDBkey()] = $t->getArticleId(); } $catlinks = IACLStorage::get('Util')->getCategoryLinks(array_keys($catkeys)); // Draw security descriptors $nodes = array(); $edges = array(); $ns_first = array(); $cluster = array(); foreach ($defs as $def) { if ($def['pe_type'] != IACL::PE_PAGE) { $nodes['sd' . $def['key']] = $def; if ($def['pe_type'] == IACL::PE_CATEGORY) { $edges['sd' . $def['key']]['cat' . $def['pe_id']] = true; $nodes['cat' . $def['pe_id']] = true; $cluster['sd' . $def['key']] = "clusterns" . NS_CATEGORY; } } else { $nodes['pg' . $def['pe_id']] = true; $edges['sd' . $def['key']]['pg' . $def['pe_id']] = true; if (!isset($ns_first[$titles[$def['pe_id']]->getNamespace()])) { $ns_first[$titles[$def['pe_id']]->getNamespace()] = 'pg' . $def['pe_id']; } } } // Group pages in category clusters within namespaces $cat_cluster = array(); $cat_cluster[NS_CATEGORY][''] = array(); foreach ($catlinks as $catkey => $cattitles) { $cattitle = $titles[$catkeys[$catkey]]; $catid = $cattitle->getArticleId(); foreach ($cattitles as $t) { $tns = $t->getNamespace(); $tid = $t->getArticleId(); if ($tns == NS_CATEGORY) { $edges["cat{$catid}"]["cat{$tid}"] = true; if (!isset($nodes["cat{$tid}"])) { $nodes["cat{$tid}"] = true; } } elseif (isset($nodes["pg{$tid}"])) { if (!isset($cluster["pg{$tid}"])) { $cluster["pg{$tid}"] = 'clustercat' . $tns . '_' . $catid; if (!isset($cat_cluster[$tns][$catid])) { $cat_cluster[$tns][$catid] = array(); $edges["cat{$catid}"]["pg{$tid}"] = 'lhead=clustercat' . $tns . '_' . $catid; } } else { $edges["cat{$catid}"]["pg{$tid}"] = true; } } } } // Set namespace clusters for non-grouped nodes foreach ($nodes as $n => &$attr) { if (substr($n, 0, 2) == 'pg' && !isset($cluster[$n])) { $cluster[$n] = 'clusterns' . $titles[substr($n, 2)]->getNamespace(); } elseif (substr($n, 0, 3) == 'cat') { $cluster[$n] = 'clusterns' . NS_CATEGORY; if (!isset($ns_first[NS_CATEGORY])) { $ns_first[NS_CATEGORY] = $n; } } } unset($attr); // prevent reference bugs // Group SDs in the same clusters as their PEs and draw namespace SD edges $sdbyid = array(); foreach ($defs as $def) { if ($def['pe_type'] == IACL::PE_PAGE) { $cluster['sd' . $def['key']] = $cluster['pg' . $def['pe_id']]; $sdbyid[$def['key']] = $def; } elseif ($def['pe_type'] == IACL::PE_NAMESPACE) { $cluster['sd' . $def['key']] = ''; if (isset($ns_first[$def['pe_id']])) { $k = $ns_first[$def['pe_id']]; } else { $k = 'etc' . $def['pe_id']; $nodes[$k] = array('label' => '...', 'shape' => 'circle', 'href' => Title::newFromText('Special:Allpages')->getFullUrl(array('namespace' => $def['pe_id'])), 'tooltip' => "Click to see all pages in namespace " . $wgContLang->getNsText($def['pe_id'])); $cluster[$k] = "clusterns" . $def['pe_id']; $ns_first[$def['pe_id']] = $k; } $edges['sd' . $def['key']][$k] = "lhead=clusterns" . $def['pe_id']; } elseif ($def['pe_type'] == IACL::PE_RIGHT) { $cluster['sd' . $def['key']] = ''; } } // Draw right hierarchy $hier = array(); foreach ($defs as $def) { foreach ($def['rules'] as $rules) { foreach ($rules as $rule) { if ($rule['child_type'] != IACL::PE_USER && $rule['child_type'] != IACL::PE_GROUP && $rule['child_type'] != IACL::PE_ALL_USERS && $rule['child_type'] != IACL::PE_REG_USERS && $rule['actions'] & IACL::ACTION_INCLUDE_SD) { $parent = $rule['pe_type'] . '-' . $rule['pe_id']; // get_key $child = $rule['child_type'] . '-' . $rule['child_id']; // get_key if (isset($sdbyid[$child]) && $sdbyid[$child]['pe_type'] == IACL::PE_PAGE) { $nodes['sd' . $child] = $sdbyid[$child]; } if (isset($sdbyid[$parent]) && $sdbyid[$parent]['pe_type'] == IACL::PE_PAGE) { $nodes['sd' . $parent] = $sdbyid[$parent]; } if (isset($nodes['sd' . $child]) && isset($nodes['sd' . $parent])) { $edges['sd' . $child]['sd' . $parent] = true; } } } } } foreach ($cluster as $k => $cl) { if (isset($nodes[$k])) { if (preg_match('/clustercat(\\d+)_(\\d+)/', $cl, $m)) { $cat_cluster[$m[1]][$m[2]][] = $k; } elseif (preg_match('/clusterns(\\d+)/', $cl, $m)) { $cat_cluster[$m[1]][''][] = $k; } elseif ($cl === '') { $cat_cluster[''][''][] = $k; } } } // Set node attributes $shapes = array('sd' => 'note', 'pg' => 'ellipse', 'cat' => 'folder'); $colors = array('sd' . IACL::PE_PAGE => '#ffd0d0', 'sd' . IACL::PE_CATEGORY => '#ffff80', 'sd' . IACL::PE_RIGHT => '#90ff90', 'sd' . IACL::PE_NAMESPACE => '#c0c0ff', 'cat' => '#ffe0c0'); foreach ($nodes as $n => $r) { if (is_array($r)) { continue; } preg_match('/([a-z]+)(\\d+(?:-\\d+)?)/', $n, $m); $type = $m[1]; $id = $m[2]; $nodes[$n] = array('shape' => $shapes[$type], 'label' => $titles[$id]->getPrefixedText(), 'href' => $titles[$id]->getFullUrl()); if ($type != 'pg') { $type2 = $type; if ($type2 == 'sd') { $type2 .= $r['pe_type']; } if (isset($colors[$type2])) { $nodes[$n]['fillcolor'] = $colors[$type2]; } $nodes[$n]['style'] = 'filled'; } } if ($nodes) { // Draw clusters $graph = ''; $ns_first[''] = ''; foreach ($ns_first as $ns => $first) { if ($ns !== '') { $graph .= "subgraph clusterns{$ns} {\n"; $graph .= "graph [label=\"Namespace " . ($ns ? $wgContLang->getNsText($ns) : 'Main') . "\", href=\"" . Title::newFromText('Special:Allpages')->getFullUrl(array('namespace' => $ns)) . "\"];\n"; } if (isset($cat_cluster[$ns])) { foreach ($cat_cluster[$ns] as $cat => $ks) { if ($cat !== '') { $graph .= "subgraph clustercat{$ns}_{$cat} {\n"; $graph .= 'graph [label="' . $titles[$cat]->getPrefixedText() . '", href="' . $titles[$cat]->getFullUrl() . '"];' . "\n"; } foreach ($ks as $nodename) { $graph .= "\"{$nodename}\" [" . self::attrstring($nodes[$nodename]) . "];\n"; } if ($cat !== '') { $graph .= "}\n"; } } } if ($ns !== '') { $graph .= "}\n"; } } // Draw edges foreach ($edges as $from => $to) { if (isset($nodes[$from])) { foreach ($to as $id => $attr) { if ($attr !== true) { $attr .= ', '; } else { $attr = ''; } $attr .= self::attrstring(array('href' => $nodes[$from]['href'], 'tooltip' => $nodes[$from]['label'])); $graph .= "\"{$from}\" -> \"{$id}\" [{$attr}];\n"; } } } // Render the graph $graph = "<graphviz>\ndigraph G {\nedge [penwidth=2 color=blue];\nsplines=polyline;\n" . "overlap=false;\nranksep=2;\nrankdir=LR;\ncompound=true;\n{$graph}\n}\n</graphviz>\n"; $wgOut->addWikiText($graph); $wgOut->addHTML("<pre>{$graph}</pre>"); } else { $wgOut->addWikiText(wfMsg('hacl_acllist_empty')); } haclfRestoreTitlePatch($patch); }
protected static function checkProtectPageRight($pageID, $userID) { $etc = haclfDisableTitlePatch(); $title = Title::newFromId($pageID); haclfRestoreTitlePatch($etc); return IACLDefinition::userCan($userID, IACL::PE_NAMESPACE, $title->getNamespace(), IACL::ACTION_PROTECT_PAGES) > 0 || IACLDefinition::userCan($userID, IACL::PE_CATEGORY, IACLStorage::get('Util')->getParentCategoryIDs($pageID), IACL::ACTION_PROTECT_PAGES) > 0; }
/** * Checks if the current user can perform the given $action on the articles with * the given $titleNames. * * @param string $titleName * Comma separated list of article names * @param string $action * Name of the action * * @return bool * A JSON encoded array of results: * array( * array(titlename, allowed or not: true/false), * ... * ) */ function smwf_om_userCanMultiple($titleNames, $action) { // Special handling if the extension HaloACL is present global $wgUser; $titleNames = split(',', $titleNames); if (defined('HACL_HALOACL_VERSION')) { $etc = haclfDisableTitlePatch(); } $results = array(); foreach ($titleNames as $t) { $result = true; $title = Title::newFromText(trim($t)); wfRunHooks('userCan', array($title, $wgUser, $action, &$result)); if (isset($result) && $result == false) { $results[] = array($t, "false"); } else { $results[] = array($t, "true"); } } if (defined('HACL_HALOACL_VERSION')) { haclfRestoreTitlePatch($etc); } return json_encode($results); }