1/*
2 * HTML Parser By John Resig (ejohn.org)
3 * Original code by Erik Arvidsson, Mozilla Public License
4 * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
5 * @license    GPL 3 or later (http://www.gnu.org/licenses/gpl.html)
6*/
7
8var HTMLParser;
9var HTMLParserInstalled=true;
10var HTMLParser_Elements = new Array();
11(function(){
12
13	// Regular Expressions for parsing tags and attributes
14	var startTag = /^<(\w+)((?:\s+[\w-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
15		endTag = /^<\/(\w+)[^>]*>/,
16		attr = /([\w-]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
17
18	// Empty Elements - HTML 4.01
19	var empty = makeMap("br,col,hr,img");
20   // HTMLParser_Elements['empty'] = empty;
21
22	// Block Elements - HTML 4.01
23	var block = makeMap("blockquote,center,del,div,dl,dt,hr,iframe,ins,li,ol,p,pre,table,tbody,td,tfoot,th,thead,tr,ul");
24  //  HTMLParser_Elements['block'] = block;
25
26	// Inline Elements - HTML 4.01
27	var inline = makeMap("a,abbr,acronym,b,big,br,cite,code,del,em,font,h1,h2,h3,h4,h5,h6,i,img,ins,kbd,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var");
28
29	// Elements that you can, intentionally, leave open
30	// (and which close themselves)
31	var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
32
33	// Attributes that have their values filled in disabled="disabled"
34	var fillAttrs = makeMap("checked,disabled,ismap,noresize,nowrap,readonly,selected");
35
36	// Special Elements (can contain anything)
37	var special = makeMap("script,style");
38
39   //define ('BROKEN_IMAGE', DOKU_URL . 'lib/plugins/ckgedit/fckeditor/userfiles/blink.jpg?nolink&33x34');
40   var broken_image ='http://' +  location.host +  DOKU_BASE +  '/lib/plugins/ckgedit/fckeditor/userfiles/blink.jpg?nolink&33x34';
41	HTMLParser = this.HTMLParser = function( html, handler ) {
42		var index, chars, match, stack = [], last = html;
43
44      html =  html.replace(/(<img.*?src="data:image\/\w+;base64,\s*)(.*?)(\/>)/gm,
45                  function(match, p1, p2) {
46                  var skip = false;
47                   if(p1.match(/msword/) ) {
48                       skip = true;
49                       match = match.replace(/msword/,"");
50                   }
51                   if(p2.length > 2500000 && !skip ) {
52                        jQuery('#dw__editform').append('<input type="hidden" id="broken_image" name="broken_image" value="' + p2.length +'" />');
53                        return  '{{' + broken_image + '}}';
54                    }
55                    return match;
56           });
57          html = html.replace(/~~OPEN_HTML_BLOCK~~/gm , '~~START_HTML_BLOCK~~') ;
58          html = html.replace(/~~END_HTML_BLOCK~~/gm , '~~CLOSE_HTML_BLOCK~~') ;
59
60          if(html.match(/~~START_HTML_BLOCK~~/gm) ){            //adopted [\s\S] from Goyvaerts, Reg. Exp. Cookbook (O'Reilly)
61              if(!JSINFO['htmlok']) {
62                 html = html.replace(/~~START_HTML_BLOCK~~|~~CLOSE_HTML_BLOCK~~/gm,"");
63                }
64
65             html = html.replace(/(<p>)*\s*~~START_HTML_BLOCK~~\s*(<\/p>)*([\s\S]+)~~CLOSE_HTML_BLOCK~~\s*(<\/p>)*/gm, function(match,p,p1,text,p2) {
66             text = text.replace(/<\/?div.*?>/gm,"");
67             text = text.replace(/<code>/gm,"");
68             text = text.replace(/<\/code>/gm,"");
69             text = text.replace(/</gm,"&lt;");
70             text = text.replace(/<\//gm,"&gt;");
71             return  "~~START_HTML_BLOCK~~\n\n" +   text  + "\n\n~~CLOSE_HTML_BLOCK~~\n\n";
72         });
73        }
74        /* remove dwfck note superscripts from inside links */
75        html = html.replace(/(<sup\s+class=\"dwfcknote fckgL\d+\"\>fckgL\d+\s*\<\/sup\>)\<\/a\>/gm, function(match,sup,a) {
76             return( '</a>' +sup);
77         }
78       );
79     /* remove html5 attributes */
80	 var pos = html.indexOf('data-');
81     if(pos != -1) {
82       html = html.replace(/(<\w+)([^>]+)>/gm,function(match,tag,atts){
83            atts = atts.replace(/data-[\w\-]+\s*=\s*(\"|\')\w+(\"|\')/,"");
84            //alert(atts);
85             return tag + atts+ '>';
86	  });
87	}
88		stack.last = function(){
89			return this[ this.length - 1 ];
90		};
91
92		while ( html ) {
93			chars = true;
94
95			// Make sure we're not in a script or style element
96			if ( !stack.last() || !special[ stack.last() ] ) {
97
98				// Comment
99				if ( html.indexOf("<!--") == 0 ) {
100					index = html.indexOf("-->");
101
102					if ( index >= 0 ) {
103						if ( handler.comment )
104							handler.comment( html.substring( 4, index ) );
105						html = html.substring( index + 3 );
106						chars = false;
107					}
108
109				// end tag
110				} else if ( html.indexOf("</") == 0 ) {
111					match = html.match( endTag );
112
113					if ( match ) {
114						html = html.substring( match[0].length );
115						match[0].replace( endTag, parseEndTag );
116						chars = false;
117					}
118
119				// start tag
120				} else if ( html.indexOf("<") == 0 ) {
121					match = html.match( startTag );
122
123					if ( match ) {
124						html = html.substring( match[0].length );
125						match[0].replace( startTag, parseStartTag );
126						chars = false;
127					}
128				}
129
130				if ( chars ) {
131					index = html.indexOf("<");
132
133					var text = index < 0 ? html : html.substring( 0, index );
134					html = index < 0 ? "" : html.substring( index );
135
136					if ( handler.chars )
137						handler.chars( text );
138				}
139
140			} else {
141				html = html.replace(new RegExp("(.*)<\/" + stack.last() + "[^>]*>"), function(all, text){
142					text = text.replace(/<!--(.*?)-->/g, "$1")
143						.replace(/<!\[CDATA\[(.*?)]]>/g, "$1");
144
145					if ( handler.chars )
146						handler.chars( text );
147
148					return "";
149				});
150
151				parseEndTag( "", stack.last() );
152			}
153
154			if ( html == last )
155				throw "Parse Error: " + html;
156			last = html;
157		}
158
159		// Clean up any remaining tags
160		parseEndTag();
161
162		function parseStartTag( tag, tagName, rest, unary ) {
163			if ( block[ tagName ] ) {
164				while ( stack.last() && inline[ stack.last() ] ) {
165					parseEndTag( "", stack.last() );
166				}
167			}
168
169			if ( closeSelf[ tagName ] && stack.last() == tagName ) {
170				parseEndTag( "", tagName );
171			}
172
173			unary = empty[ tagName ] || !!unary;
174
175			if ( !unary )
176				stack.push( tagName );
177
178			if ( handler.start ) {
179				var attrs = [];
180
181				rest.replace(attr, function(match, name) {
182					var value = arguments[2] ? arguments[2] :
183						arguments[3] ? arguments[3] :
184						arguments[4] ? arguments[4] :
185						fillAttrs[name] ? name : "";
186
187					attrs.push({
188						name: name,
189						value: value,
190						escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
191					});
192				});
193
194				if ( handler.start )
195					handler.start( tagName, attrs, unary );
196			}
197		}
198
199		function parseEndTag( tag, tagName ) {
200			// If no tag name is provided, clean shop
201			if ( !tagName )
202				var pos = 0;
203
204			// Find the closest opened tag of the same type
205			else
206				for ( var pos = stack.length - 1; pos >= 0; pos-- )
207					if ( stack[ pos ] == tagName )
208						break;
209
210			if ( pos >= 0 ) {
211				// Close all the open elements, up the stack
212				for ( var i = stack.length - 1; i >= pos; i-- )
213					if ( handler.end )
214						handler.end( stack[ i ] );
215
216				// Remove the open elements from the stack
217				stack.length = pos;
218			}
219		}
220	};
221
222
223	function makeMap(str){
224		var obj = {}, items = str.split(",");
225		for ( var i = 0; i < items.length; i++ )
226			obj[ items[i] ] = true;
227		return obj;
228	}
229})();
230
231
232function HTMLParser_test_result(results) {
233
234var test_str = "";
235for ( i=0; i < results.length; i++) {
236   var character = results.charAt(i);
237   if(results.charCodeAt(i) == 10)
238         character ='\\n';
239   if(results.charCodeAt(i) == 32)
240         character ='SP';
241   var entry =  character + ' ';
242
243  test_str += entry;
244  if(results.charCodeAt(i) == 10) {
245       test_str += "\n";
246   }
247}
248
249if(!confirm(test_str)) return false;
250return true;
251
252}
253
254function hide_backup_msg() {
255  document.getElementById("backup_msg").style.display="none";
256  return false;
257}
258
259function show_backup_msg(msg) {
260  document.getElementById("backup_msg").style.display="block";
261  document.getElementById("backup_msg_area").innerHTML = "Backed up to: " + msg;
262
263  return false;
264}
265
266  // legacy functions
267 function remove_draft(){
268 }
269
270function dwedit_draft_delete() {
271}
272  // legacy functions  end
273
274  function setEdHeight(h) {
275        h = parseInt(h);
276        document.cookie = 'ckgEdht=' + h +';expires=0;path=' +JSINFO['doku_base'] + ';SameSite=Lax;';
277   }
278
279   /* enable disable image paste */
280  function ckgd_setImgPaste(which) {
281      var state = JSINFO['ckgEdPaste'] ? JSINFO['ckgEdPaste']  : "";
282      if(state == 'on')  {
283            which = 'off'
284      }
285      else which = 'on';
286      JSINFO['ckgEdPaste'] = which;
287       document.cookie = 'ckgEdPaste=' + which +';expires="Thu, 18 Dec 2575 12:00:00 UTC";path=' +JSINFO['doku_base'];
288      alert(LANG.plugins.ckgedit.ckg_paste_restart + ' ' + LANG.plugins.ckgedit[which]);
289   }
290
291   function ckg_RawImgMsg() {
292       return LANG.plugins.ckgedit.broken_image_1 + "\n" +  LANG.plugins.ckgedit.broken_image_2 ;
293   }
294  function GetE(e) {
295       return  document.getElementById(e);
296  }
297var dokuBase = location.host + DOKU_BASE;
298
299 if(window.getSelection != undefined) {
300    var doku_ckg_getSelection = window.getSelection;
301    window.getSelection = function(ta) {
302        if(!ta) ta = GetE("wiki__text");
303        return doku_ckg_getSelection(ta);
304    };
305 }
306
307 function ckgedit_seteditor_priority(m,client,dw_val_obj) {
308       var which = {'Y': 'Dokuwiki', 'N': 'CKEditor'};
309
310       if (typeof m === "undefined") {  // Safari
311               if(dw_val_obj[0].checked) {
312                   m= dw_val_obj[0].value;
313               }
314              else if(dw_val_obj[1].checked) {
315                           m = dw_val_obj[1].value;
316              }
317       }
318        var params = "dw_val=" +  m;   params += '&call=cked_selector';    params += "&dwp_client=" + client;
319        jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', params,
320                function (data) {
321                    if(data == 'done') {
322                        if(!m)
323                             alert(LANG.plugins.ckgedit.dwp_not_sel);
324                          else
325                             alert(LANG.plugins.ckgedit.dwp_updated + which[m]);
326                    }
327                      else  {
328                          alert(LANG.plugins.ckgedit.dwp_save_err + data);
329                      }
330                    },
331                'html'
332            );
333 }
334
335 /* gets both size and filetime: "size||filetime" */
336 function ckged_get_unlink_size(id) {
337                var params = 'call=cked_deletedsize';    params += "&cked_delid=" + id;
338                jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', params,
339                function (data) {
340                    if(data) {
341                     JSINFO['ckg_del_sz'] = data;
342                      //console.log(data);
343                    }
344                      else  {
345                    //      alert(LANG.plugins.ckgedit.dwp_save_err + data);
346                      }
347                    },
348                'html'
349            );
350
351 }
352
353 function ckged_setmedia(id,del, refresh_cb) {
354
355             var params = 'call=cked_upload';    params += "&ckedupl_id=" + id;
356             if(del)  params += "&ckedupl_del=D&delsize="+JSINFO['ckg_del_sz'];
357                jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', params,
358                function (data) {
359                    if(data) {
360                      if(refresh_cb) {
361                           refresh_cb.postMessage(JSINFO['doku_url'], JSINFO['doku_url']);
362                      }
363                    //  console.log(data);
364                    }
365                      else  {
366                    //      alert(LANG.plugins.ckgedit.dwp_save_err + data);
367                      }
368                    },
369                'html'
370            );
371 }
372
373jQuery(function() {
374     if(JSINFO['hide_captcha_error'] =='hide') {
375         jQuery("div.error").hide();
376     }
377 });
378
379
380jQuery(function() {
381    jQuery( "#editor_height" ).keydown(function(event) {
382          if ( event.which == 13 ) {
383           event.preventDefault();
384        }
385    });
386
387    $dokuWiki = jQuery('.dokuwiki');
388     jQuery('.editbutton_table button').click(function() {
389           var f = this.form;
390           jQuery('<input />').attr('type','hidden').attr('name','mode').attr('value','dwiki').appendTo(jQuery(f));
391            jQuery('<input />').attr('type','hidden').attr('name','fck_preview_mode').attr('value','nil').appendTo(jQuery(f));
392    });
393
394    if(typeof(JSINFO['dbl_click_auth'] !== 'undefined') && JSINFO['dbl_click_auth'] == "") return;
395    if(!JSINFO['ckg_dbl_click']) return;
396
397    /**
398     * If one or more edit section buttons exist?
399     * This makes sure this feature is enabled only on the edit page and for users with page edit rights.
400     */
401    if (jQuery('.editbutton_section', $dokuWiki).length > 0) {
402
403        // register double click event for all headings and section divs
404        jQuery('[class^="sectionedit"], div[class^="level"]', $dokuWiki).dblclick(function(){
405            // find the closest edit button form to the element double clicked (downwards) and submit the form
406            var f =  jQuery(this).nextAll('.editbutton_section:eq(0)').children('form:eq(0)');
407            //alert(jQuery(f).hasClass('button'));
408            jQuery('<input />').attr('type','hidden').attr('name','mode').attr('value','dwiki').appendTo(jQuery(f));
409            jQuery('<input />').attr('type','hidden').attr('name','fck_preview_mode').attr('value','nil').appendTo(jQuery(f));
410            f.submit();
411        })
412    }
413
414   if(JSINFO['ckg_template'].match(/bootstrap/) && jQuery('div.editButtons').length>0) {
415      // var n=jQuery('div.editButtons input').length;
416       jQuery( "div.editButtons input").each(function( index ) {
417           if(jQuery(this).hasClass('btn-success')) {
418               jQuery(this).removeClass('btn-success')
419           }
420           if(jQuery(this).hasClass('btn-danger')) {
421               jQuery(this).removeClass('btn-danger');
422           }
423
424     });
425
426   }
427
428});
429
430function ckg_edit_mediaman_insert(edid, id, opts, dw_align) {
431    var link, width, s, align;
432
433    //parse option string
434    var options = opts.substring(1).split('&');
435
436    //get width and link options
437    link = 'detail';
438    for (var i in options) {
439        var opt = options[i];
440        if (typeof opt !== 'string') {
441            continue;
442        }
443         if (opt.match(/^\d+$/)) {
444            width = opt;
445        } else  if (opt.match(/^\w+$/)) {
446            link = opt;
447        }
448    }
449
450    //get alignment option
451    switch (dw_align) {
452    case '2':
453        align = 'medialeft';
454        break;
455    case '3':
456        align = 'mediacenter';
457        break;
458    case '4':
459        align = 'mediaright';
460        break;
461    default:
462        align = '';
463        break;
464    }
465
466    var funcNum = CKEDITOR.instances.wiki__text._.filebrowserFn;
467    var fileUrl = DOKU_BASE + 'lib/exe/fetch.php?media=' + id;
468    CKEDITOR.tools.callFunction(funcNum, fileUrl, function() {
469        var dialog = this.getDialog();
470        if ( dialog.getName() == "image" ) {
471            if (align != null) {
472                dialog.getContentElement("info", "cmbAlign").setValue(align);
473            }
474            if (link != null) {
475                dialog.getContentElement("info", "cmbLinkType").setValue(link);
476            }
477            if (width != null) {
478                dialog.getContentElement("info", "txtWidth").setValue(width);
479                dialog.dontResetSize = true;
480            }
481        }
482    });
483}
484
485function ckg_edit_mediaman_insertlink(edid, id, opts, dw_align) {
486    var funcNum = CKEDITOR.instances.wiki__text._.filebrowserFn;
487    CKEDITOR.tools.callFunction(funcNum, id, function() {
488        var dialog = this.getDialog();
489        if (dialog.getName() == "link") {
490            dialog.getContentElement('info', 'media').setValue(id);
491        }
492    });
493}
494
495function getCookie(name) {
496    var re = new RegExp(name + "=([^;]+)");
497    var value = re.exec(document.cookie);
498    return (value != null) ? decodeURIComponent(value[1]) : null;
499}
500function ckg_admininfo(t){
501	if(t.innerHTML == LANG.plugins.ckgedit.stylesheet_cinfo)
502	  t.innerHTML = LANG.plugins.ckgedit.stylesheet_oinfo;
503    else t.innerHTML = LANG.plugins.ckgedit.stylesheet_cinfo;
504}
505
506  /* DOKUWIKI:include_once locktimer.js */
507
508