DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:draw

Draw Plugin

Compatible with DokuWiki

No compatibility info given!

plugin Draw and edit diagrams using a Java Applet

Last updated on
2005-10-14
Provides
Syntax

This extension has not been updated in over 2 years. It may no longer be maintained or supported and may have compatibility issues.

Similar to svgedit

Tagged with !discontinued, diagram, images, java, media

Draw and Edit diagrams using a Java Applet. This plugin is an adaption of the TWikiDraw facility of the MoinMoin-Wiki.

Looking for a new maintainer

Hi all,

I wrote this plugin about 3 years ago for an internal wiki of a company I was working for at that time. I've not used DokuWiki myself since then. Apparently the plugin is not compatible with the latest version of DokuWiki anymore. If there's anyone out there who's willing to update the plugin, don't hesitate to contact me (julian.rueth@gmail.com). I'd gladly support you in making the plugin usable again. It'd be great if someone who's actually using DokuWiki and this plugin, could volunteer for being the maintainer for it, as I myself can't take care of this job anymore.

Julian Rüth 2008-04-14

svgedit plugin is finally done! it can easily replace draw, but it needs a modern browser.

Syntax

DokuWiki Syntax:

<draw name=NAME [namespace=NAMESPACE_ROOT:NAMESPACE:...] [width=PIXELS] [height=PIXELS]>

Examples:

<draw name=hello_world>
<draw name=hello_namespace namespace=some_namespace>

This will put a diagram hello_world on the page with a small Edit button beneath. A click on the Edit button starts a Java Applet to edit the diagram.

Notes

  • Every diagram will be put in the namespace media; if you specify a namespace, then the diagram will be put in NAMESPACE:media
  • You can't use hyperlinks together with width or height as the <map> will not be stretched accordingly.
  • You can set links to wiki pages by setting the URL in the editor to doku.php?id=NAME

Plugin

Setup

New Method

This works with “DokuWiki version: Release 2006-11-06”: Just copy and paste http://home.tu-clausthal.de/~ifcma/draw.tgz to the URL-Line in the Plugin manager and click “Download”. The plugin should install successful.

Next add the following two lines to conf/mime.local.conf

  draw    text/plain
  map     text/plain

If you don't add the two mime Types, you'll get a warning message on every page containing a “Draw”-Object, because the .map and .draw file can't be uploaded without them.

I've also just updated the .tgz-file to hide the edit buttons if the use hasn't got the permission level 16 (Upload and Delete) - without them edits can't be saved, so why bother?
Christian Marg – 2007-04-05 15:30

Old Method:

  • Mkdir lib/plugins/draw/
  • Copy syntax.php to lib/plugins/draw/
  • Copy close.html to lib/exe/
  • Add the following css code to lib/tpl/default/design.css
a.diagbutton {
  border: 1px solid #8cacbb;
  color: Green;
  background-color: white;
  vertical-align: middle;
  text-decoration:none;
  margin: 0px;
  padding: 0px;
  font-size: 10px;
  cursor: pointer;
  height: 15px !important;
  max-height: 15px !important;
  min-height: 15px !important;
/*  float:right;*/
  display: inline;
}
  • Copy twikidraw.jar to lib/plugins/draw
  • add following two lines to conf/mime.conf
  draw    text/plain
  map     text/plain

Source Code

syntax.php:

I'm a complete newbie to PHP, so don't blame me for this ugly code ;)

<?php
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');
 
class syntax_plugin_draw extends DokuWiki_Syntax_Plugin {
 
    function getInfo(){
        return array(
            'author' => 'Julian Rueth',
            'email'  => 'julian.rueth@gmail.com',
            'date'   => '2005-10-14',
            'name'   => 'Hotdraw Plugin',
            'desc'   => 'Use JHotdraw to paint images',
            'url'    => 'none',
        );
    }
 
