Page MenuHomePhabricator

No OneTemporary

diff --git a/action.php b/action.php
new file mode 100644
--- /dev/null
+++ b/action.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * DokuWiki linksenhanced PlugIn - Ajax component
+ * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
+ * @author Andreas Böhler <dev@aboehler.at>
+ */
+
+if(!defined('DOKU_INC')) die();
+
+class action_plugin_linksenhanced extends DokuWiki_Action_Plugin {
+
+ function register(Doku_Event_Handler $controller) {
+ $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown');
+ $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'add_jsinfo_information');
+ }
+
+ /**
+ * Add the language variable to the JSINFO variable
+ */
+ function add_jsinfo_information(Doku_Event $event, $param) {
+ global $JSINFO;
+
+ $JSINFO['plugin']['linksenhanced']['sectok'] = getSecurityToken();
+ }
+
+ function handle_ajax_call_unknown(&$event, $param) {
+ if($event->data != 'plugin_linksenhanced') return;
+
+ $event->preventDefault();
+ $event->stopPropagation();
+ global $INPUT;
+
+ $action = trim($INPUT->post->str('action'));
+ $url = trim($INPUT->post->str('url'));
+
+ if(!checkSecurityToken())
+ {
+ echo "CSRF Attack.";
+ return;
+ }
+
+ $data = array();
+
+ $data['result'] = false;
+
+ if($action === 'check')
+ {
+ $client = new DokuHTTPClient();
+ $client->sendRequest($url);
+ $httpcode = $client->status;
+
+ $data['error'] = $client->error;
+ $data['httpcode'] = $httpcode;
+
+ if($httpcode>=200 && $httpcode<300)
+ $data['result'] = true;
+ }
+ else
+ {
+ echo "Unknown operation.";
+ return;
+ }
+
+ // If we are still here, JSON output is requested
+
+ //json library of DokuWiki
+ require_once DOKU_INC . 'inc/JSON.php';
+ $json = new JSON();
+
+ //set content type
+ header('Content-Type: application/json');
+ echo $json->encode($data);
+ }
+
+}
diff --git a/conf/default.php b/conf/default.php
new file mode 100644
--- /dev/null
+++ b/conf/default.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Default settings for the linksenhanced plugin
+ *
+ * @author Andreas Boehler <dev@aboehler.at>
+ */
+
+$conf['check_all_external'] = 0;
+$conf['check_only_namespace'] = '';
diff --git a/conf/metadata.php b/conf/metadata.php
new file mode 100644
--- /dev/null
+++ b/conf/metadata.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Options for the linksenhanced plugin
+ *
+ * @author Andreas Boehler <dev@aboehler.at>
+ */
+
+
+$meta['check_all_external'] = array('onoff');
+$meta['check_only_namespace'] = array('string');
diff --git a/plugin.info.txt b/plugin.info.txt
--- a/plugin.info.txt
+++ b/plugin.info.txt
@@ -1,7 +1,7 @@
base linksenhanced
author Andreas Boehler
email dev@aboehler.at
-date 2015-03-10
+date 2019-01-23
name linksenhanced plugin
desc Enhanced Link Syntax
url http://www.aboehler.at
diff --git a/script.js b/script.js
new file mode 100644
--- /dev/null
+++ b/script.js
@@ -0,0 +1,33 @@
+jQuery(function() {
+
+ jQuery('div.dokuwiki a.plugin_linksenhanced_pending').each(function() {
+ var $link = jQuery(this).prop('href');
+ if(!$link)
+ return;
+ var $obj = jQuery(this);
+ // If we are still here, we found our target link
+ jQuery.post(
+ DOKU_BASE + 'lib/exe/ajax.php',
+ {
+ call: 'plugin_linksenhanced',
+ url: $link,
+ action: 'check',
+ sectok: JSINFO.plugin.linksenhanced['sectok'],
+ },
+ function(data)
+ {
+ var result = data['result'];
+ if(result === true)
+ {
+ $obj.removeClass('plugin_linksenhanced_pending');
+ $obj.addClass('plugin_linksenhanced_online');
+ }
+ else
+ {
+ $obj.removeClass('plugin_linksenhanced_pending');
+ $obj.addClass('plugin_linksenhanced_offline');
+ }
+ }
+ );
+ });
+});
diff --git a/style.css b/style.css
new file mode 100644
--- /dev/null
+++ b/style.css
@@ -0,0 +1,35 @@
+div.dokuwiki a.plugin_linksenhanced_pending::before{
+ content: '';
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ margin-right:3px;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ background-color: #e7793c;
+}
+
+div.dokuwiki a.plugin_linksenhanced_online::before{
+ content: '';
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ margin-right:3px;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ background-color: #1ac423;
+}
+
+div.dokuwiki a.plugin_linksenhanced_offline::before{
+ content: '';
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ margin-right:3px;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ background-color: #e52020;
+}
\ No newline at end of file
diff --git a/syntax.php b/syntax.php
--- a/syntax.php
+++ b/syntax.php
@@ -1,396 +1,415 @@
<?php
/**
* linksenhanced Plugin - Render Link Title using Wiki Markup
* Heavily based on the standard linking code.
*
* Usage:
*
+ * [[check^http://www.dokuwiki.org|www.dokuwiki.org]]
* [[render noparagraph^http://www.dokuwiki.org|<faicon fa fe-euro> FontAwesome Code]]
* [[render^http://www.dokuwiki.org|//Formatted Output, probably within a paragraph//]]
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Böhler <dev@aboehler.at>
*/
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
/**
* All DokuWiki plugins to extend the parser/rendering mechanism
* need to inherit from this class
*/
class syntax_plugin_linksenhanced extends DokuWiki_Syntax_Plugin {
function getType() {
return 'substition';
}
function getPType() {
return 'normal';
}
function getAllowedTypes() {
return array('container','substition','protected','disabled','paragraphs','formatting');
}
function getSort() {
return 202;
}
function connectTo($mode) {
$this->Lexer->addSpecialPattern('\[\[(?:(?:[^[\]]*?\[.*?\])|.*?)\]\]',$mode,'plugin_linksenhanced');
}
/**
* Handle the match. Use either the standard linking mechanism or, when enabled,
* pass the title through the parser
*/
function handle($match, $state, $pos, Doku_Handler $handler) {
+ global $ID;
+
$match = substr($match, 2, -2);
$link = explode('|',$match,2);
$nopara = false;
$optionsSet = explode('^', $link[0], 2);
$options = array('render' => false,
'noparagraph' => false,
+ 'check' => false,
'class' => false,
'target' => false);
if(isset($optionsSet[1]))
{
$link[0] = $optionsSet[1];
$opts = explode(' ', $optionsSet[0]);
foreach($opts as $opt)
{
if(strpos($opt, 'class') === 0)
$options['class'] = explode('=', $opt)[1];
elseif(strpos($opt, 'target') === 0)
$options['target'] = explode('=', $opt)[1];
else
$options[$opt] = true;
}
}
-
+
+ if($this->getConf('check_all_external') == 1)
+ {
+ if($this->getConf('check_only_namespace') != '')
+ {
+ if(getNS($ID) == $this->getConf('check_only_namespace'))
+ $options['check'] = true;
+ }
+ else
+ {
+ $options['check'] = true;
+ }
+ }
if($options['render'] && isset($link[1]))
{
$link[1] = $this->render_text($link[1]);
if($options['noparagraph'])
{
$link[1] = str_replace('</p>', '', str_replace('<p>', '', $link[1]));
}
if($link[1] === '')
$link[1] = null;
}
else if ( isset($link[1]) && preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) {
// If the title is an image, convert it to an array containing the image details
$link[1] = Doku_Handler_Parse_Media($link[1]);
}
else if(!isset($link[1]))
{
$link[1] = null;
}
$link[0] = trim($link[0]);
//decide which kind of link it is
if ( preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u',$link[0]) ) {
$type = 'interwiki';
}elseif ( preg_match('/^\\\\\\\\[^\\\\]+?\\\\/u',$link[0]) ) {
$type = 'windowsshare';
}elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) ) {
$type = 'external';
}elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link[0]) ) {
$type = 'email';
}elseif ( preg_match('!^#.+!',$link[0]) ){
$type = 'local';
$link[0] = substr($link[0],1);
}else{
$type = 'internal';
}
return array($type, $link, $options);
}
/**
* Create output. This is largely based on the internal linking mechanism.
*/
function render($mode, Doku_Renderer $renderer, $data) {
if (empty($data)) return false;
global $conf;
global $ID;
global $INFO;
global $lang;
list($type, $link, $options) = $data;
$url = $link[0];
$name = $link[1];
-
if($mode == 'xhtml') {
switch($type)
{
case 'interwiki':
$interwiki = explode('>',$link[0],2);
$wikiName = strtolower($interwiki[0]);
$wikiUri = $interwiki[1];
$link = array();
$link['target'] = $conf['target']['interwiki'];
$link['pre'] = '';
$link['suf'] = '';
$link['more'] = '';
if($name === null || !$options['render'])
$link['name'] = $renderer->_getLinkTitle($name, $wikiUri, $isImage);
else
$link['name'] = $name;
//get interwiki URL
$exists = null;
$url = $renderer->_resolveInterWiki($wikiName, $wikiUri, $exists);
if(!$isImage) {
$class = preg_replace('/[^_\-a-z0-9]+/i', '_', $wikiName);
$link['class'] = "interwiki iw_$class";
} else {
$link['class'] = 'media';
}
//do we stay at the same server? Use local target
if(strpos($url, DOKU_URL) === 0 OR strpos($url, DOKU_BASE) === 0) {
$link['target'] = $conf['target']['wiki'];
}
if($options['target'] !== false)
$link['target'] = $options['target'];
if($exists !== null && !$isImage) {
if($exists) {
$link['class'] .= ' wikilink1';
} else {
$link['class'] .= ' wikilink2';
$link['rel'] = 'nofollow';
}
}
if($options['class'] !== false)
$link['class'] = $options['class'];
$link['url'] = $url;
$link['title'] = htmlspecialchars($link['url']);
//output formatted
$renderer->doc .= $renderer->_formatLink($link);
break;
case 'windowsshare':
//simple setup
$link['target'] = $conf['target']['windows'];
$link['pre'] = '';
$link['suf'] = '';
$link['style'] = '';
if($options['target'] !== false)
$link['target'] = $options['target'];
if($name === null || !$options['render'])
$link['name'] = $renderer->_getLinkTitle($name, $url, $isImage);
else
$link['name'] = $name;
if ( !$isImage ) {
$link['class'] = 'windows';
} else {
$link['class'] = 'media';
}
if($options['class'] !== false)
$link['class'] = $options['class'];
$link['title'] = $renderer->_xmlEntities($url);
$url = str_replace('\\','/',$url);
$url = 'file:///'.$url;
$link['url'] = $url;
//output formatted
$renderer->doc .= $renderer->_formatLink($link);
break;
case 'external':
if($name === null || !$options['render'])
$name = $renderer->_getLinkTitle($name, $url, $isImage);
// url might be an attack vector, only allow registered protocols
$schemes = getSchemes();
list($scheme) = explode('://',$url);
$scheme = strtolower($scheme);
if(!in_array($scheme,$schemes)) $url = '';
// is there still an URL?
if(!$url){
$renderer->doc .= $name;
return;
}
// set class
if ( !$isImage ) {
$class='urlextern';
} else {
$class='media';
}
if($options['class'] !== false)
$class = $options['class'];
//prepare for formating
$link['target'] = $conf['target']['extern'];
$link['style'] = '';
$link['pre'] = '';
$link['suf'] = '';
$link['more'] = '';
$link['class'] = $class;
$link['url'] = $url;
if($options['target'] !== false)
$link['target'] = $options['target'];
-
+
+ if($options['check'] !== false)
+ {
+ $link['class'] = 'plugin_linksenhanced_pending';
+ }
$link['name'] = $name;
$link['title'] = $renderer->_xmlEntities($url);
if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"';
//output formatted
$renderer->doc .= $renderer->_formatLink($link);
break;
case 'email':
$link = array();
$link['target'] = '';
$link['pre'] = '';
$link['suf'] = '';
$link['style'] = '';
$link['more'] = '';
if($name === null || !$options['render'])
$name = $renderer->_getLinkTitle($name, '', $isImage);
if ( !$isImage ) {
$link['class']='mail';
} else {
$link['class']='media';
}
if($options['class'] !== false)
$link['class'] = $options['class'];
$url = $renderer->_xmlEntities($url);
$url = obfuscate($url);
$title = $url;
if(empty($name)){
$name = $url;
}
if($conf['mailguard'] == 'visible') $url = rawurlencode($url);
$link['url'] = 'mailto:'.$url;
$link['name'] = $name;
$link['title'] = $title;
//output formatted
$renderer->doc .= $renderer->_formatLink($link);
break;
case 'local':
if($name === null || !$options['render'])
$name = $renderer->_getLinkTitle($name, $url, $isImage);
$url = $renderer->_headerToLink($url);
$title = $ID.' ↵';
if($options['class'] !== false)
$class = $options['class'];
else
$class = "wikilink1";
$renderer->doc .= '<a href="#'.$url.'" title="'.$title.'" class="'.$class.'">';
$renderer->doc .= $name;
$renderer->doc .= '</a>';
break;
case 'internal':
$id = $url;
$params = '';
$linktype = 'content';
$parts = explode('?', $id, 2);
if (count($parts) === 2) {
$id = $parts[0];
$params = $parts[1];
}
// For empty $id we need to know the current $ID
// We need this check because _simpleTitle needs
// correct $id and resolve_pageid() use cleanID($id)
// (some things could be lost)
if ($id === '') {
$id = $ID;
}
// default name is based on $id as given
$default = $renderer->_simpleTitle($id);
// now first resolve and clean up the $id
resolve_pageid(getNS($ID),$id,$exists);
if($name === null || !$options['render'])
$name = $renderer->_getLinkTitle($name, $default, $isImage, $id, $linktype);
if ( !$isImage ) {
if ( $exists ) {
$class='wikilink1';
} else {
$class='wikilink2';
$link['rel']='nofollow';
}
} else {
$class='media';
}
if($options['class'] !== false)
$class = $options['class'];
//keep hash anchor
@list($id,$hash) = explode('#',$id,2);
if(!empty($hash)) $hash = $renderer->_headerToLink($hash);
//prepare for formating
$link['target'] = $conf['target']['wiki'];
$link['style'] = '';
$link['pre'] = '';
$link['suf'] = '';
// highlight link to current page
if ($id == $INFO['id']) {
$link['pre'] = '<span class="curid">';
$link['suf'] = '</span>';
}
$link['more'] = '';
$link['class'] = $class;
$link['url'] = wl($id, $params);
$link['name'] = $name;
$link['title'] = $id;
if($options['target'] !== false)
$link['target'] = $options['target'];
//add search string
if($search){
($conf['userewrite']) ? $link['url'].='?' : $link['url'].='&amp;';
if(is_array($search)){
$search = array_map('rawurlencode',$search);
$link['url'] .= 's[]='.join('&amp;s[]=',$search);
}else{
$link['url'] .= 's='.rawurlencode($search);
}
}
//keep hash
if($hash) $link['url'].='#'.$hash;
//output formatted
if($returnonly){
return $renderer->_formatLink($link);
}else{
$renderer->doc .= $renderer->_formatLink($link);
}
break;
}
}
return false;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 24, 6:00 PM (1 d, 2 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
532419
Default Alt Text
(20 KB)

Event Timeline