/** * Create event for tools menues * * @author Anika Henke <*****@*****.**> */ function _tpl_toolsevent($toolsname, $items, $view = 'main') { $data = array('view' => $view, 'items' => $items); $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY'; $evt = new Doku_Event($hook, $data); if ($evt->advise_before()) { foreach ($evt->data['items'] as $k => $html) { echo $html; } } $evt->advise_after(); }
/** * Wraps an event around the parent function * * @triggers HTTPCLIENT_REQUEST_SEND * @author Andreas Gohr <*****@*****.**> */ function sendRequest($url, $data = '', $method = 'GET') { $httpdata = array('url' => $url, 'data' => $data, 'method' => $method); $evt = new Doku_Event('HTTPCLIENT_REQUEST_SEND', $httpdata); if ($evt->advise_before()) { $url = $httpdata['url']; $data = $httpdata['data']; $method = $httpdata['method']; } $evt->advise_after(); unset($evt); return parent::sendRequest($url, $data, $method); }
/** * copied to core (available since Detritus) */ function white_toolsevent($toolsname, $items, $view = 'main') { $data = array('view' => $view, 'items' => $items); $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY'; $evt = new Doku_Event($hook, $data); if ($evt->advise_before()) { $actions = array('export_pdf'); foreach ($evt->data['items'] as $k => $html) { if (in_array($k, $actions)) { $html = str_replace(' ' . $k, ' plugin_' . $k, $html); } echo $html; } } $evt->advise_after(); }
/** * Prepares and prints an JavaScript array with all toolbar buttons * * @emits TOOLBAR_DEFINE * @param string $varname Name of the JS variable to fill * @author Andreas Gohr <*****@*****.**> */ function toolbar_JSdefines($varname) { global $lang; $menu = array(); $evt = new Doku_Event('TOOLBAR_DEFINE', $menu); if ($evt->advise_before()) { // build button array $menu = array_merge($menu, array(array('type' => 'format', 'title' => $lang['qb_bold'], 'icon' => 'bold.png', 'key' => 'b', 'open' => '**', 'close' => '**', 'block' => false), array('type' => 'format', 'title' => $lang['qb_italic'], 'icon' => 'italic.png', 'key' => 'i', 'open' => '//', 'close' => '//', 'block' => false), array('type' => 'format', 'title' => $lang['qb_underl'], 'icon' => 'underline.png', 'key' => 'u', 'open' => '__', 'close' => '__', 'block' => false), array('type' => 'format', 'title' => $lang['qb_code'], 'icon' => 'mono.png', 'key' => 'c', 'open' => "''", 'close' => "''", 'block' => false), array('type' => 'format', 'title' => $lang['qb_strike'], 'icon' => 'strike.png', 'key' => 'd', 'open' => '<del>', 'close' => '</del>', 'block' => false), array('type' => 'autohead', 'title' => $lang['qb_hequal'], 'icon' => 'hequal.png', 'key' => '8', 'text' => $lang['qb_h'], 'mod' => 0, 'block' => true), array('type' => 'autohead', 'title' => $lang['qb_hminus'], 'icon' => 'hminus.png', 'key' => '9', 'text' => $lang['qb_h'], 'mod' => 1, 'block' => true), array('type' => 'autohead', 'title' => $lang['qb_hplus'], 'icon' => 'hplus.png', 'key' => '0', 'text' => $lang['qb_h'], 'mod' => -1, 'block' => true), array('type' => 'picker', 'title' => $lang['qb_hs'], 'icon' => 'h.png', 'class' => 'pk_hl', 'list' => array(array('type' => 'format', 'title' => $lang['qb_h1'], 'icon' => 'h1.png', 'key' => '1', 'open' => '====== ', 'close' => ' ======\\n'), array('type' => 'format', 'title' => $lang['qb_h2'], 'icon' => 'h2.png', 'key' => '2', 'open' => '===== ', 'close' => ' =====\\n'), array('type' => 'format', 'title' => $lang['qb_h3'], 'icon' => 'h3.png', 'key' => '3', 'open' => '==== ', 'close' => ' ====\\n'), array('type' => 'format', 'title' => $lang['qb_h4'], 'icon' => 'h4.png', 'key' => '4', 'open' => '=== ', 'close' => ' ===\\n'), array('type' => 'format', 'title' => $lang['qb_h5'], 'icon' => 'h5.png', 'key' => '5', 'open' => '== ', 'close' => ' ==\\n')), 'block' => true), array('type' => 'linkwiz', 'title' => $lang['qb_link'], 'icon' => 'link.png', 'key' => 'l', 'open' => '[[', 'close' => ']]', 'block' => false), array('type' => 'format', 'title' => $lang['qb_extlink'], 'icon' => 'linkextern.png', 'open' => '[[', 'close' => ']]', 'sample' => 'http://example.com|' . $lang['qb_extlink'], 'block' => false), array('type' => 'formatln', 'title' => $lang['qb_ol'], 'icon' => 'ol.png', 'open' => ' - ', 'close' => '', 'key' => '-', 'block' => true), array('type' => 'formatln', 'title' => $lang['qb_ul'], 'icon' => 'ul.png', 'open' => ' * ', 'close' => '', 'key' => '.', 'block' => true), array('type' => 'insert', 'title' => $lang['qb_hr'], 'icon' => 'hr.png', 'insert' => '\\n----\\n', 'block' => true), array('type' => 'mediapopup', 'title' => $lang['qb_media'], 'icon' => 'image.png', 'url' => 'lib/exe/mediamanager.php?ns=', 'name' => 'mediaselect', 'options' => 'width=750,height=500,left=20,top=20,scrollbars=yes,resizable=yes', 'block' => false), array('type' => 'picker', 'title' => $lang['qb_smileys'], 'icon' => 'smiley.png', 'list' => getSmileys(), 'icobase' => 'smileys', 'block' => false), array('type' => 'picker', 'title' => $lang['qb_chars'], 'icon' => 'chars.png', 'list' => explode(' ', 'À à Á á  â à ã Ä ä Ǎ ǎ Ă ă Å å Ā ā Ą ą Æ æ Ć ć Ç ç Č č Ĉ ĉ Ċ ċ Ð đ ð Ď ď È è É é Ê ê Ë ë Ě ě Ē ē Ė ė Ę ę Ģ ģ Ĝ ĝ Ğ ğ Ġ ġ Ĥ ĥ Ì ì Í í Î î Ï ï Ǐ ǐ Ī ī İ ı Į į Ĵ ĵ Ķ ķ Ĺ ĺ Ļ ļ Ľ ľ Ł ł Ŀ ŀ Ń ń Ñ ñ Ņ ņ Ň ň Ò ò Ó ó Ô ô Õ õ Ö ö Ǒ ǒ Ō ō Ő ő Œ œ Ø ø Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ş ş Š š Ŝ ŝ Ţ ţ Ť ť Ù ù Ú ú Û û Ü ü Ǔ ǔ Ŭ ŭ Ū ū Ů ů ǖ ǘ ǚ ǜ Ų ų Ű ű Ŵ ŵ Ý ý Ÿ ÿ Ŷ ŷ Ź ź Ž ž Ż ż Þ þ ß Ħ ħ ¿ ¡ ¢ £ ¤ ¥ € ¦ § ª ¬ ¯ ° ± ÷ ‰ ¼ ½ ¾ ¹ ² ³ µ ¶ † ‡ · • º ∀ ∂ ∃ Ə ə ∅ ∇ ∈ ∉ ∋ ∏ ∑ ‾ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ ⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ◊ ℘ ℑ ℜ ℵ ♠ ♣ ♥ ♦ α β Γ γ Δ δ ε ζ η Θ θ ι κ Λ λ μ Ξ ξ Π π ρ Σ σ Τ τ υ Φ φ χ Ψ ψ Ω ω ★ ☆ ☎ ☚ ☛ ☜ ☝ ☞ ☟ ☹ ☺ ✔ ✘ × „ “ ” ‚ ‘ ’ « » ‹ › — – … ← ↑ → ↓ ↔ ⇐ ⇑ ⇒ ⇓ ⇔ © ™ ® ′ ″ [ ] { } ~ ( ) % § $ # | @'), 'block' => false), array('type' => 'signature', 'title' => $lang['qb_sig'], 'icon' => 'sig.png', 'key' => 'y', 'block' => false))); } // end event TOOLBAR_DEFINE default action $evt->advise_after(); unset($evt); // use JSON to build the JavaScript array $json = new JSON(); print "var {$varname} = " . $json->encode($menu) . ";\n"; }
/** * Triggers before preview xhtml render, * allows plugins to metadata render on the preview. */ public function _preview_before(&$event, $param) { global $ACT; global $TEXT; global $SUF; global $PRE; global $ID; global $METADATA_RENDERERS; if ($ACT == 'preview') { $triples =& plugin_load('helper', 'strata_triples'); $triples->beginPreview(); $text = $PRE . $TEXT . $SUF; $orig = p_read_metadata($ID); // store the original metadata in the global $METADATA_RENDERERS so p_set_metadata can use it $METADATA_RENDERERS[$ID] =& $orig; // add an extra key for the event - to tell event handlers the page whose metadata this is $orig['page'] = $ID; $evt = new Doku_Event('STRATA_PREVIEW_METADATA_RENDER', $orig); if ($evt->advise_before()) { // get instructions $instructions = p_get_instructions($text); if (is_null($instructions)) { unset($METADATA_RENDERERS[$ID]); return null; // something went wrong with the instructions } // set up the renderer $renderer = new renderer_plugin_strata(); $renderer->meta =& $orig['current']; $renderer->persistent =& $orig['persistent']; // loop through the instructions foreach ($instructions as $instruction) { // execute the callback against the renderer call_user_func_array(array(&$renderer, $instruction[0]), (array) $instruction[1]); } $evt->result = array('current' => &$renderer->meta, 'persistent' => &$renderer->persistent); } $evt->advise_after(); // clean up unset($METADATA_RENDERERS[$id]); } }
/** * Add recent changed pages to a feed object * * @author Andreas Gohr <*****@*****.**> * @param object $rss - the FeedCreator Object * @param array $data - the items to add * @param array $opt - the feed options */ function rss_buildItems(&$rss, &$data, $opt) { global $conf; global $lang; global $auth; $eventData = array('rss' => &$rss, 'data' => &$data, 'opt' => &$opt); $event = new Doku_Event('FEED_DATA_PROCESS', $eventData); if ($event->advise_before(false)) { foreach ($data as $ditem) { if (!is_array($ditem)) { // not an array? then only a list of IDs was given $ditem = array('id' => $ditem); } $item = new FeedItem(); $id = $ditem['id']; $meta = p_get_metadata($id); // add date if ($ditem['date']) { $date = $ditem['date']; } elseif ($meta['date']['modified']) { $date = $meta['date']['modified']; } else { $date = @filemtime(wikiFN($id)); } if ($date) { $item->date = date('r', $date); } // add title if ($conf['useheading'] && $meta['title']) { $item->title = $meta['title']; } else { $item->title = $ditem['id']; } if ($conf['rss_show_summary'] && !empty($ditem['sum'])) { $item->title .= ' - ' . strip_tags($ditem['sum']); } // add item link switch ($opt['link_to']) { case 'page': $item->link = wl($id, 'rev=' . $date, true, '&'); break; case 'rev': $item->link = wl($id, 'do=revisions&rev=' . $date, true, '&'); break; case 'current': $item->link = wl($id, '', true, '&'); break; case 'diff': default: $item->link = wl($id, 'rev=' . $date . '&do=diff', true, '&'); } // add item content switch ($opt['item_content']) { case 'diff': case 'htmldiff': require_once DOKU_INC . 'inc/DifferenceEngine.php'; $revs = getRevisions($id, 0, 1); $rev = $revs[0]; if ($rev) { $df = new Diff(explode("\n", htmlspecialchars(rawWiki($id, $rev))), explode("\n", htmlspecialchars(rawWiki($id, '')))); } else { $df = new Diff(array(''), explode("\n", htmlspecialchars(rawWiki($id, '')))); } if ($opt['item_content'] == 'htmldiff') { $tdf = new TableDiffFormatter(); $content = '<table>'; $content .= '<tr><th colspan="2" width="50%">' . $rev . '</th>'; $content .= '<th colspan="2" width="50%">' . $lang['current'] . '</th></tr>'; $content .= $tdf->format($df); $content .= '</table>'; } else { $udf = new UnifiedDiffFormatter(); $content = "<pre>\n" . $udf->format($df) . "\n</pre>"; } break; case 'html': $content = p_wiki_xhtml($id, $date, false); // no TOC in feeds $content = preg_replace('/(<!-- TOC START -->).*(<!-- TOC END -->)/s', '', $content); // make URLs work when canonical is not set, regexp instead of rerendering! if (!$conf['canonical']) { $base = preg_quote(DOKU_REL, '/'); $content = preg_replace('/(<a href|<img src)="(' . $base . ')/s', '$1="' . DOKU_URL, $content); } break; case 'abstract': default: $content = $meta['description']['abstract']; } $item->description = $content; //FIXME a plugin hook here could be senseful // add user # FIXME should the user be pulled from metadata as well? $user = null; $user = @$ditem['user']; // the @ spares time repeating lookup $item->author = ''; if ($user && $conf['useacl'] && $auth) { $userInfo = $auth->getUserData($user); $item->author = $userInfo['name']; if ($userInfo && !$opt['guardmail']) { $item->authorEmail = $userInfo['mail']; } else { //cannot obfuscate because some RSS readers may check validity $item->authorEmail = $user . '@' . $ditem['ip']; } } elseif ($user) { // this happens when no ACL but some Apache auth is used $item->author = $user; $item->authorEmail = $user . '@' . $ditem['ip']; } else { $item->authorEmail = 'anonymous@' . $ditem['ip']; } // add category if ($meta['subject']) { $item->category = $meta['subject']; } else { $cat = getNS($id); if ($cat) { $item->category = $cat; } } // 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(); }
/** * Handles media file deletions * * If configured, checks for media references before deletion * * @author Andreas Gohr <*****@*****.**> * @return mixed false on error, true on delete or array with refs */ function media_delete($id, $auth) { if ($auth < AUTH_DELETE) { return false; } if (!checkSecurityToken()) { return false; } global $conf; global $lang; $file = mediaFN($id); // trigger an event - MEDIA_DELETE_FILE $data['id'] = $id; $data['name'] = basename($file); $data['path'] = $file; $data['size'] = @file_exists($file) ? filesize($file) : 0; $data['unl'] = false; $data['del'] = false; $evt = new Doku_Event('MEDIA_DELETE_FILE', $data); if ($evt->advise_before()) { $data['unl'] = @unlink($file); if ($data['unl']) { addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE); $data['del'] = io_sweepNS($id, 'mediadir'); } } $evt->advise_after(); unset($evt); if ($data['unl'] && $data['del']) { // current namespace was removed. redirecting to root ns passing msg along send_redirect(DOKU_URL . 'lib/exe/mediamanager.php?msg1=' . rawurlencode(sprintf(noNS($id), $lang['deletesucc']))); } return $data['unl']; }
/** * Creates a snippet extract * * @author Andreas Gohr <*****@*****.**> * @triggers FULLTEXT_SNIPPET_CREATE */ function ft_snippet($id, $highlight) { $text = rawWiki($id); $text = str_replace("", '', $text); // remove soft-hyphens $evdata = array('id' => $id, 'text' => &$text, 'highlight' => &$highlight, 'snippet' => ''); $evt = new Doku_Event('FULLTEXT_SNIPPET_CREATE', $evdata); if ($evt->advise_before()) { $match = array(); $snippets = array(); $utf8_offset = $offset = $end = 0; $len = utf8_strlen($text); // build a regexp from the phrases to highlight $re1 = '(' . join('|', array_map('ft_snippet_re_preprocess', array_map('preg_quote_cb', array_filter((array) $highlight)))) . ')'; $re2 = "{$re1}.{0,75}(?!\\1){$re1}"; $re3 = "{$re1}.{0,45}(?!\\1){$re1}.{0,45}(?!\\1)(?!\\2){$re1}"; for ($cnt = 4; $cnt--;) { if (0) { } else { if (preg_match('/' . $re3 . '/iu', $text, $match, PREG_OFFSET_CAPTURE, $offset)) { } else { if (preg_match('/' . $re2 . '/iu', $text, $match, PREG_OFFSET_CAPTURE, $offset)) { } else { if (preg_match('/' . $re1 . '/iu', $text, $match, PREG_OFFSET_CAPTURE, $offset)) { } else { break; } } } } list($str, $idx) = $match[0]; // convert $idx (a byte offset) into a utf8 character offset $utf8_idx = utf8_strlen(substr($text, 0, $idx)); $utf8_len = utf8_strlen($str); // establish context, 100 bytes surrounding the match string // first look to see if we can go 100 either side, // then drop to 50 adding any excess if the other side can't go to 50, $pre = min($utf8_idx - $utf8_offset, 100); $post = min($len - $utf8_idx - $utf8_len, 100); if ($pre > 50 && $post > 50) { $pre = $post = 50; } else { if ($pre > 50) { $pre = min($pre, 100 - $post); } else { if ($post > 50) { $post = min($post, 100 - $pre); } else { // both are less than 50, means the context is the whole string // make it so and break out of this loop - there is no need for the // complex snippet calculations $snippets = array($text); break; } } } // establish context start and end points, try to append to previous // context if possible $start = $utf8_idx - $pre; $append = $start < $end ? $end : false; // still the end of the previous context snippet $end = $utf8_idx + $utf8_len + $post; // now set it to the end of this context if ($append) { $snippets[count($snippets) - 1] .= utf8_substr($text, $append, $end - $append); } else { $snippets[] = utf8_substr($text, $start, $end - $start); } // set $offset for next match attempt // substract strlen to avoid splitting a potential search success, // this is an approximation as the search pattern may match strings // of varying length and it will fail if the context snippet // boundary breaks a matching string longer than the current match $utf8_offset = $utf8_idx + $post; $offset = $idx + strlen(utf8_substr($text, $utf8_idx, $post)); $offset = utf8_correctIdx($text, $offset); } $m = ""; $snippets = preg_replace('/' . $re1 . '/iu', $m . '$1' . $m, $snippets); $snippet = preg_replace('/' . $m . '([^' . $m . ']*?)' . $m . '/iu', '<strong class="search_hit">$1</strong>', hsc(join('... ', $snippets))); $evdata['snippet'] = $snippet; } $evt->advise_after(); unset($evt); return $evdata['snippet']; }
function tpl_content_core() { global $ACT; global $TEXT; global $PRE; global $SUF; global $SUM; global $IDX; switch ($ACT) { case 'show': html_show(); break; case 'preview': html_edit($TEXT); html_show($TEXT); break; case 'recover': html_edit($TEXT); break; case 'edit': html_edit(); break; case 'draft': html_draft(); break; case 'wordblock': html_edit($TEXT, 'wordblock'); break; case 'search': html_search(); break; case 'revisions': $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0; html_revisions($first); break; case 'diff': html_diff(); break; case 'recent': if (is_array($_REQUEST['first'])) { $_REQUEST['first'] = array_keys($_REQUEST['first']); $_REQUEST['first'] = $_REQUEST['first'][0]; } $first = is_numeric($_REQUEST['first']) ? intval($_REQUEST['first']) : 0; html_recent($first); break; case 'index': html_index($IDX); #FIXME can this be pulled from globals? is it sanitized correctly? break; case 'backlink': html_backlinks(); break; case 'conflict': html_conflict(con($PRE, $TEXT, $SUF), $SUM); html_diff(con($PRE, $TEXT, $SUF), false); break; case 'locked': html_locked(); html_edit(); break; case 'login': html_login(); break; case 'register': html_register(); break; case 'resendpwd': html_resendpwd(); break; case 'denied': print p_locale_xhtml('denied'); break; case 'profile': html_updateprofile(); break; case 'admin': tpl_admin(); break; default: $evt = new Doku_Event('TPL_ACT_UNKNOWN', $ACT); if ($evt->advise_before()) { msg("Failed to handle command: " . hsc($ACT), -1); } $evt->advise_after(); unset($evt); return false; } return true; }
/** * Split a page into words * * Returns an array of word counts, false if an error occurred. * Array is keyed on the word length, then the word index. * * @author Andreas Gohr <*****@*****.**> * @author Christopher Smith <*****@*****.**> */ function idx_getPageWords($page) { global $conf; $swfile = DOKU_INC . 'inc/lang/' . $conf['lang'] . '/stopwords.txt'; if (@file_exists($swfile)) { $stopwords = file($swfile); } else { $stopwords = array(); } $body = ''; $data = array($page, $body); $evt = new Doku_Event('INDEXER_PAGE_ADD', $data); if ($evt->advise_before()) { $data[1] .= rawWiki($page); } $evt->advise_after(); unset($evt); list($page, $body) = $data; $body = strtr($body, "\r\n\t", ' '); $tokens = explode(' ', $body); $tokens = array_count_values($tokens); // count the frequency of each token // ensure the deaccented or romanised page names of internal links are added to the token array // (this is necessary for the backlink function -- there maybe a better way!) if ($conf['deaccent']) { $links = p_get_metadata($page, 'relation references'); if (!empty($links)) { $tmp = join(' ', array_keys($links)); // make a single string $tmp = strtr($tmp, ':', ' '); // replace namespace separator with a space $link_tokens = array_unique(explode(' ', $tmp)); // break into tokens foreach ($link_tokens as $link_token) { if (isset($tokens[$link_token])) { continue; } $tokens[$link_token] = 1; } } } $words = array(); foreach ($tokens as $word => $count) { $arr = idx_tokenizer($word, $stopwords); $arr = array_count_values($arr); foreach ($arr as $w => $c) { $l = wordlen($w); if (isset($words[$l])) { $words[$l][$w] = $c * $count + (isset($words[$l][$w]) ? $words[$l][$w] : 0); } else { $words[$l] = array($w => $c * $count); } } } // arrive here with $words = array(wordlen => array(word => frequency)) $index = array(); //resulting index foreach (array_keys($words) as $wlen) { $word_idx = idx_getIndex('w', $wlen); foreach ($words[$wlen] as $word => $freq) { $wid = array_search("{$word}\n", $word_idx); if (!is_int($wid)) { $wid = count($word_idx); $word_idx[] = "{$word}\n"; } if (!isset($index[$wlen])) { $index[$wlen] = array(); } $index[$wlen][$wid] = $freq; } // save back word index if (!idx_saveIndex('w', $wlen, $word_idx)) { trigger_error("Failed to write word index", E_USER_ERROR); return false; } } return $index; }
/** * renders the metadata of a page * * @author Esther Brunner <*****@*****.**> */ function p_render_metadata($id, $orig) { // make sure the correct ID is in global ID global $ID, $METADATA_RENDERERS; // avoid recursive rendering processes for the same id if (isset($METADATA_RENDERERS[$id])) { return $orig; } // store the original metadata in the global $METADATA_RENDERERS so p_set_metadata can use it $METADATA_RENDERERS[$id] =& $orig; $keep = $ID; $ID = $id; // add an extra key for the event - to tell event handlers the page whose metadata this is $orig['page'] = $id; $evt = new Doku_Event('PARSER_METADATA_RENDER', $orig); if ($evt->advise_before()) { require_once DOKU_INC . "inc/parser/metadata.php"; // get instructions $instructions = p_cached_instructions(wikiFN($id), false, $id); if (is_null($instructions)) { $ID = $keep; unset($METADATA_RENDERERS[$id]); return null; // something went wrong with the instructions } // set up the renderer $renderer = new Doku_Renderer_metadata(); $renderer->meta =& $orig['current']; $renderer->persistent =& $orig['persistent']; // loop through the instructions foreach ($instructions as $instruction) { // execute the callback against the renderer call_user_func_array(array(&$renderer, $instruction[0]), (array) $instruction[1]); } $evt->result = array('current' => &$renderer->meta, 'persistent' => &$renderer->persistent); } $evt->advise_after(); // clean up $ID = $keep; unset($METADATA_RENDERERS[$id]); return $evt->result; }
/** * Call the needed action handlers * * @author Andreas Gohr <*****@*****.**> * @triggers ACTION_ACT_PREPROCESS * @triggers ACTION_HEADERS_SEND */ function act_dispatch() { global $INFO; global $ACT; global $ID; global $QUERY; global $lang; global $conf; global $license; $preact = $ACT; // give plugins an opportunity to process the action $evt = new Doku_Event('ACTION_ACT_PREPROCESS', $ACT); if ($evt->advise_before()) { //sanitize $ACT $ACT = act_clean($ACT); //check if searchword was given - else just show $s = cleanID($QUERY); if ($ACT == 'search' && empty($s)) { $ACT = 'show'; } //login stuff if (in_array($ACT, array('login', 'logout'))) { $ACT = act_auth($ACT); } //check if user is asking to (un)subscribe a page if ($ACT == 'subscribe') { try { $ACT = act_subscription($ACT); } catch (Exception $e) { msg($e->getMessage(), -1); } } //check permissions $ACT = act_permcheck($ACT); //register $nil = array(); if ($ACT == 'register' && $_POST['save'] && register()) { $ACT = 'login'; } if ($ACT == 'resendpwd' && act_resendpwd()) { $ACT = 'login'; } //update user profile if ($ACT == 'profile') { if (!$_SERVER['REMOTE_USER']) { $ACT = 'login'; } else { if (updateprofile()) { msg($lang['profchanged'], 1); $ACT = 'show'; } } } //revert if ($ACT == 'revert') { if (checkSecurityToken()) { $ACT = act_revert($ACT); } else { $ACT = 'show'; } } //save if ($ACT == 'save') { if (checkSecurityToken()) { $ACT = act_save($ACT); } else { $ACT = 'show'; } } //cancel conflicting edit if ($ACT == 'cancel') { $ACT = 'show'; } //draft deletion if ($ACT == 'draftdel') { $ACT = act_draftdel($ACT); } //draft saving on preview if ($ACT == 'preview') { $ACT = act_draftsave($ACT); } //edit if (($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']) { $ACT = act_edit($ACT); } else { unlock($ID); //try to unlock } //handle export if (substr($ACT, 0, 7) == 'export_') { $ACT = act_export($ACT); } //display some infos if ($ACT == 'check') { check(); $ACT = 'show'; } //handle admin tasks if ($ACT == 'admin') { // retrieve admin plugin name from $_REQUEST['page'] if (!empty($_REQUEST['page'])) { $pluginlist = plugin_list('admin'); if (in_array($_REQUEST['page'], $pluginlist)) { // attempt to load the plugin if (($plugin =& plugin_load('admin', $_REQUEST['page'])) !== null) { $plugin->handle(); } } } } // check permissions again - the action may have changed $ACT = act_permcheck($ACT); } // end event ACTION_ACT_PREPROCESS default action $evt->advise_after(); unset($evt); // when action 'show', the intial not 'show' and POST, do a redirect if ($ACT == 'show' && $preact != 'show' && strtolower($_SERVER['REQUEST_METHOD']) == 'post') { act_redirect($ID, $preact); } //call template FIXME: all needed vars available? $headers[] = 'Content-Type: text/html; charset=utf-8'; trigger_event('ACTION_HEADERS_SEND', $headers, 'act_sendheaders'); include template('main.php'); // output for the commands is now handled in inc/templates.php // in function tpl_content() }
/** * Create a pronouncable password * * The $foruser variable might be used by plugins to run additional password * policy checks, but is not used by the default implementation * * @author Andreas Gohr <*****@*****.**> * @link http://www.phpbuilder.com/annotate/message.php3?id=1014451 * @triggers AUTH_PASSWORD_GENERATE * * @param string $foruser username for which the password is generated * @return string pronouncable password */ function auth_pwgen($foruser = '') { $data = array('password' => '', 'foruser' => $foruser); $evt = new Doku_Event('AUTH_PASSWORD_GENERATE', $data); if ($evt->advise_before(true)) { $c = 'bcdfghjklmnprstvwz'; //consonants except hard to speak ones $v = 'aeiou'; //vowels $a = $c . $v; //both $s = '!$%&?+*~#-_:.;,'; // specials //use thre syllables... for ($i = 0; $i < 3; $i++) { $data['password'] .= $c[auth_random(0, strlen($c) - 1)]; $data['password'] .= $v[auth_random(0, strlen($v) - 1)]; $data['password'] .= $a[auth_random(0, strlen($a) - 1)]; } //... and add a nice number and special $data['password'] .= auth_random(10, 99) . $s[auth_random(0, strlen($s) - 1)]; } $evt->advise_after(); return $data['password']; }
/** * Create event for tools menues, adapted from core to enable adding Fontawesome icons before echo * * @author Anika Henke <*****@*****.**> * @param string $toolsname name of menu * @param array $items * @param string $view e.g. 'main', 'detail', ... */ function _mixture_toolsevent($toolsname, $items, $context) { $data = array('view' => 'main', 'items' => $items); // Events triggered are: TEMPLATE_NAVTOOLS_DISPLAY, TEMPLATE_PAGETOOLS_DISPLAY, TEMPLATE_USERTOOLS_DISPLAY, TEMPLATE_SITETOOLS_DISPLAY $hook = 'TEMPLATE_' . strtoupper(str_replace("_", "", $toolsname)) . '_DISPLAY'; $evt = new Doku_Event($hook, $data); if ($evt->advise_before()) { foreach ($evt->data['items'] as $k => $html) { $parts = explode('">', $html); // Adding proper Fonteawesome icons to plugins' page tools if (strpos($html, 'addtobook') !== false) { $html = '<li><a href="/doku.php?id=' . $ID . '&do=addtobook" class="action addtobook" rel="nofollow" title="Ajouter au livre"><h1><i class="fa fa-file-pdf-o"></i></h1>Ajouter au livre</a></li>'; $html = $parts[0] . '"><i class="fa fa-file-pdf-o"></i>' . _mixture_menuitem_string($parts[1], $context); } elseif (strpos($html, 'export_pdf') !== false) { $html = $parts[0] . '">' . _mixture_glyph('export_pdf', false) . _mixture_menuitem_string($parts[1], $context); } elseif (strpos($html, 'export_odt') !== false) { $html = $parts[0] . '">' . _mixture_glyph('export_odt', false) . _mixture_menuitem_string($parts[1], $context); } elseif (strpos($html, 'plugin_move_page') !== false) { $tooltip = str_replace("<span>", "", $parts[2]); $tooltip = str_replace("</span></a></li>", "", $tooltip); $link = '<a href="" class="action rename" rel="nofollow" title="' . $tooltip . '">'; $parts[0] = '<li class="plugin_move_page"'; $html = $parts[0] . '>' . $link . _mixture_glyph('rename', false) . _mixture_menuitem_string($parts[2], $context); } $html = str_replace('class="action', 'class="' . $toolsname . ' action', $html); if ($context == "fixed") { $html = str_replace('class=\'fa', 'class=\'fa fa-fw', $html); } echo $html; } } $evt->advise_after(); }
/** * Create event for tools menues * * @author Anika Henke <*****@*****.**> * @author Giuseppe Di Terlizzi <*****@*****.**> * * @param string $toolsname name of menu * @param array $items * @param string $view e.g. 'main', 'detail', ... * @param boolean $return * @return string */ function bootstrap3_toolsevent($toolsname, $items, $view = 'main', $return = false) { $output = ''; $data = array('view' => $view, 'items' => $items); $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY'; $evt = new Doku_Event($hook, $data); $search = array('<span>', '</span>'); if ($evt->advise_before()) { foreach ($evt->data['items'] as $k => $html) { switch ($k) { case 'export_odt': $icon = 'file-text'; break; case 'export_pdf': $icon = 'file-pdf-o'; break; case 'plugin_move': $icon = 'i-cursor text-muted'; $html = preg_replace('/<a href=""><span>(.*?)<\\/span>/', '<a href="" title="$1"><span>$1</span></a>', $html); break; default: $icon = 'puzzle-piece'; // Unknown } $replace = array('<i class="fa fa-fw fa-' . $icon . '"></i> ', ''); $html = str_replace($search, $replace, $html); $output .= $html; } } $evt->advise_after(); if ($return) { return $output; } echo $output; }
/** * List all files found by the search request * * @author Tobias Sarnowski <*****@*****.**> * @author Andreas Gohr <*****@*****.**> * @author Kate Arzamastseva <*****@*****.**> * @triggers MEDIA_SEARCH */ function media_searchlist($query, $ns, $auth = null, $fullscreen = false, $sort = 'natural') { global $conf; global $lang; $ns = cleanID($ns); if ($query) { $evdata = array('ns' => $ns, 'data' => array(), 'query' => $query); $evt = new Doku_Event('MEDIA_SEARCH', $evdata); if ($evt->advise_before()) { $dir = utf8_encodeFN(str_replace(':', '/', $evdata['ns'])); $pattern = '/' . preg_quote($evdata['query'], '/') . '/i'; search($evdata['data'], $conf['mediadir'], 'search_media', array('showmsg' => false, 'pattern' => $pattern), $dir, 1, $sort); } $evt->advise_after(); unset($evt); } if (!$fullscreen) { echo '<h1 id="media__ns">' . sprintf($lang['searchmedia_in'], hsc($ns) . ':*') . '</h1>' . NL; media_searchform($ns, $query); } if (!count($evdata['data'])) { echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; } else { if ($fullscreen) { echo '<ul class="' . _media_get_list_type() . '">'; } foreach ($evdata['data'] as $item) { if (!$fullscreen) { media_printfile($item, $item['perm'], '', true); } else { media_printfile_thumbs($item, $item['perm'], false, true); } } if ($fullscreen) { echo '</ul>' . NL; } } }
function ping($sourceUri, $targetUri) { // Plugin not enabled? Quit if (plugin_isdisabled('linkback')) { return new IXR_Error(PINGBACK_ERROR_TARGETURI_CANNOT_BE_USED, ''); } // pingback disabled? Quit if (!$this->tools->getConf('enable_pingback')) { return new IXR_Error(PINGBACK_ERROR_TARGETURI_CANNOT_BE_USED, ''); } // Given URLs are no urls? Quit if (!preg_match("#^([a-z0-9\\-\\.+]+?)://.*#i", $sourceUri)) { return new IXR_Error(PINGBACK_ERROR_GENERIC, ''); } if (!preg_match("#^([a-z0-9\\-\\.+]+?)://.*#i", $targetUri)) { return new IXR_Error(PINGBACK_ERROR_GENERIC, ''); } // Source URL does not exist? Quit $page = $this->tools->getPage($sourceUri); if (!$page['success'] && ($page['status'] < 200 || $page['status'] >= 300)) { return new IXR_Error(PINGBACK_ERROR_SOURCEURI_DOES_NOT_EXIST, ''); } // Target URL does not match with request? Quit $ID = substr($_SERVER['PATH_INFO'], 1); if ($targetUri != wl($ID, '', true)) { return new IXR_Error(PINGBACK_ERROR_GENERIC, ''); } $file = metaFN($ID, '.linkbacks'); $data = array('send' => false, 'receive' => false, 'display' => false, 'sentpings' => array(), 'receivedpings' => array(), 'number' => 0); if (@file_exists($file)) { $data = unserialize(io_readFile($file, false)); } // Target URL is not pingback enabled? Quit if (!$data['receive']) { return new IXR_Error(PINGBACK_ERROR_TARGETURI_CANNOT_BE_USED, ''); } // Pingback already done? Quit if ($data['receivedpings'][md5($sourceUri)]) { return new IXR_Error(PINGBACK_ERROR_PINGBACK_ALREADY_MADE, ''); } // Retrieve data from source $linkback = $this->_getTrackbackData($sourceUri, $targetUri, $page); // Source URL does not contain link to target? Quit if (!$linkback) { return new IXR_Error(PINGBACK_ERROR_SOURCEURI_DOES_NOT_CONTAIN_LINK, ''); } // Prepare event for Antispam plugins $evt_data = array('linkback' => $linkback, 'page' => $page, 'target' => $targetUri, 'show' => true, 'log' => array(date('Y/m/d H:i', time()) . ': Received pingback from ' . $linkback['url'] . ' (' . $linkback['lid'] . ')')); $event = new Doku_Event('ACTION_LINKBACK_RECEIVED', $evt_data); if ($event->advise_before()) { $linkback['show'] = $evt_data['show']; if ($this->tools->getConf('usefavicon')) { $linkback['favicon'] = $this->tools->getFavicon($linkback['url'], $page['body']); } // add pingback $data['receivedpings'][$linkback['lid']] = $linkback; if ($linkback['show']) { $data['number']++; } io_saveFile($file, serialize($data)); $this->tools->addLogEntry($linkback['received'], $ID, 'cl', '', $linkback['lid']); $this->tools->notify($ID, $linkback); if ($this->tools->getConf('log_processing')) { $this->tools->addProcessLogEntry($evt_data['log']); } $event->advise_after(); } else { // Pingback was denied if ($this->tools->getConf('log_processing')) { $this->tools->addProcessLogEntry($evt_data['log']); } $event->advise_after(); return new IXR_Error(PINGBACK_ERROR_ACCESS_DENIED, $helper->getLang('error_noreason')); } }
/** * Add recent changed pages to a feed object * * @author Andreas Gohr <*****@*****.**> * @param FeedCreator $rss the FeedCreator Object * @param array $data the items to add * @param array $opt the feed options */ function rss_buildItems(&$rss, &$data, $opt) { global $conf; global $lang; /* @var auth_basic $auth */ global $auth; $eventData = array('rss' => &$rss, 'data' => &$data, 'opt' => &$opt); $event = new Doku_Event('FEED_DATA_PROCESS', $eventData); if ($event->advise_before(false)) { foreach ($data as $ditem) { if (!is_array($ditem)) { // not an array? then only a list of IDs was given $ditem = array('id' => $ditem); } $item = new FeedItem(); $id = $ditem['id']; if (!$ditem['media']) { $meta = p_get_metadata($id); } else { $meta = array(); } // add date if ($ditem['date']) { $date = $ditem['date']; } elseif ($ditem['media']) { $date = @filemtime(mediaFN($id)); } elseif (@file_exists(wikiFN($id))) { $date = @filemtime(wikiFN($id)); } elseif ($meta['date']['modified']) { $date = $meta['date']['modified']; } else { $date = 0; } if ($date) { $item->date = date('r', $date); } // add title if ($conf['useheading'] && $meta['title']) { $item->title = $meta['title']; } else { $item->title = $ditem['id']; } if ($conf['rss_show_summary'] && !empty($ditem['sum'])) { $item->title .= ' - ' . strip_tags($ditem['sum']); } // add item link switch ($opt['link_to']) { case 'page': if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id), 'rev' => $date), '&', true); } else { $item->link = wl($id, 'rev=' . $date, true, '&'); } break; case 'rev': if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id), 'rev' => $date, 'tab_details' => 'history'), '&', true); } else { $item->link = wl($id, 'do=revisions&rev=' . $date, true, '&'); } break; case 'current': if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id)), '&', true); } else { $item->link = wl($id, '', true, '&'); } break; case 'diff': default: if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id), 'rev' => $date, 'tab_details' => 'history', 'mediado' => 'diff'), '&', true); } else { $item->link = wl($id, 'rev=' . $date . '&do=diff', true, '&'); } } // add item content switch ($opt['item_content']) { case 'diff': case 'htmldiff': if ($ditem['media']) { $revs = getRevisions($id, 0, 1, 8192, true); $rev = $revs[0]; $src_r = ''; $src_l = ''; if ($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)), 300)) { $more = 'w=' . $size[0] . '&h=' . $size[1] . 't=' . @filemtime(mediaFN($id)); $src_r = ml($id, $more); } if ($rev && ($size = media_image_preview_size($id, $rev, new JpegMeta(mediaFN($id, $rev)), 300))) { $more = 'rev=' . $rev . '&w=' . $size[0] . '&h=' . $size[1]; $src_l = ml($id, $more); } $content = ''; if ($src_r) { $content = '<table>'; $content .= '<tr><th width="50%">' . $rev . '</th>'; $content .= '<th width="50%">' . $lang['current'] . '</th></tr>'; $content .= '<tr align="center"><td><img src="' . $src_l . '" alt="" /></td><td>'; $content .= '<img src="' . $src_r . '" alt="' . $id . '" /></td></tr>'; $content .= '</table>'; } } else { require_once DOKU_INC . 'inc/DifferenceEngine.php'; $revs = getRevisions($id, 0, 1); $rev = $revs[0]; if ($rev) { $df = new Diff(explode("\n", rawWiki($id, $rev)), explode("\n", rawWiki($id, ''))); } else { $df = new Diff(array(''), explode("\n", rawWiki($id, ''))); } if ($opt['item_content'] == 'htmldiff') { // note: no need to escape diff output, TableDiffFormatter provides 'safe' html $tdf = new TableDiffFormatter(); $content = '<table>'; $content .= '<tr><th colspan="2" width="50%">' . $rev . '</th>'; $content .= '<th colspan="2" width="50%">' . $lang['current'] . '</th></tr>'; $content .= $tdf->format($df); $content .= '</table>'; } else { // note: diff output must be escaped, UnifiedDiffFormatter provides plain text $udf = new UnifiedDiffFormatter(); $content = "<pre>\n" . hsc($udf->format($df)) . "\n</pre>"; } } break; case 'html': if ($ditem['media']) { if ($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)))) { $more = 'w=' . $size[0] . '&h=' . $size[1] . 't=' . @filemtime(mediaFN($id)); $src = ml($id, $more); $content = '<img src="' . $src . '" alt="' . $id . '" />'; } else { $content = ''; } } else { if (@filemtime(wikiFN($id)) === $date) { $content = p_wiki_xhtml($id, '', false); } else { $content = p_wiki_xhtml($id, $date, false); } // no TOC in feeds $content = preg_replace('/(<!-- TOC START -->).*(<!-- TOC END -->)/s', '', $content); // add alignment for images $content = preg_replace('/(<img .*?class="medialeft")/s', '\\1 align="left"', $content); $content = preg_replace('/(<img .*?class="mediaright")/s', '\\1 align="right"', $content); // make URLs work when canonical is not set, regexp instead of rerendering! if (!$conf['canonical']) { $base = preg_quote(DOKU_REL, '/'); $content = preg_replace('/(<a href|<img src)="(' . $base . ')/s', '$1="' . DOKU_URL, $content); } } break; case 'abstract': default: if ($ditem['media']) { if ($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)))) { $more = 'w=' . $size[0] . '&h=' . $size[1] . 't=' . @filemtime(mediaFN($id)); $src = ml($id, $more); $content = '<img src="' . $src . '" alt="' . $id . '" />'; } else { $content = ''; } } else { $content = $meta['description']['abstract']; } } $item->description = $content; //FIXME a plugin hook here could be senseful // add user # FIXME should the user be pulled from metadata as well? $user = @$ditem['user']; // the @ spares time repeating lookup $item->author = ''; if ($user && $conf['useacl'] && $auth) { $userInfo = $auth->getUserData($user); if ($userInfo) { switch ($conf['showuseras']) { case 'username': $item->author = $userInfo['name']; break; default: $item->author = $user; break; } } else { $item->author = $user; } if ($userInfo && !$opt['guardmail']) { $item->authorEmail = $userInfo['mail']; } else { //cannot obfuscate because some RSS readers may check validity $item->authorEmail = $user . '@' . $ditem['ip']; } } elseif ($user) { // this happens when no ACL but some Apache auth is used $item->author = $user; $item->authorEmail = $user . '@' . $ditem['ip']; } else { $item->authorEmail = 'anonymous@' . $ditem['ip']; } // add category if (isset($meta['subject'])) { $item->category = $meta['subject']; } else { $cat = getNS($id); if ($cat) { $item->category = $cat; } } // 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(); }
/** * Handler to prepare matched data for the rendering process * * @param string $match The text matched by the patterns * @param int $state The lexer state for the match * @param int $pos The character position of the matched text * @param Doku_Handler $handler The Doku_Handler object * @return bool|array Return an array with all data you want to use in render, false don't add an instruction */ public function handle($match, $state, $pos, Doku_Handler $handler) { $match = substr($match, 6, -7); // remove form wrap $lines = explode("\n", $match); $actions = $rawactions = array(); $thanks = ''; $labels = ''; // parse the lines into an command/argument array $cmds = array(); while (count($lines) > 0) { $line = trim(array_shift($lines)); if (!$line) { continue; } $args = $this->_parse_line($line, $lines); $args[0] = $this->_sanitizeClassName($args[0]); if (in_array($args[0], array('action', 'thanks', 'labels'))) { if (count($args) < 2) { msg(sprintf($this->getLang('e_missingargs'), hsc($args[0]), hsc($args[1])), -1); continue; } // is action element? if ($args[0] == 'action') { array_shift($args); $rawactions[] = array('type' => array_shift($args), 'argv' => $args); continue; } // is thank you text? if ($args[0] == 'thanks') { $thanks = $args[1]; continue; } // is labels? if ($args[0] == 'labels') { $labels = $args[1]; continue; } } if (strpos($args[0], '_') === false) { $name = 'bureaucracy_field' . $args[0]; } else { //name convention: plugin_componentname $name = $args[0]; } /** @var helper_plugin_bureaucracy_field $field */ $field = $this->loadHelper($name, false); if ($field && is_a($field, 'helper_plugin_bureaucracy_field')) { $field->initialize($args); $cmds[] = $field; } else { $evdata = array('fields' => &$cmds, 'args' => $args); $event = new Doku_Event('PLUGIN_BUREAUCRACY_FIELD_UNKNOWN', $evdata); if ($event->advise_before()) { msg(sprintf($this->getLang('e_unknowntype'), hsc($name)), -1); } } } // check if action is available foreach ($rawactions as $action) { $action['type'] = $this->_sanitizeClassName($action['type']); if (strpos($action['type'], '_') === false) { $action['actionname'] = 'bureaucracy_action' . $action['type']; } else { //name convention for other plugins: plugin_componentname $action['actionname'] = $action['type']; } list($plugin, $component) = explode('_', $action['actionname']); $alternativename = $action['type'] . '_' . $action['type']; // bureaucracy_action<name> or <plugin>_<componentname> if (!plugin_isdisabled($action['actionname']) || @file_exists(DOKU_PLUGIN . $plugin . '/helper/' . $component . '.php')) { $actions[] = $action; // shortcut for other plugins with component name <name>_<name> } elseif (plugin_isdisabled($alternativename) || !@file_exists(DOKU_PLUGIN . $action['type'] . '/helper/' . $action['type'] . '.php')) { $action['actionname'] = $alternativename; $actions[] = $action; // not found } else { $evdata = array('actions' => &$actions, 'action' => $action); $event = new Doku_Event('PLUGIN_BUREAUCRACY_ACTION_UNKNOWN', $evdata); if ($event->advise_before()) { msg(sprintf($this->getLang('e_unknownaction'), hsc($action['actionname'])), -1); } } } // action(s) found? if (count($actions) < 1) { msg($this->getLang('e_noaction'), -1); } // set thank you message if (!$thanks) { $thanks = ""; foreach ($actions as $action) { $thanks .= $this->getLang($action['type'] . '_thanks'); } } else { $thanks = hsc($thanks); } return array('fields' => $cmds, 'actions' => $actions, 'thanks' => $thanks, 'labels' => $labels); }
/** * Trigger the AUTH_USERDATA_CHANGE event and call the modification function. [ DO NOT OVERRIDE ] * * You should use this function instead of calling createUser, modifyUser or * deleteUsers directly. The event handlers can prevent the modification, for * example for enforcing a user name schema. * * @author Gabriel Birke <*****@*****.**> * @param string $type Modification type ('create', 'modify', 'delete') * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. The content of this array depends on the modification type * @return mixed Result from the modification function or false if an event handler has canceled the action */ function triggerUserMod($type, $params) { $validTypes = array('create' => 'createUser', 'modify' => 'modifyUser', 'delete' => 'deleteUsers'); if (empty($validTypes[$type])) { return false; } $eventdata = array('type' => $type, 'params' => $params, 'modification_result' => null); $evt = new Doku_Event('AUTH_USER_CHANGE', $eventdata); if ($evt->advise_before(true)) { $result = call_user_func_array(array($this, $validTypes[$type]), $params); $evt->data['modification_result'] = $result; } $evt->advise_after(); unset($evt); return $result; }
/** * Returns the pagetemplate contents for the ID's namespace * * @triggers COMMON_PAGETPL_LOAD * @author Andreas Gohr <*****@*****.**> */ function pageTemplate($id) { global $conf; if (is_array($id)) { $id = $id[0]; } // prepare initial event data $data = array('id' => $id, 'tpl' => '', 'tplfile' => '', 'doreplace' => true); $evt = new Doku_Event('COMMON_PAGETPL_LOAD', $data); if ($evt->advise_before(true)) { // the before event might have loaded the content already if (empty($data['tpl'])) { // if the before event did not set a template file, try to find one if (empty($data['tplfile'])) { $path = dirname(wikiFN($id)); if (@file_exists($path . '/_template.txt')) { $data['tplfile'] = $path . '/_template.txt'; } else { // search upper namespaces for templates $len = strlen(rtrim($conf['datadir'], '/')); while (strlen($path) >= $len) { if (@file_exists($path . '/__template.txt')) { $data['tplfile'] = $path . '/__template.txt'; break; } $path = substr($path, 0, strrpos($path, '/')); } } } // load the content $data['tpl'] = io_readFile($data['tplfile']); } if ($data['doreplace']) { parsePageTemplate($data); } } $evt->advise_after(); unset($evt); return $data['tpl']; }
/** * Pings search engines with the sitemap url. Plugins can add or remove * urls to ping using the SITEMAP_PING event. * * @author Michael Hamann */ public function pingSearchEngines() { //ping search engines... $http = new DokuHTTPClient(); $http->timeout = 8; $encoded_sitemap_url = urlencode(wl('', array('do' => 'sitemap'), true, '&')); $ping_urls = array('google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap=' . $encoded_sitemap_url, 'yahoo' => 'http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=dokuwiki&url=' . $encoded_sitemap_url, 'microsoft' => 'http://www.bing.com/webmaster/ping.aspx?siteMap=' . $encoded_sitemap_url); $data = array('ping_urls' => $ping_urls, 'encoded_sitemap_url' => $encoded_sitemap_url); $event = new Doku_Event('SITEMAP_PING', $data); if ($event->advise_before(true)) { foreach ($data['ping_urls'] as $name => $url) { dbglog("Sitemapper::PingSearchEngines(): pinging {$name}"); $resp = $http->get($url); if ($http->error) { dbglog("Sitemapper:pingSearchengines(): {$http->error}"); } dbglog('Sitemapper:pingSearchengines(): ' . preg_replace('/[\\n\\r]/', ' ', strip_tags($resp))); } } $event->advise_after(); return true; }
/** * Split the text into words for fulltext search * * TODO: does this also need &$stopwords ? * * @triggers INDEXER_TEXT_PREPARE * This event allows plugins to modify the text before it gets tokenized. * Plugins intercepting this event should also intercept INDEX_VERSION_GET * * @param string $text plain text * @param boolean $wc are wildcards allowed? * @return array list of words in the text * @author Tom N Harris <*****@*****.**> * @author Andreas Gohr <*****@*****.**> */ public function tokenizer($text, $wc = false) { $wc = $wc ? '' : '\\*'; $stopwords =& idx_get_stopwords(); // prepare the text to be tokenized $evt = new Doku_Event('INDEXER_TEXT_PREPARE', $text); if ($evt->advise_before(true)) { if (preg_match('/[^0-9A-Za-z ]/u', $text)) { // handle asian chars as single words (may fail on older PHP version) $asia = @preg_replace('/(' . IDX_ASIAN . ')/u', ' \\1 ', $text); if (!is_null($asia)) { $text = $asia; } // recover from regexp falure } } $evt->advise_after(); unset($evt); $text = strtr($text, array("\r" => ' ', "\n" => ' ', "\t" => ' ', "" => '')); if (preg_match('/[^0-9A-Za-z ]/u', $text)) { $text = utf8_stripspecials($text, ' ', '\\._\\-:' . $wc); } $wordlist = explode(' ', $text); foreach ($wordlist as $i => $word) { $wordlist[$i] = preg_match('/[^0-9A-Za-z]/u', $word) ? utf8_strtolower($word) : strtolower($word); } foreach ($wordlist as $i => $word) { if (!is_numeric($word) && strlen($word) < IDX_MINWORDLENGTH || array_search($word, $stopwords, true) !== false) { unset($wordlist[$i]); } } return array_values($wordlist); }
/** * Call the needed action handlers * * @author Andreas Gohr <*****@*****.**> * @triggers ACTION_ACT_PREPROCESS * @triggers ACTION_HEADERS_SEND */ function act_dispatch() { global $ACT; global $ID; global $INFO; global $QUERY; /* @var Input $INPUT */ global $INPUT; global $lang; global $conf; $preact = $ACT; // give plugins an opportunity to process the action $evt = new Doku_Event('ACTION_ACT_PREPROCESS', $ACT); $headers = array(); if ($evt->advise_before()) { //sanitize $ACT $ACT = act_validate($ACT); //check if searchword was given - else just show $s = cleanID($QUERY); if ($ACT == 'search' && empty($s)) { $ACT = 'show'; } //login stuff if (in_array($ACT, array('login', 'logout'))) { $ACT = act_auth($ACT); } //check if user is asking to (un)subscribe a page if ($ACT == 'subscribe') { try { $ACT = act_subscription($ACT); } catch (Exception $e) { msg($e->getMessage(), -1); } } //display some info if ($ACT == 'check') { check(); $ACT = 'show'; } //check permissions $ACT = act_permcheck($ACT); //sitemap if ($ACT == 'sitemap') { act_sitemap($ACT); } //recent changes if ($ACT == 'recent') { $show_changes = $INPUT->str('show_changes'); if (!empty($show_changes)) { set_doku_pref('show_changes', $show_changes); } } //diff if ($ACT == 'diff') { $difftype = $INPUT->str('difftype'); if (!empty($difftype)) { set_doku_pref('difftype', $difftype); } } //register if ($ACT == 'register' && $INPUT->post->bool('save') && register()) { $ACT = 'login'; } if ($ACT == 'resendpwd' && act_resendpwd()) { $ACT = 'login'; } // user profile changes if (in_array($ACT, array('profile', 'profile_delete'))) { if (!$INPUT->server->str('REMOTE_USER')) { $ACT = 'login'; } else { switch ($ACT) { case 'profile': if (updateprofile()) { msg($lang['profchanged'], 1); $ACT = 'show'; } break; case 'profile_delete': if (auth_deleteprofile()) { msg($lang['profdeleted'], 1); $ACT = 'show'; } else { $ACT = 'profile'; } break; } } } //revert if ($ACT == 'revert') { if (checkSecurityToken()) { $ACT = act_revert($ACT); } else { $ACT = 'show'; } } //save if ($ACT == 'save') { if (checkSecurityToken()) { $ACT = act_save($ACT); } else { $ACT = 'preview'; } } //cancel conflicting edit if ($ACT == 'cancel') { $ACT = 'show'; } //draft deletion if ($ACT == 'draftdel') { $ACT = act_draftdel($ACT); } //draft saving on preview if ($ACT == 'preview') { $headers[] = "X-XSS-Protection: 0"; $ACT = act_draftsave($ACT); } //edit if (in_array($ACT, array('edit', 'preview', 'recover'))) { $ACT = act_edit($ACT); } else { unlock($ID); //try to unlock } //handle export if (substr($ACT, 0, 7) == 'export_') { $ACT = act_export($ACT); } //handle admin tasks if ($ACT == 'admin') { // retrieve admin plugin name from $_REQUEST['page'] if (($page = $INPUT->str('page', '', true)) != '') { /** @var $plugin DokuWiki_Admin_Plugin */ if ($plugin = plugin_getRequestAdminPlugin()) { $plugin->handle(); } } } // check permissions again - the action may have changed $ACT = act_permcheck($ACT); } // end event ACTION_ACT_PREPROCESS default action $evt->advise_after(); // Make sure plugs can handle 'denied' if ($conf['send404'] && $ACT == 'denied') { http_status(403); } unset($evt); // when action 'show', the intial not 'show' and POST, do a redirect if ($ACT == 'show' && $preact != 'show' && strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post') { act_redirect($ID, $preact); } global $INFO; global $conf; global $license; //call template FIXME: all needed vars available? $headers[] = 'Content-Type: text/html; charset=utf-8'; trigger_event('ACTION_HEADERS_SEND', $headers, 'act_sendheaders'); include template('main.php'); // output for the commands is now handled in inc/templates.php // in function tpl_content() }
/** * prints the "main content" in the mediamanger popup * * Depending on the user's actions this may be a list of * files in a namespace, the meta editing dialog or * a message of referencing pages * * Only allowed in mediamanager.php * * @triggers MEDIAMANAGER_CONTENT_OUTPUT * @param bool $fromajax - set true when calling this function via ajax * @author Andreas Gohr <*****@*****.**> */ function tpl_mediaContent($fromajax = false) { global $IMG; global $AUTH; global $INUSE; global $NS; global $JUMPTO; global $INPUT; $do = $INPUT->extract('do')->str('do'); if (in_array($do, array('save', 'cancel'))) { $do = ''; } if (!$do) { if ($INPUT->bool('edit')) { $do = 'metaform'; } elseif (is_array($INUSE)) { $do = 'filesinuse'; } else { $do = 'filelist'; } } // output the content pane, wrapped in an event. if (!$fromajax) { ptln('<div id="media__content">'); } $data = array('do' => $do); $evt = new Doku_Event('MEDIAMANAGER_CONTENT_OUTPUT', $data); if ($evt->advise_before()) { $do = $data['do']; if ($do == 'filesinuse') { media_filesinuse($INUSE, $IMG); } elseif ($do == 'filelist') { media_filelist($NS, $AUTH, $JUMPTO); } elseif ($do == 'searchlist') { media_searchlist($INPUT->str('q'), $NS, $AUTH); } else { msg('Unknown action ' . hsc($do), -1); } } $evt->advise_after(); unset($evt); if (!$fromajax) { ptln('</div>'); } }
/** * Send the mail * * Call this after all data was set * * @triggers MAIL_MESSAGE_SEND * @return bool true if the mail was successfully passed to the MTA */ public function send() { $success = false; // prepare hook data $data = array('mail' => $this, 'to' => &$this->headers['To'], 'cc' => &$this->headers['Cc'], 'bcc' => &$this->headers['Bcc'], 'from' => &$this->headers['From'], 'subject' => &$this->headers['Subject'], 'body' => &$this->text, 'params' => &$this->sendparam, 'headers' => '', 'success' => &$success); // do our thing if BEFORE hook approves $evt = new Doku_Event('MAIL_MESSAGE_SEND', $data); if ($evt->advise_before(true)) { // clean up before using the headers $this->cleanHeaders(); // any recipients? if (trim($this->headers['To']) === '' && trim($this->headers['Cc']) === '' && trim($this->headers['Bcc']) === '') { return false; } // The To: header is special if (array_key_exists('To', $this->headers)) { $to = (string) $this->headers['To']; unset($this->headers['To']); } else { $to = ''; } // so is the subject if (array_key_exists('Subject', $this->headers)) { $subject = (string) $this->headers['Subject']; unset($this->headers['Subject']); } else { $subject = ''; } // make the body $body = $this->prepareBody(); if ($body === false) { return false; } // cook the headers $headers = $this->prepareHeaders(); // add any headers set by legacy plugins if (trim($data['headers'])) { $headers .= MAILHEADER_EOL . trim($data['headers']); } // send the thing if (is_null($this->sendparam)) { $success = @mail($to, $subject, $body, $headers); } else { $success = @mail($to, $subject, $body, $headers, $this->sendparam); } } // any AFTER actions? $evt->advise_after(); return $success; }
if (!$defer && !$output) { sendGIF(); // send gif } $ID = cleanID($INPUT->str('id')); // Catch any possible output (e.g. errors) if (!$output) { ob_start(); } else { header('Content-Type: text/plain'); } // run one of the jobs $tmp = array(); // No event data $evt = new Doku_Event('INDEXER_TASKS_RUN', $tmp); if ($evt->advise_before()) { runIndexer() or runSitemapper() or sendDigest() or runTrimRecentChanges() or runTrimRecentChanges(true) or $evt->advise_after(); } if (!$output) { ob_end_clean(); if ($defer) { sendGIF(); } } exit; // -------------------------------------------------------------------- /** * Trims the recent changes cache (or imports the old changelog) as needed. * * @param media_changes If the media changelog shall be trimmed instead of * the page changelog
/** * Returns users realname w/o link * * @param string|null $username or null when currently logged-in user should be used * @param bool $textonly true returns only plain text, true allows returning html * @return string html or plain text(not escaped) of formatted user name * * @triggers COMMON_USER_LINK */ function userlink($username = null, $textonly = false) { global $conf, $INFO; /** @var DokuWiki_Auth_Plugin $auth */ global $auth; /** @var Input $INPUT */ global $INPUT; // prepare initial event data $data = array('username' => $username, 'name' => '', 'link' => array('target' => '', 'pre' => '', 'suf' => '', 'style' => '', 'more' => '', 'url' => '', 'title' => '', 'class' => ''), 'userlink' => '', 'textonly' => $textonly); if ($username === null) { $data['username'] = $username = $INPUT->server->str('REMOTE_USER'); if ($textonly) { $data['name'] = $INFO['userinfo']['name'] . ' (' . $INPUT->server->str('REMOTE_USER') . ')'; } else { $data['name'] = '<bdi>' . hsc($INFO['userinfo']['name']) . '</bdi> (<bdi>' . hsc($INPUT->server->str('REMOTE_USER')) . '</bdi>)'; } } $evt = new Doku_Event('COMMON_USER_LINK', $data); if ($evt->advise_before(true)) { if (empty($data['name'])) { if ($auth) { $info = $auth->getUserData($username); } if ($conf['showuseras'] != 'loginname' && isset($info) && $info) { switch ($conf['showuseras']) { case 'username': case 'username_link': $data['name'] = $textonly ? $info['name'] : hsc($info['name']); break; case 'email': case 'email_link': $data['name'] = obfuscate($info['mail']); break; } } else { $data['name'] = $textonly ? $data['username'] : hsc($data['username']); } } /** @var Doku_Renderer_xhtml $xhtml_renderer */ static $xhtml_renderer = null; if (!$data['textonly'] && empty($data['link']['url'])) { if (in_array($conf['showuseras'], array('email_link', 'username_link'))) { if (!isset($info)) { if ($auth) { $info = $auth->getUserData($username); } } if (isset($info) && $info) { if ($conf['showuseras'] == 'email_link') { $data['link']['url'] = 'mailto:' . obfuscate($info['mail']); } else { if (is_null($xhtml_renderer)) { $xhtml_renderer = p_get_renderer('xhtml'); } if (empty($xhtml_renderer->interwiki)) { $xhtml_renderer->interwiki = getInterwiki(); } $shortcut = 'user'; $exists = null; $data['link']['url'] = $xhtml_renderer->_resolveInterWiki($shortcut, $username, $exists); $data['link']['class'] .= ' interwiki iw_user'; if ($exists !== null) { if ($exists) { $data['link']['class'] .= ' wikilink1'; } else { $data['link']['class'] .= ' wikilink2'; $data['link']['rel'] = 'nofollow'; } } } } else { $data['textonly'] = true; } } else { $data['textonly'] = true; } } if ($data['textonly']) { $data['userlink'] = $data['name']; } else { $data['link']['name'] = $data['name']; if (is_null($xhtml_renderer)) { $xhtml_renderer = p_get_renderer('xhtml'); } $data['userlink'] = $xhtml_renderer->_formatLink($data['link']); } } $evt->advise_after(); unset($evt); return $data['userlink']; }
/** * Adds/updates the search index for the given page * * Locking is handled internally. * * @param string $page name of the page to index * @param boolean $verbose print status messages * @param boolean $force force reindexing even when the index is up to date * @return boolean the function completed successfully * @author Tom N Harris <*****@*****.**> */ function enhanced_idx_addPage($page, $verbose = false, $force = false) { $idxtag = metaFN($page, '.indexed'); // check if page was deleted but is still in the index if (!page_exists($page)) { if (!@file_exists($idxtag)) { if ($verbose) { print "Indexer: {$page} does not exist, ignoring" . DOKU_LF; } return false; } $Indexer = enhanced_idx_get_indexer(); $result = $Indexer->deletePage($page); if ($result === "locked") { if ($verbose) { print "Indexer: locked" . DOKU_LF; } return false; } @unlink($idxtag); return $result; } // check if indexing needed if (!$force && @file_exists($idxtag)) { if (trim(io_readFile($idxtag)) == idx_get_version()) { $last = @filemtime($idxtag); if ($last > @filemtime(wikiFN($page))) { if ($verbose) { print "Indexer: index for {$page} up to date" . DOKU_LF; } return false; } } } $indexenabled = p_get_metadata($page, 'internal index', METADATA_RENDER_UNLIMITED); if ($indexenabled === false) { $result = false; if (@file_exists($idxtag)) { $Indexer = enhanced_idx_get_indexer(); $result = $Indexer->deletePage($page); if ($result === "locked") { if ($verbose) { print "Indexer: locked" . DOKU_LF; } return false; } @unlink($idxtag); } if ($verbose) { print "Indexer: index disabled for {$page}" . DOKU_LF; } return $result; } $Indexer = enhanced_idx_get_indexer(); $pid = $Indexer->getPID($page); if ($pid === false) { if ($verbose) { print "Indexer: getting the PID failed for {$page}" . DOKU_LF; } return false; } $body = ''; $metadata = array(); $metadata['title'] = p_get_metadata($page, 'title', METADATA_RENDER_UNLIMITED); if (($references = p_get_metadata($page, 'relation references', METADATA_RENDER_UNLIMITED)) !== null) { $metadata['relation_references'] = array_keys($references); } else { $metadata['relation_references'] = array(); } if (($media = p_get_metadata($page, 'relation media', METADATA_RENDER_UNLIMITED)) !== null) { $metadata['relation_media'] = array_keys($media); } else { $metadata['relation_media'] = array(); } $data = compact('page', 'body', 'metadata', 'pid'); $evt = new Doku_Event('INDEXER_PAGE_ADD', $data); if ($evt->advise_before()) { $data['body'] = $data['body'] . " " . rawWiki($page); } $evt->advise_after(); unset($evt); extract($data); $result = $Indexer->addPageWords($page, $body); if ($result === "locked") { if ($verbose) { print "Indexer: locked" . DOKU_LF; } return false; } if ($result) { $result = $Indexer->addMetaKeys($page, $metadata); if ($result === "locked") { if ($verbose) { print "Indexer: locked" . DOKU_LF; } return false; } } if ($result) { io_saveFile(metaFN($page, '.indexed'), idx_get_version()); } if ($verbose) { print "Indexer: finished" . DOKU_LF; return true; } return $result; }
public function handle() { global $conf, $ID; //$this->_debug_print_r($data); //$this->_debug_print_r($_REQUEST); //If delete requested if(isset($_REQUEST['media_id_to_delete'])){ if(checkSecurityToken($_REQUEST['sectok'])){ $mediaToDelete = $_REQUEST['media_id_to_delete']; $file = mediaFN($mediaToDelete); if(file_exists($file)){ if(media_inuse($mediaToDelete)===false){ // trigger an event - MEDIA_DELETE_FILE $data['id'] = $mediaToDelete; $data['name'] = basename($file); $data['path'] = $file; $data['size'] = (@file_exists($file)) ? filesize($file) : 0; $data['unl'] = false; $data['del'] = false; $evt = new Doku_Event('MEDIA_DELETE_FILE',$data); if ($evt->advise_before()) { $data['unl'] = @unlink($file); if($data['unl']){ addMediaLogEntry(time(), $mediaToDelete, DOKU_CHANGE_TYPE_DELETE); $data['del'] = io_sweepNS($mediaToDelete,'mediadir'); } } $evt->advise_after(); unset($evt); $this->ok = sprintf($this->getLang('delete_file_ok'),$mediaToDelete); ; }else{ $this->error = sprintf($this->getLang('delete_file_in_use'),$mediaToDelete); } }else{ $this->error = sprintf($this->getLang('delete_file_not_found'),$mediaToDelete); } }//end of csrf check } //Searching for orphaned medias $data = array(); //getting all medias search($data,$conf['mediadir'],'search_media', array('showmsg'=>true,'depth'=>500),str_replace(':', '/', getNS($ID))); //check if they are (still) in use or not. foreach($data as $media){ $isUsed = media_inuse($media['id']); if($isUsed === false){ $this->orphans_medias[$media['id']] = $media; } } }