    function getType(){ return 'substition'; }
    function getSort(){ return 731; }
    Function connectTo($mode) { $this->Lexer->addSpecialPattern('<draw.*?>',$mode,'plugin_draw'); }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
      preg_match('/width=([0-9]+)/i', substr($match,6,-1), $match_width);
      preg_match('/height=([0-9]+)/i', substr($match,6,-1), $match_height);
      preg_match('/name=([a-zA-Z_0-9]+)/i', substr($match,6,-1), $match_name);
      preg_match('/namespace=([a-zA-Z_0-9:]+)/i', substr($match,6,-1), $match_namespace);
      return array($match_name[1], intval($match_width[1]), intval($match_height[1]), $match_namespace[1]);
    }
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $indata) {
      global $conf;
 
      list($name, $width, $height, $namespace) = $indata;
 
      if($mode == 'xhtml') {
        //check name 
        $name = strtolower($name);
        if (strlen($name)==0){
          $renderer->doc.="---INVALID_DIAGRAM---";
          return true;
        }
        $default_namespace="media";
        if (substr($namespace,-strlen($default_namespace)-1)!=$default_namespace) $namespace.=":$default_namespace";
        $namespace.=':';
        //copy template files if the appropriate files don't exist
        //TODO: saving of gif's doesn't work properly
        $media_dir = $conf['mediadir'].'/'.str_replace(":","/",$namespace);
        if (! file_exists($media_dir)) mkdir ($media_dir);
        $png_file = $name.'.png';
        //$gif_file = $name.'.gif';
        $draw_file = $name.'.draw';
        $map_file = $name.'.map';
        $default_png_file = "default_dont_delete_me".'.png';
        //$default_gif_file = "default_dont_delete_me".'.gif';
        $default_draw_file = "default_dont_delete_me".'.draw';
        $default_map_file = "default_dont_delete_me".'.map';
        if (! is_readable($media_dir.$png_file)) copy($conf['mediadir'].'/'.$default_namespace.'/'.$default_png_file, $media_dir.$png_file);
        //if (! is_readable($media_dir.$gif_file))  copy($conf['mediadir'].'/'.$default_namespace.''/'.$default_gif_file, $media_dir.$gif_file);
        if (! is_readable($media_dir.$draw_file)) copy($conf['mediadir'].'/'.$default_namespace.'/'.$default_draw_file, $media_dir.$draw_file);
        if (! is_readable($media_dir.$map_file)) copy($conf['mediadir'].'/'.$default_namespace.'/'.$default_map_file, $media_dir.$map_file);
 
        //base URL to fetch every file
        $fetchpath = DOKU_BASE."lib/exe/fetch.php?media=$namespace";
        //URL to post files for saving
        $saveurl = DOKU_BASE."lib/exe/media.php";
        //URL to go after the applet is closed
        $viewpath = DOKU_BASE."lib/exe/close.html";
        $helppath = DOKU_BASE."lib/exe/close.html";
 
        //add some JScript to open up the Applet
        $random = rand(0,100000); //to prevent JS errors if one diagram is on a page mupltiple times
        $jscript_name = "switchToDiagram__$name_$random";
        $renderer->doc.="<script language=\"javascript\" type=\"text/javascript\" charset=\"utf-8\">".
        "function $jscript_name () {\n".
        "  w=window.open('about:blank');\n".
        "  w.document.write('<html><body>\\\n".
        "<applet code=\"CH.ifa.draw.twiki.TWikiDraw.class\" archive=\"".DOKU_BASE."lib/plugins/draw/twikidraw.jar\" width=\"640\" height=\"480\">\\\n".
        "<param name=\"drawpath\" value=\"$fetchpath$draw_file\">\\\n".
        "<param name=\"pngpath\"  value=\"$fetchpath$png_file\">\\\n".
        "<param name=\"savepath\" value=\"$saveurl\">\\\n".
        "<param name=\"basename\" value=\"$name\">\\\n".
        "<param name=\"viewpath\" value=\"$viewpath\">\\\n".
        "<param name=\"helppath\" value=\"$helppath\">\\\n".
        "<param name=\"namespace\" value=\"$namespace\">\\\n".
        "<strong>NOTE:</strong> You need a Java enabled browser to edit the drawing example.\\\n".
        "</applet>\\\n".
        "</body></html>', \"Edit Diagram\", \"\");\n".
        " w.document.close();\n".
 
        "}\n".
        "</script>";
 
        //we can't use a map if the image will be scaled
        if ($width>0 || $height>0) $dont_use_map=1;
        $map= implode('', file($media_dir.$map_file));
        if ($dont_use_map) $renderer->doc.="<img src=\"$fetchpath$png_file\" alt=\" [diagram] \"";
        else $renderer->doc.=$map."<img usemap=\"#$name\" src=\"$fetchpath$png_file\" alt=\" [diagram] \"";
        if ($height>0) $renderer->doc.= "height=\"$height\" ";
        if ($width>0) $renderer->doc.= "width=\"$width\" ";
        $renderer->doc.=">";
        //some edit button
        $renderer->doc.="<a class=\"diagbutton\" href=\"javascript:$jscript_name()\">Edit</a>\n".
        "\n";
        return true;
       }
       return false;
    }
}

