diff --git a/action.php b/action.php --- a/action.php +++ b/action.php @@ -1,204 +1,210 @@ */ // 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 $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 @@ */ // 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 .= '
  • '.$item['id']; $out .= ''; } else { $out .= '
  • '.$item['id']; } $out .= '
  • '; } } return $out; } function html() { echo '

    Meta Data Editor

    '; echo ''; echo ''; echo ''; - echo ''; echo ''; echo ''; echo '
    PageMeta DataValue
    '; + echo '
    '; echo '
      '.$this->recurseTree('/').'
    '; echo '

    '; echo '
    '; echo ''; echo '
    '; } } // 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?
     
    "; jqModalManager.msg += "PageId: " + selectedPageId + "
    "; jqModalManager.msg += "NodePath: " + selectedNodePath + "
    "; 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
     
    "; 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
     
    "; 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( '
    ' + jqModalManager.msg + '
    ' + '
    Name
    ' + (jqModalManager.createValue ? '
    Value
    ' : '') ) .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( '
    ' + jqModalManager.msg + '
    ' ) .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( '
    ' + jqModalManager.msg + '
    ' ) .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; } };