Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1820095
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
20 KB
Subscribers
None
View Options
diff --git a/action.php b/action.php
--- a/action.php
+++ b/action.php
@@ -1,204 +1,210 @@
<?php
/**
* DokuWiki Plugin metaeditor (Action Component)
*
* Simple Meta Data Editor, heavily AJAX/jQuery based.
*
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
* @author Andreas Böhler <dev@aboehler.at>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
class action_plugin_metaeditor extends DokuWiki_Action_Plugin {
// Load the helper plugin
public function action_plugin_metaeditor() {
}
// Register our hooks
function register(Doku_Event_Handler $controller) {
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown');
}
function handle_ajax_call_unknown($event, $param) {
if($event->data != 'plugin_metaeditor') return;
$event->preventDefault();
$event->stopPropagation();
global $INPUT;
$action = trim($INPUT->post->str('q'));
$pageid = trim($INPUT->post->str('r'));
$opts = $INPUT->post->arr('opts');
$data = array();
$useJson = true;
+ if(!checkSecurityToken())
+ {
+ echo "CSRF Attack.";
+ return;
+ }
+
$perm = auth_quickaclcheck($pageid);
if($perm == AUTH_ADMIN)
{
switch($action)
{
case 'getMeta':
$data = $this->getMetaForPage($pageid);
break;
case 'getMetaValue':
$useJson = false;
$data = $this->getMetaValueForPage($pageid, $opts['key']);
break;
case 'setMetaValue':
$data = $this->setMetaValueForPage($pageid, $opts['key'], $opts['oldval'], $opts['newval']);
break;
case 'deleteMetaValue':
$data = $this->deleteMetaValueForPage($pageid, $opts['key']);
break;
case 'createMetaArray':
$data = $this->createMetaArrayForPage($pageid, $opts['key'], $opts['newval']);
break;
case 'createMetaValue':
$data = $this->createMetaValueForPage($pageid, $opts['key'], $opts['newkey'], $opts['newval']);
break;
}
}
else
{
$data = array(false, "You are not an admin");
}
if($useJson)
{
//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);
}
else
{
echo $data;
}
}
function createMetaArrayForPage($pageid, $key, $newval)
{
$cache = false;
$meta = p_read_metadata($pageid, $cache);
$m = &$meta;
foreach($key as $k)
{
$m = &$m[$k];
}
$m[$newval] = array();
if(p_save_metadata($pageid, $meta))
return array(true, "Successfully saved: $newval");
else
return array(false, "Error saving value: $newval");
}
function createMetaValueForPage($pageid, $key, $newkey, $newval)
{
$cache = false;
$meta = p_read_metadata($pageid, $cache);
$m = &$meta;
foreach($key as $k)
{
$m = &$m[$k];
}
$m[$newkey] = $newval;
if(p_save_metadata($pageid, $meta))
return array(true, "Successfully saved: $newval");
else
return array(false, "Error saving value: $newval");
}
function setMetaValueForPage($pageid, $key, $oldval, $newval)
{
$cache = false;
$meta = p_read_metadata($pageid, $cache);
$m = &$meta;
foreach($key as $k)
$m = &$m[$k];
if($m == $oldval)
{
$m = $newval;
if(p_save_metadata($pageid, $meta))
return array(true, "Successfully saved: $newval");
else
return array(false, "Error saving value: $newval");
}
else
{
return array(false, "Key has changed in the meantime, expected $oldval but got $m. Nothing was saved!");
}
}
function deleteMetaValueForPage($pageid, $key)
{
$cache = false;
$meta = p_read_metadata($pageid, $cache);
$m = &$meta;
for($i=0;$i<count($key);$i++)
{
if($i == count($key)-1)
unset($m[$key[$i]]);
else
$m = &$m[$key[$i]];
}
if(p_save_metadata($pageid, $meta))
return array(true, "Successfully deleted key: " . join(':', $key));
else
return array(false, "Error deleting key: " . join(':', $key));
}
function parseMetaTree($meta)
{
$out = array();
foreach($meta as $k => $v)
{
$a = array();
$a['text'] = $k;
if(is_array($v))
{
$a['children'] = $this->parseMetaTree($v);
$a['li_attr'] = array('data-type' => 'folder');
}
else
{
$a['li_attr'] = array('data-type' => 'file');
$a['icon'] = DOKU_URL."/lib/images/page.png";
}
$out[] = $a;
}
return $out;
}
function getMetaForPage($pageid)
{
$cache = false;
$meta = p_read_metadata($pageid, $cache);
$out = $this->parseMetaTree($meta);
return $out;
}
function getMetaValueForPage($pageid, $key)
{
$cache = false;
$meta = p_read_metadata($pageid, $cache);
foreach($key as $k)
{
$meta = $meta[$k];
}
return $meta;
}
}
diff --git a/admin/editor.php b/admin/editor.php
--- a/admin/editor.php
+++ b/admin/editor.php
@@ -1,86 +1,86 @@
<?php
/**
* DokuWiki Plugin metaeditor (Admin Component)
*
* Simple Meta Data Editor, heavily AJAX/jQuery based.
*
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
require_once(DOKU_PLUGIN.'admin.php');
class admin_plugin_metaeditor_editor extends DokuWiki_Admin_Plugin {
/**
* Constructor. Load helper plugin
*/
function admin_plugin_metaeditor_editor(){
}
function getMenuSort() { return 501; }
function forAdminOnly() { return true; }
function getMenuText($language) {
return "Simple Meta Data Editor";
}
function handle() {
if(!is_array($_REQUEST['d']) || !checkSecurityToken()) return;
}
function recurseTree($ns) {
global $conf;
$out = '';
$list = array();
$opts = array(
'depth' => 1,
'listfiles' => true,
'listdirs' => true,
'pagesonly' => true,
'firsthead' => true,
'sneakyacl' => $conf['sneaky_index'],
);
search($list,$conf['datadir'],'search_universal',$opts,$ns);
foreach($list as $item)
{
if($item['type'] == 'f' || $item['type'] == 'd')
{
if($item['type'] == 'd')
{
$out .= '<li>'.$item['id'];
$out .= '<ul>'.$this->recurseTree(str_replace(':', '/', $item['id'])).'</ul>';
}
else
{
$out .= '<li data-jstree=\'{"icon":"'.DOKU_URL.'/lib/images/page.png"}\'>'.$item['id'];
}
$out .= '</li>';
}
}
return $out;
}
function html() {
echo '<h1>Meta Data Editor</h1>';
echo '<table>';
echo '<tr><th width="30\%">Page</th><th width="30\%">Meta Data</th><th width="30\%">Value</th></tr>';
echo '<tr>';
- echo '<td><div id="fileTree">';
+ echo '<td><div id="fileTree" data-sectok="'.getSecurityToken().'">';
echo '<ul>'.$this->recurseTree('/').'</ul>';
echo '</div></td>';
echo '<td><div id="metaTree"></div></td>';
echo '<td><div id="event_path"></div><br><div id="event_result">';
echo '<input type="text" id="event_value" value="..."><br>';
echo '<input type="submit" id="event_save" value="Save">';
echo '</div></td>';
echo '</tr></table>';
}
}
// vim:ts=4:sw=4:et:enc=utf-8:
diff --git a/script.js b/script.js
--- a/script.js
+++ b/script.js
@@ -1,406 +1,415 @@
/* DOKUWIKI:include_once jstree.js */
jQuery(function()
{
var selectedPageId = null;
var selectedNode = null;
var selectedNodePath = null;
var selectedNodeValue = null;
+ var sectok = jQuery('#fileTree').data('sectok');
+ if(!sectok) return;
jqModalManager.init();
jQuery('#event_save').click(function() {
var newVal = jQuery('#event_value').val();
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_metaeditor',
q: 'setMetaValue',
r: selectedPageId,
+ sectok: sectok,
opts: {
key : selectedNode,
oldval : selectedNodeValue,
newval : newVal
}
},
function(data) {
jqModalManager.msg = data[1];
jqModalManager.showInfoDialog();
selectedNodeValue = newVal;
}
);
});
function refreshMetaTree() {
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_metaeditor',
q: 'getMeta',
- r: selectedPageId
+ r: selectedPageId,
+ sectok: sectok
},
function(data) {
jQuery('#event_path').html('');
jQuery('#event_value').val('...');
selectedNodePath = null;
selectedNodeValue = null;
selectedNode = null;
jQuery('#metaTree').jstree(true).settings.core.data = data;
jQuery('#metaTree').jstree(true).refresh();
}
);
}
function customMenu(node) {
// The default set of all items
var items = {
/*renameItem: { // The "rename" menu item
label: "Rename",
action: function () {
alert('rename called');
}
},*/
deleteItem: { // The "delete" menu item
label: "Delete",
action: function () {
jqModalManager.data =
{
call : 'plugin_metaeditor',
q: 'deleteMetaValue',
r: selectedPageId,
+ sectok: sectok,
opts: {
key: selectedNodePath,
oldval: selectedNodeValue
}
};
jqModalManager.msg = "Do you really want to delete the selected node?<br> <br>";
jqModalManager.msg += "PageId: " + selectedPageId + "<br>";
jqModalManager.msg += "NodePath: " + selectedNodePath + "<br>";
jqModalManager.msg += "Value: " + selectedNodeValue;
jqModalManager.completeCb = function(data) {
jqModalManager.msg = data[1];
jqModalManager.showInfoDialog();
refreshMetaTree();
};
jqModalManager.showConfirmDialog();
}
},
createFolderItem: { // The "Create folder" menu item
label: "Create Folder",
action: function (data) {
var tree = jQuery("#metaTree").jstree(true);
var nodePath = tree.get_path(node);
if(node.li_attr['data-type'] == 'file')
{
var id = tree.get_parent(node);
var parentNode = tree.get_node(id);
nodePath = tree.get_path(parentNode);
}
jqModalManager.data =
{
call : 'plugin_metaeditor',
q: 'createMetaArray',
r: selectedPageId,
+ sectok: sectok,
opts: {
key : nodePath,
newval: null
}
};
jqModalManager.msg = "Create new folder<br> <br>";
jqModalManager.msg += "Parent: " + nodePath;
jqModalManager.completeCb = function(data) {
jqModalManager.msg = data[1];
jqModalManager.showInfoDialog();
refreshMetaTree();
};
jqModalManager.createValue = false;
jqModalManager.showCreateDialog();
}
},
createItem: { // The "Create" menu item
label: "Create Property",
action: function () {
var tree = jQuery("#metaTree").jstree(true);
var nodePath = tree.get_path(node);
if(node.li_attr['data-type'] == 'file')
{
var id = tree.get_parent(node);
var parentNode = tree.get_node(id);
nodePath = tree.get_path(parentNode);
}
jqModalManager.data =
{
call : 'plugin_metaeditor',
q: 'createMetaValue',
r: selectedPageId,
+ sectok: sectok,
opts: {
key : nodePath,
newkey: null,
newval: null
}
};
jqModalManager.msg = "Create new item<br> <br>";
jqModalManager.msg += "Parent: " + nodePath;
jqModalManager.completeCb = function(data) {
jqModalManager.msg = data[1];
jqModalManager.showInfoDialog();
refreshMetaTree();
};
jqModalManager.createValue = true;
jqModalManager.showCreateDialog();
}
}
};
return items;
}
jQuery('#metaTree').on('changed.jstree', function (e, data) {
var i, j, r;
if(data.selected.length != 1)
return;
var node = data.instance.get_node(data.selected[0]);
r = data.instance.get_path(data.selected[0]);
selectedNodePath = r;
if(node.li_attr['data-type'] == 'folder')
return;
//if(!data.instance.is_leaf(node))
// return;
selectedNode = r;
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_metaeditor',
q: 'getMetaValue',
r: selectedPageId,
+ sectok: sectok,
opts: {
key: r
}
},
function(data) {
jQuery('#event_path').html(selectedNode.join(':'));
jQuery('#event_value').val(data);
selectedNodeValue = data;
}
);
})
// create the instance
.jstree({
core : {
multiple: false,
},
plugins: ["wholerow", "contextmenu"],
contextmenu: { items: customMenu }
});
jQuery('#fileTree').on('changed.jstree', function (e, data) {
var i, j, r;
if(data.selected.length != 1)
return;
var node = data.instance.get_node(data.selected[0]);
if(!data.instance.is_leaf(node))
return;
r = node.text;
selectedPageId = r;
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'plugin_metaeditor',
q: 'getMeta',
+ sectok: sectok,
r: r
},
function(data) {
jQuery('#metaTree').jstree(true).settings.core.data = data;
jQuery('#metaTree').jstree(true).refresh();
}
);
})
// create the instance
.jstree({
core : {
multiple: false
},
plugins: ["wholerow"]
});
});
var jqModalManager = {
jqConfirmModal : null,
jqCreateModal : null,
jqInfoModal : null,
completeCb : null,
data : null,
msg : null,
createValue: false,
init : function()
{
},
showCreateDialog : function() {
jqModalManager.jqCreateModal = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: "Create",
resizable: true,
buttons: {
Create: function() {
if(jqModalManager.createValue)
{
jqModalManager.data.opts.newkey = jQuery("#metaeditor__createInput").val();
jqModalManager.data.opts.newval = jQuery("#metaeditor__createValue").val();
}
else
{
jqModalManager.data.opts.newval = jQuery("#metaeditor__createInput").val();
}
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
jqModalManager.data,
function(data) {
jqModalManager.completeCb(data);
}
);
jqModalManager.hideCreateDialog();
},
Cancel: function() {
jqModalManager.hideCreateDialog();
}
}
})
.html(
'<div>' + jqModalManager.msg + '</div>' +
'<div>Name <input type="text" id="metaeditor__createInput"></div>' +
(jqModalManager.createValue ? '<div>Value <input type="text" id="metaeditor__createValue"></div>' : '')
)
.parent()
.attr('id','metaeditor__create')
.show()
.appendTo('.dokuwiki:first');
jQuery('#metaeditor__createInput').focus();
jQuery('#metaeditor__create').position({
my: "center",
at: "center",
of: window
});
// attach event handlers
jQuery('#metaeditor__create .ui-dialog-titlebar-close').click(function(){
jqModalManager.hideCreateDialog();
});
},
showInfoDialog : function() {
jqModalManager.jqInfoModal = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: "Info",
resizable: true,
buttons: {
OK: function() {
jqModalManager.hideInfoDialog();
}
}
})
.html(
'<div>' + jqModalManager.msg + '</div>'
)
.parent()
.attr('id','metaeditor__info')
.show()
.appendTo('.dokuwiki:first');
jQuery('#metaeditor__info').position({
my: "center",
at: "center",
of: window
});
// attach event handlers
jQuery('#metaeditor__info .ui-dialog-titlebar-close').click(function(){
jqModalManager.hideInfoDialog();
});
},
showConfirmDialog : function() {
jqModalManager.jqConfirmModal = jQuery(document.createElement('div'))
.dialog({
autoOpen: false,
draggable: true,
title: "Confirmation",
resizable: true,
buttons: {
Yes: function() {
jQuery.post(
DOKU_BASE + 'lib/exe/ajax.php',
jqModalManager.data,
function(data) {
jqModalManager.completeCb(data);
}
);
jqModalManager.hideConfirmDialog();
},
Cancel: function() {
jqModalManager.hideConfirmDialog();
}
}
})
.html(
'<div>' + jqModalManager.msg + '</div>'
)
.parent()
.attr('id','metaeditor__confirm')
.show()
.appendTo('.dokuwiki:first');
jQuery('#metaeditor__confirm').position({
my: "center",
at: "center",
of: window
});
// attach event handlers
jQuery('#metaeditor__confirm .ui-dialog-titlebar-close').click(function(){
jqModalManager.hideConfirmDialog();
});
},
hideConfirmDialog : function() {
jqModalManager.jqConfirmModal.empty();
jqModalManager.jqConfirmModal.remove();
jqModalManager.jqConfirmModal = null;
},
hideCreateDialog : function() {
jqModalManager.jqCreateModal.empty();
jqModalManager.jqCreateModal.remove();
jqModalManager.jqCreateModal = null;
},
hideInfoDialog : function() {
jqModalManager.jqInfoModal.empty();
jqModalManager.jqInfoModal.remove();
jqModalManager.jqInfoModal = null;
}
};
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 7:23 PM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
533769
Default Alt Text
(20 KB)
Attached To
rMETAEDITOR DokuWiki MetaData Editor
Event Timeline
Log In to Comment