close.html:

<html><head><script language="javascript">self.close();</script></head><body>done.</body></html>

twikidraw.jar:

This is a slightly modified version of the twikidraw.jar used by MoinMoin. You can download the source code twikidraw.tgz here.

Discussion

Everything should work now - twikidraw.jar has changed, so please download it again (for most browsers you have to close your browser completely; otherwise your browser will take the old applet from its cache). — Julian Rüth

I'm getting a 401 error in the twikidraw.jar. (“GET /dokuwiki/lib/exe/fetch.php?media=:media:hello_world.draw HTTP/1.1” 401 12 “-” “Mozilla/4.0” from Apache logs) It complains that the fetch.php is unable to find the media. I've check and the default draw,map,png all get moved into the new name as they should. The files seem to be there but it wont work. I'm using a snapshot of DokuWiki from 10-3.. I followed the instructions from this plugin page with the files linked in the install instructions. Any ideas? — Matt Pascoe 10/27/2005 02:06

Have you checked the permissions? Perhaps you have to insert some umask() in the script; also check whether the media dir was created with appropriate permissions? — Julian Rüth Sun Oct 30 16:26:09 CET 2005
I did forget to mention that the ownership and permissions are correct. Files and dirs all the way through data/media/media/* are owned by Apache and are rw all the way across. The new files are created this way so the umask already seems to be appropriate so I'm not sure that setting it in the script would help? — Matt Pascoe 10/31/2005 08:30
Not sure what the heck my problem was but I refreshed my browser and all seems good now? So I guess, never mind on my issues.. Thanks.. Good tool by the way. — Matt Pascoe 10/31/2005 12:03

Hi all! I have a similar problem as Matt. Whenever I create a new drawing, the files get created inside data/media/media. But they are always only a copy of the default. I can start the applet and draw some things, but after hitting save everything is gone again. — Markus Hinterseer 11/08/2006 11:10

  • I have a problem. When I add a text box and it contains a new line the .draw file won't load. When I look in the .draw file I see that the string has a ^M before the \n. If I remove the ^M it loads. — Fredrik Espinoza 11/23/2995 17:45
  • It's working for me! That's really great! I was waiting for that tool for several years… THANKS A LOT. Cyrille 2006-09-10

Using Firefox, when I add a multiple line label to a drawing, there is a new line character inserted after the '\n'. This produces a syntax error when the image is reloaded. Editing the file to remove the new line fixes that syntax error. Does anyone know how to modify the JavaScript to eliminate the newline? Bob McConnell 2006-09-20


我的不工作:It doesn's work!! 按照提示安装完成后可以绘画但不能保存.I can draw but nothing can be saved, help!hisir@hiisee.net

:!: this plugin does not work since version DokuWiki-2006-11-06 ;( If you can, please fix it. Bohuslav Blin 2006-12-13

Thought it was working but save failed. Any fixes?? Please. georgie 2006-12-28

In the file lib/plugins/draw/syntax.php you need to change media.php to mediamanager.php Tom Gray 2006-12-29

Thank-you, that makes a lot of sense. What a fantastic tool. It is exactly what I needed. georgie 2006-12-29


Hi, I am trying to use this plugin with DokuWiki 2006-11-06. I have a page docs_user:fvpc:start with a diagram named “fvpc”. I was able to create and save the diagram, but when reloading I get a Java (running Java 1.5.0_08 on Win2k) error:

java.io.IOException: String expected in line: 42
	at CH.ifa.draw.util.StorableInput.readString(StorableInput.java:75)
	at CH.ifa.draw.figures.TextFigure.read(TextFigure.java:322)
	at CH.ifa.draw.util.StorableInput.readStorable(StorableInput.java:52)
	at CH.ifa.draw.standard.CompositeFigure.read(CompositeFigure.java:410)
	at CH.ifa.draw.util.StorableInput.readStorable(StorableInput.java:52)
	at CH.ifa.draw.standard.CompositeFigure.read(CompositeFigure.java:410)
	at CH.ifa.draw.util.StorableInput.readStorable(StorableInput.java:52)
	at CH.ifa.draw.appframe.DrawFrame.readFromStorableInput(DrawFrame.java:423)
	at CH.ifa.draw.appframe.DrawFrame.readDrawing(DrawFrame.java:409)
	at CH.ifa.draw.appframe.DrawFrame.loadDrawing(DrawFrame.java:401)
	at CH.ifa.draw.twiki.TWikiFrame.<init>(TWikiFrame.java:101)
	at CH.ifa.draw.twiki.TWikiDraw.init(TWikiDraw.java:73)
	at sun.applet.AppletPanel.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

I don't know if this indicates a file permission issue or a bad save. I thought I'd pass it along, as this plugin would really make my day in terms of completing my ability to use DokuWiki.


In my case I can see that the *.draw, *.map and *.pnf files are created but never overwritten by the applet. Anyway, no error is reported. My drawings are empty by default and nothing else. – Mihai PALADE


Hello, and thanks for that nice and usefull tool!
When I put some 'URL' on the draw, the file mydraw.map is well filled, but the HTML map still empty (and I didn't put width & height in the draw tag).
Cyrille37 2007-03-30


It seems that in syntax.php, $conf['baseurl'] should be replaced with DOKU_BASE in order to refer to the correct base URL of DokuWiki.

<draw name=hello_world>


Hallo!
Bei mir kommt immer folgender Error in der Java-Konsole, wenn ich versuche die eingefügte Grafik zu verändern:

Laden: Klasse CH.ifa.draw.twiki.TWikiDraw.class nicht gefunden
java.lang.ClassNotFoundException: CH.ifa.draw.twiki.TWikiDraw.class
	at sun.applet.AppletClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.applet.AppletClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.applet.AppletClassLoader.loadCode(Unknown Source)
	at sun.applet.AppletPanel.createApplet(Unknown Source)
	at sun.plugin.AppletViewer.createApplet(Unknown Source)
	at sun.applet.AppletPanel.runLoader(Unknown Source)
	at sun.applet.AppletPanel.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: open HTTP connection failed.
	at sun.applet.AppletClassLoader.getBytes(Unknown Source)
	at sun.applet.AppletClassLoader.access$100(Unknown Source)
	at sun.applet.AppletClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	... 10 more

Ich dachte erst es läge vielleicht daran, dass ich Java nicht richtig installiert hätte, aber auf anderen Rechnern kommt der gleiche Fehler. Hat jemand eine Ahnung, wie ich das beheben kann? Ist das Plugin so wie es derzeit angeboten wird überhaupt einwandfrei lauffähig?


Bei mir kommt exakt dieselbe Fehlermeldung… (2008-03-13)


Yeah, I have the same problem as our German friend above. Here's that error output in English:

load: class CH.ifa.draw.twiki.TWikiDraw.class not found.
java.lang.ClassNotFoundException: CH.ifa.draw.twiki.TWikiDraw.class
	at sun.applet.AppletClassLoader.findClass(AppletClassLoader.java:168)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at sun.applet.AppletClassLoader.loadClass(AppletClassLoader.java:119)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
	at sun.applet.AppletClassLoader.loadCode(AppletClassLoader.java:599)
	at sun.applet.AppletPanel.createApplet(AppletPanel.java:722)
	at sun.plugin.AppletViewer.createApplet(AppletViewer.java:1811)
	at sun.applet.AppletPanel.runLoader(AppletPanel.java:651)
	at sun.applet.AppletPanel.run(AppletPanel.java:325)
	at java.lang.Thread.run(Thread.java:595)
Caused by: java.io.IOException: open HTTP connection failed.
	at sun.applet.AppletClassLoader.getBytes(AppletClassLoader.java:271)
	at sun.applet.AppletClassLoader.access$100(AppletClassLoader.java:44)
	at sun.applet.AppletClassLoader$1.run(AppletClassLoader.java:158)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.applet.AppletClassLoader.findClass(AppletClassLoader.java:155)
	... 9 more

When I tried to “Edit” my first drawing, I got a “Java Applet failed to load” message from Firefox and this is in the Java Console. Any ideas of what I am doing wrong?

bug in URL :

I think it would be better :

 //base URL to fetch every file
        $fetchpath = $conf['baseurl'].$conf['basedir']."lib/exe/fetch.php?media=$namespace";
        //URL to post files for saving
        $saveurl = $conf['baseurl'].$conf['basedir']."lib/exe/mediamanager.php";
        //URL to go after the applet is closed
        $viewpath = $conf['baseurl'].$conf['basedir']."lib/plugins/draw/close.html";
        $helppath = $conf['baseurl'].$conf['basedir']."lib/plugins/draw/close.html";
Me,too -2007/11/13

Used and checked with “DokuWiki 2007-06-26b” MANDATORY mods of syntax.php thanx “Me,too”!

David - 2008/04/14

DokuWiki release DokuWiki 2007-06-26

I'm working with DokuWiki Release 2007-06-26 and Draw plugins doesn't work… Simply, the java VM does not execute the jar file….Any idea? Any upgrade?

Draw plugin development still active?

Is this draw plugin still being actively being developed?!

I am trying to desperately get the draw plugin working on my DokuWiki setup.

The plugin seem to install OK and I have made sure I added the two mime type entries. The syntax also is working. However, when the java application loads I just get a red X and when I check the java console log I get the following error:

load: class CH.ifa.draw.twiki.TWikiDraw.class not found.
java.lang.ClassNotFoundException: CH.ifa.draw.twiki.TWikiDraw.class
      at sun.applet.AppletClassLoader.findClass(Unknown Source)
      at java.lang.ClassLoader.loadClass(Unknown Source)
      at sun.applet.AppletClassLoader.loadClass(Unknown Source)
      at java.lang.ClassLoader.loadClass(Unknown Source)
      at sun.applet.AppletClassLoader.loadCode(Unknown Source)
      at sun.applet.AppletPanel.createApplet(Unknown Source)
      at sun.plugin.AppletViewer.createApplet(Unknown Source)
      at sun.applet.AppletPanel.runLoader(Unknown Source)
      at sun.applet.AppletPanel.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)

When I check my Apache access/error logs I notice the following message when I try to use the draw java app:

access_log:

"GET /dokuwiki/CH/ifa/draw/twiki/TWikiDraw.class HTTP/1.1" 404 316 "-" "Mozilla/4.0 (Windows Vista 6.0) Java/1.6.0_05"

error_log:

File does not exist: /var/www/html/dokuwiki/CH

The directory “/var/www/html/dokuwiki/CH” does not actually exist and I don't know what 'CH' refers to and why the DokuWiki or the draw module is trying to look inside this non-existent directory.

Below are some details about my setup:

DokuWiki version Release rc2008-03-31
PHP version 5.1.6
Server OS CentOS 5.1
HTTP Server Apache 2.2.3
Browser Firefox 2.0.0.13
Client OS Windows Vista Business (SP1)

Java RPMs:

gcc-java-4.1.2-14.el5
java-1.4.2-gcj-compat-devel-1.4.2.0-40jpp.112
java-1.4.2-gcj-compat-1.4.2.0-40jpp.112

I would really love to get this plugin working as having the ability to create drawings in the wiki is most useful.

Note: I tried to send an email to the author but it seems the email address is not correct - unknown user at the domain.

MP 11/04/2008

Update

I think I've fixed it!

First of all I made the changes as described above to the paths (in syntax.php) - I replace:

$conf['baseurl']

with:

$conf['baseurl'].$conf['basedir']

This allows the java app to launch and the GUI displayed. However, then there was the problem with the files not being saved - rendering the plugin practically useless.

I did some further investigations and it looks like it has something to do with CSRF within DokuWiki and mediamanager:

Making your plugins more secure

Looks like media manager uses the checkSecurityToken() function. Thus, that is why uploading the file fails.

For plugins that makes use of this plugin you need to pass it the security plugin. I've changed the syntax.php so that it does this:

$token=getSecurityToken();
$saveurl = $conf['baseurl'].$conf['basedir']."lib/exe/mediamanager.php?sectok=$token";

And this seems to make it work! I need to do more testing to see whether there are any other problems.

I really hope this is the workaround to get this plugin at least working so that further development can proceed. :-D

Monideth Pen 2008/05/04 08:58

New Modified Draw Plugin

I'm using version 2008-05-05 of DokuWiki and had a hard time to get this plugin running. I used some hints from the comments here, hunted some bugs by myself and added some new functions. I think the result can be very useful for others trying to run this nice plugin on newer DokuWikis.

Changes

  • fixed base URLs
  • fixed absent security token
  • fixed multiline label bug (resulted in broken .draw-files)
  • replaced (almost empty) pop-up window with an auto-hiding iframe
  • image reloads automatically after editor frame is closed (no page reloads are needed anymore)
  • editor frame will be centered and/or maximized when started

Install

You can download my version of this plugin from http://stegi.net/dokuwiki/draw.zip (also works with PluginManager).

Don't forget to add the following two lines to conf/mime.local.conf

  draw    text/plain
  map     text/plain

I did not tested the plugin very well. It works for me under Firefox 3 and Sun JRE 1.6.0. If you find some problems please send me an email.

Changes in Java Code

Because of the multiline label bug the java applet required a little fix. The problem was an absent escaping of carriage returns when the .draw-files are generated. As a consequence the editor can't open it and so the image can't be edited anymore when there are some labels with “enter”s in it. This bug may be OS-dependent as carriage returns are used differently as line terminators.

The fix is just an added line at row 107 in StorableOutput.java:

		case '\r': fStream.print('\\'); fStream.print('r'); break;  // line added

I did also a little change a row before where tabulators should be escaped. It was a replace “\t” ⇒ “\\\t” what just seems to be wrong. So I changed it to a replace “\t” ⇒ “\\t”.

The other made changes are in the init-function of LightWeightDrawApplet.java:

protected void init(Frame f) {
  frame = f;
  frame.setSize(640,480);
  frame.setLocationRelativeTo(null);
  frame.pack();
  frame.setExtendedState(Frame.MAXIMIZED_BOTH);
  frame.show();


}

You see… it's only a changed starting behavior. But this may cause that older JVM are excluded as setLocationRelativeTo is introduced in JRE 1.4.

These are the only java code changes of the sources provided above. If you need my sources anyway you can write an email.

Michael Stegbauer 2008-07-04

I have encountered a really annoying issue on my system. This doesn't belong to my changes above cause it also happens with the original code. In fact I don't even think it's a bug of the plugin. The issue occurs sometimes after closing the applet frame regardless whether saved or not. After the editor frame disappears the browser freezes and has to be killed. Because of the freeze I get no information what happened. I've done some tests to isolate the problem: It sometimes happens under WinXP in FF3 and IE7 but almost always in Opera 9.5. I tried Suns JRE 1.6.0_05, 1.6.0_10b and 1.5.0_15 with no differences. In Ubuntu there are no such problems (tested FF3, Opera 9.5 with JRE 1.6).

Please leave a note if you have any hints on this kind of problem.

Michael Stegbauer 2008-07-05

Bug report + solution

I've found a bug in changes introduced by Monideth Pen on 2008/05/04 08:58 concerning adding security token to the $saveurl variable. Even after the user has logged off, a security token still remains in the cached wikipage source. Consequently, any guest visiting our DokuWiki, who hasn't got appropriate rights, can save his changes to the image.

Solutions

I see two possible solutions to this problem:

  • to turn off page caching
  • to do some changes in both syntax.php file and java code, as well as create a new PHP file

The first one is unacceptable if our DokuWiki (or DokuWiki farm) is visited frequently.

In order to keep caching working, I had to do some source-code changes.

Code modifications

First of all I modified syntax.php file:

  • replaced (line 88):
		$saveurl = DOKU_BASE."lib/exe/mediamanager.php?sectok=".getSecurityToken();

with:

		$saveurl = DOKU_BASE."lib/exe/mediamanager.php";
  • added (for example in line 92):
		$sectoken_url = "http://".$_SERVER['SERVER_NAME'].DOKU_BASE."lib/plugins/draw/getSectoken.php";

or you can insert URL in more proper/elegant way

  • add (line 116, in applet params' section):
		<param name='sectoken_url' value='{$sectoken_url}'>\\

Next, I created getSectoken.php file with a content as follows:

<?php
require_once('../../../inc/init.php');
require_once('../../../inc/auth.php');
require_once('../../../inc/common.php');
 
echo getSecurityToken();
?>

Finally, I modified TWikiFrame.java file from CH.ifa.draw.twiki package:

  • at line 74 I added:
	import java.io.BufferedReader;
	import java.io.InputStreamReader;
  • at line 96 I added:
	static private String SECTOKEN_URL = "sectoken_url";
	private String sectoken;
  • at line 105 I added:
	TWikiDraw app = (TWikiDraw)getApplication();
	String sectoken_url = app.getParameter(SECTOKEN_URL);
	if (sectoken_url == null)
		sectoken_url = "";
        try{
        	URL sectokenPage = new URL(sectoken_url);
        	BufferedReader in = new BufferedReader(
        			new InputStreamReader(
        					sectokenPage.openStream()));
        	sectoken = in.readLine();
        	if(sectoken == null)
        		sectoken = "";
        	in.close();
        } catch (MalformedURLException e){
        	System.exit(-1);
        } catch (IOException e){
        	System.exit(-1);
        }
  • at line 442, to the code:
	// gets script name
	String savePath = app.getParameter(SAVEPATH_PARAMETER);
	if (savePath == null)
		savePath = "";

I added:

	else
		savePath = savePath + "?sectok=" + sectoken;

After rebuilding twikidraw.jar and copying all created and modified files everything should work poperly. I hope I didn't miss any modification.

Michal Kolodziejski 2008-07-25

Are you sure this is a real bug? Like Making your plugins more secure says the security token is an extra prevention against cross-site-request-forgery attacks only and neither for authentification nor authorization of the uploader itself. So this token alone should be pretty useless and within a user session there is no difference at all.

A look on the source file inc/common.php [lines 55-78]

/**
 * Return a secret token to be used for CSRF attack prevention
 *
 * @author  Andreas Gohr <andi@splitbrain.org>
 * @link    http://en.wikipedia.org/wiki/Cross-site_request_forgery
 * @link    http://christ1an.blogspot.com/2007/04/preventing-csrf-efficiently.html
 * @return  string
 */
function getSecurityToken(){
  return md5(auth_cookiesalt().session_id());
}
 
/**
 * Check the secret CSRF token
 */
function checkSecurityToken($token=null){
  if(is_null($token)) $token = $_REQUEST['sectok'];
  if(getSecurityToken() != $token){
    msg('Security Token did not match. Possible CSRF attack.',-1);
    return false;
  }
  return true;
}

supports this statement. There is only a token against session matching. The authentification itself should be session based.

Even it isn't neat to leave traces of user data, I don't think it's a security issue. If an attacker sees a token, he doesn't know the matching session. If he hijacked a session, he doesn't care any tokens. Anyway, CSRF attacks are hindered.

But after all this thinking about these tokens, I found another problem. And here your improvement comes quiet right. Assuming that the page view of a user is cached with the user's security token, nobody else can edit (exactly upload) the image cause the tokens will mismatch. I will test this behavior in a while.

I don't run a public wiki so this is not an issue for me, but even users who are not allowed to edit are seeing the edit button, right? There have to be better ways to handle this. I would propose a small JavaScript script which makes a Ajax request checking for edit authorization and only showing the button so. This script can fetch a fresh security token easily too. This way you can overcome the limits of caching. The easy way is just to ~~NOCACHE~~ the page. I think you need a real lot of page viewers to notice a slowdown.

Michael Stegbauer 2008-07-25

Yes, you're right. The bug doesn't concern the security issue but inability to save modified image without prior page edit (which updates sectok in the page's source code). I am working on several DokuWiki modifications at the time and that's why I made a mistake in the problem description.

It's also true, that “Edit” button is visible all the time. Before I wrote my patch, I'd considered writing JavaScript script taking current security token and adding it “on the fly” but I needed the plugin to be working as soon as possible. I believe JavaScript script is better way of solving this issue.

Michal Kolodziejski 2008-07-28

I just installed the http://stegi.net/dokuwiki/draw.zip on version DokuWiki-2009-02-14. It seems to work except for saving the final drawing. I put <draw name=hello> on my page. Then saved the page. The default PNG image shows with an edit link next to it. In the media folder it is putting all the correct files: hello.png, hello.map, and hello.draw, but the PNG default is not replaced by a final drawing after saving. I changed the name of this default file to see if that was the file showing up on my page, and after changing the name the word [diagram] showed up instead of the image. So the only problem is the saving. — David Matson 2009-011-25

plugin/draw.txt · Last modified: 2015-04-04 05:40 by PatrickBrown