1<?php 2 3use dokuwiki\Handler\Block; 4use dokuwiki\Handler\CallWriter; 5use dokuwiki\Handler\Lists; 6use dokuwiki\Handler\Nest; 7use dokuwiki\Handler\Preformatted; 8use dokuwiki\Handler\Quote; 9use dokuwiki\Handler\Table; 10 11if (!defined('DOKU_PARSER_EOL')) define('DOKU_PARSER_EOL', "\n"); // add this to make handling test cases simpler 12 13class Doku_Handler { 14 15 var $Renderer = null; 16 17 var $CallWriter = null; 18 19 var $calls = array(); 20 21 var $status = array( 22 'section' => false, 23 'doublequote' => 0, 24 ); 25 26 var $rewriteBlocks = true; 27 28 function __construct() { 29 $this->CallWriter = new CallWriter($this); 30 } 31 32 /** 33 * @param string $handler 34 * @param mixed $args 35 * @param integer|string $pos 36 */ 37 function _addCall($handler, $args, $pos) { 38 $call = array($handler,$args, $pos); 39 $this->CallWriter->writeCall($call); 40 } 41 42 function addPluginCall($plugin, $args, $state, $pos, $match) { 43 $call = array('plugin',array($plugin, $args, $state, $match), $pos); 44 $this->CallWriter->writeCall($call); 45 } 46 47 function _finalize(){ 48 49 $this->CallWriter->finalise(); 50 51 if ( $this->status['section'] ) { 52 $last_call = end($this->calls); 53 array_push($this->calls,array('section_close',array(), $last_call[2])); 54 } 55 56 if ( $this->rewriteBlocks ) { 57 $B = new Block(); 58 $this->calls = $B->process($this->calls); 59 } 60 61 trigger_event('PARSER_HANDLER_DONE',$this); 62 63 array_unshift($this->calls,array('document_start',array(),0)); 64 $last_call = end($this->calls); 65 array_push($this->calls,array('document_end',array(),$last_call[2])); 66 } 67 68 /** 69 * fetch the current call and advance the pointer to the next one 70 * 71 * @return bool|mixed 72 */ 73 function fetch() { 74 $call = current($this->calls); 75 if($call !== false) { 76 next($this->calls); //advance the pointer 77 return $call; 78 } 79 return false; 80 } 81 82 83 /** 84 * Special plugin handler 85 * 86 * This handler is called for all modes starting with 'plugin_'. 87 * An additional parameter with the plugin name is passed 88 * 89 * @author Andreas Gohr <andi@splitbrain.org> 90 * 91 * @param string|integer $match 92 * @param string|integer $state 93 * @param integer $pos 94 * @param $pluginname 95 * 96 * @return bool 97 */ 98 function plugin($match, $state, $pos, $pluginname){ 99 $data = array($match); 100 /** @var DokuWiki_Syntax_Plugin $plugin */ 101 $plugin = plugin_load('syntax',$pluginname); 102 if($plugin != null){ 103 $data = $plugin->handle($match, $state, $pos, $this); 104 } 105 if ($data !== false) { 106 $this->addPluginCall($pluginname,$data,$state,$pos,$match); 107 } 108 return true; 109 } 110 111 function base($match, $state, $pos) { 112 switch ( $state ) { 113 case DOKU_LEXER_UNMATCHED: 114 $this->_addCall('cdata',array($match), $pos); 115 return true; 116 break; 117 } 118 } 119 120 function header($match, $state, $pos) { 121 // get level and title 122 $title = trim($match); 123 $level = 7 - strspn($title,'='); 124 if($level < 1) $level = 1; 125 $title = trim($title,'='); 126 $title = trim($title); 127 128 if ($this->status['section']) $this->_addCall('section_close',array(),$pos); 129 130 $this->_addCall('header',array($title,$level,$pos), $pos); 131 132 $this->_addCall('section_open',array($level),$pos); 133 $this->status['section'] = true; 134 return true; 135 } 136 137 function notoc($match, $state, $pos) { 138 $this->_addCall('notoc',array(),$pos); 139 return true; 140 } 141 142 function nocache($match, $state, $pos) { 143 $this->_addCall('nocache',array(),$pos); 144 return true; 145 } 146 147 function linebreak($match, $state, $pos) { 148 $this->_addCall('linebreak',array(),$pos); 149 return true; 150 } 151 152 function eol($match, $state, $pos) { 153 $this->_addCall('eol',array(),$pos); 154 return true; 155 } 156 157 function hr($match, $state, $pos) { 158 $this->_addCall('hr',array(),$pos); 159 return true; 160 } 161 162 /** 163 * @param string|integer $match 164 * @param string|integer $state 165 * @param integer $pos 166 * @param string $name 167 */ 168 function _nestingTag($match, $state, $pos, $name) { 169 switch ( $state ) { 170 case DOKU_LEXER_ENTER: 171 $this->_addCall($name.'_open', array(), $pos); 172 break; 173 case DOKU_LEXER_EXIT: 174 $this->_addCall($name.'_close', array(), $pos); 175 break; 176 case DOKU_LEXER_UNMATCHED: 177 $this->_addCall('cdata',array($match), $pos); 178 break; 179 } 180 } 181 182 function strong($match, $state, $pos) { 183 $this->_nestingTag($match, $state, $pos, 'strong'); 184 return true; 185 } 186 187 function emphasis($match, $state, $pos) { 188 $this->_nestingTag($match, $state, $pos, 'emphasis'); 189 return true; 190 } 191 192 function underline($match, $state, $pos) { 193 $this->_nestingTag($match, $state, $pos, 'underline'); 194 return true; 195 } 196 197 function monospace($match, $state, $pos) { 198 $this->_nestingTag($match, $state, $pos, 'monospace'); 199 return true; 200 } 201 202 function subscript($match, $state, $pos) { 203 $this->_nestingTag($match, $state, $pos, 'subscript'); 204 return true; 205 } 206 207 function superscript($match, $state, $pos) { 208 $this->_nestingTag($match, $state, $pos, 'superscript'); 209 return true; 210 } 211 212 function deleted($match, $state, $pos) { 213 $this->_nestingTag($match, $state, $pos, 'deleted'); 214 return true; 215 } 216 217 218 function footnote($match, $state, $pos) { 219 if (!isset($this->_footnote)) $this->_footnote = false; 220 221 switch ( $state ) { 222 case DOKU_LEXER_ENTER: 223 // footnotes can not be nested - however due to limitations in lexer it can't be prevented 224 // we will still enter a new footnote mode, we just do nothing 225 if ($this->_footnote) { 226 $this->_addCall('cdata',array($match), $pos); 227 break; 228 } 229 $this->_footnote = true; 230 231 $this->CallWriter = new Nest($this->CallWriter,'footnote_close'); 232 $this->_addCall('footnote_open', array(), $pos); 233 break; 234 case DOKU_LEXER_EXIT: 235 // check whether we have already exitted the footnote mode, can happen if the modes were nested 236 if (!$this->_footnote) { 237 $this->_addCall('cdata',array($match), $pos); 238 break; 239 } 240 241 $this->_footnote = false; 242 $this->_addCall('footnote_close', array(), $pos); 243 244 /** @var Nest $reWriter */ 245 $reWriter = $this->CallWriter; 246 $this->CallWriter = $reWriter->process(); 247 break; 248 case DOKU_LEXER_UNMATCHED: 249 $this->_addCall('cdata', array($match), $pos); 250 break; 251 } 252 return true; 253 } 254 255 function listblock($match, $state, $pos) { 256 switch ( $state ) { 257 case DOKU_LEXER_ENTER: 258 $this->CallWriter = new Lists($this->CallWriter); 259 $this->_addCall('list_open', array($match), $pos); 260 break; 261 case DOKU_LEXER_EXIT: 262 $this->_addCall('list_close', array(), $pos); 263 /** @var Lists $reWriter */ 264 $reWriter = $this->CallWriter; 265 $this->CallWriter = $reWriter->process(); 266 break; 267 case DOKU_LEXER_MATCHED: 268 $this->_addCall('list_item', array($match), $pos); 269 break; 270 case DOKU_LEXER_UNMATCHED: 271 $this->_addCall('cdata', array($match), $pos); 272 break; 273 } 274 return true; 275 } 276 277 function unformatted($match, $state, $pos) { 278 if ( $state == DOKU_LEXER_UNMATCHED ) { 279 $this->_addCall('unformatted',array($match), $pos); 280 } 281 return true; 282 } 283 284 function php($match, $state, $pos) { 285 global $conf; 286 if ( $state == DOKU_LEXER_UNMATCHED ) { 287 $this->_addCall('php',array($match), $pos); 288 } 289 return true; 290 } 291 292 function phpblock($match, $state, $pos) { 293 global $conf; 294 if ( $state == DOKU_LEXER_UNMATCHED ) { 295 $this->_addCall('phpblock',array($match), $pos); 296 } 297 return true; 298 } 299 300 function html($match, $state, $pos) { 301 global $conf; 302 if ( $state == DOKU_LEXER_UNMATCHED ) { 303 $this->_addCall('html',array($match), $pos); 304 } 305 return true; 306 } 307 308 function htmlblock($match, $state, $pos) { 309 global $conf; 310 if ( $state == DOKU_LEXER_UNMATCHED ) { 311 $this->_addCall('htmlblock',array($match), $pos); 312 } 313 return true; 314 } 315 316 function preformatted($match, $state, $pos) { 317 switch ( $state ) { 318 case DOKU_LEXER_ENTER: 319 $this->CallWriter = new Preformatted($this->CallWriter); 320 $this->_addCall('preformatted_start',array(), $pos); 321 break; 322 case DOKU_LEXER_EXIT: 323 $this->_addCall('preformatted_end',array(), $pos); 324 /** @var Preformatted $reWriter */ 325 $reWriter = $this->CallWriter; 326 $this->CallWriter = $reWriter->process(); 327 break; 328 case DOKU_LEXER_MATCHED: 329 $this->_addCall('preformatted_newline',array(), $pos); 330 break; 331 case DOKU_LEXER_UNMATCHED: 332 $this->_addCall('preformatted_content',array($match), $pos); 333 break; 334 } 335 336 return true; 337 } 338 339 function quote($match, $state, $pos) { 340 341 switch ( $state ) { 342 343 case DOKU_LEXER_ENTER: 344 $this->CallWriter = new Quote($this->CallWriter); 345 $this->_addCall('quote_start',array($match), $pos); 346 break; 347 348 case DOKU_LEXER_EXIT: 349 $this->_addCall('quote_end',array(), $pos); 350 /** @var Lists $reWriter */ 351 $reWriter = $this->CallWriter; 352 $this->CallWriter = $reWriter->process(); 353 break; 354 355 case DOKU_LEXER_MATCHED: 356 $this->_addCall('quote_newline',array($match), $pos); 357 break; 358 359 case DOKU_LEXER_UNMATCHED: 360 $this->_addCall('cdata',array($match), $pos); 361 break; 362 363 } 364 365 return true; 366 } 367 368 /** 369 * Internal function for parsing highlight options. 370 * $options is parsed for key value pairs separated by commas. 371 * A value might also be missing in which case the value will simple 372 * be set to true. Commas in strings are ignored, e.g. option="4,56" 373 * will work as expected and will only create one entry. 374 * 375 * @param string $options space separated list of key-value pairs, 376 * e.g. option1=123, option2="456" 377 * @return array|null Array of key-value pairs $array['key'] = 'value'; 378 * or null if no entries found 379 */ 380 protected function parse_highlight_options ($options) { 381 $result = array(); 382 preg_match_all('/(\w+(?:="[^"]*"))|(\w+(?:=[^\s]*))|(\w+[^=\s\]])(?:\s*)/', $options, $matches, PREG_SET_ORDER); 383 foreach ($matches as $match) { 384 $equal_sign = strpos($match [0], '='); 385 if ($equal_sign === false) { 386 $key = trim($match[0]); 387 $result [$key] = 1; 388 } else { 389 $key = substr($match[0], 0, $equal_sign); 390 $value = substr($match[0], $equal_sign+1); 391 $value = trim($value, '"'); 392 if (strlen($value) > 0) { 393 $result [$key] = $value; 394 } else { 395 $result [$key] = 1; 396 } 397 } 398 } 399 400 // Check for supported options 401 $result = array_intersect_key( 402 $result, 403 array_flip(array( 404 'enable_line_numbers', 405 'start_line_numbers_at', 406 'highlight_lines_extra', 407 'enable_keyword_links') 408 ) 409 ); 410 411 // Sanitize values 412 if(isset($result['enable_line_numbers'])) { 413 if($result['enable_line_numbers'] === 'false') { 414 $result['enable_line_numbers'] = false; 415 } 416 $result['enable_line_numbers'] = (bool) $result['enable_line_numbers']; 417 } 418 if(isset($result['highlight_lines_extra'])) { 419 $result['highlight_lines_extra'] = array_map('intval', explode(',', $result['highlight_lines_extra'])); 420 $result['highlight_lines_extra'] = array_filter($result['highlight_lines_extra']); 421 $result['highlight_lines_extra'] = array_unique($result['highlight_lines_extra']); 422 } 423 if(isset($result['start_line_numbers_at'])) { 424 $result['start_line_numbers_at'] = (int) $result['start_line_numbers_at']; 425 } 426 if(isset($result['enable_keyword_links'])) { 427 if($result['enable_keyword_links'] === 'false') { 428 $result['enable_keyword_links'] = false; 429 } 430 $result['enable_keyword_links'] = (bool) $result['enable_keyword_links']; 431 } 432 if (count($result) == 0) { 433 return null; 434 } 435 436 return $result; 437 } 438 439 function file($match, $state, $pos) { 440 return $this->code($match, $state, $pos, 'file'); 441 } 442 443 function code($match, $state, $pos, $type='code') { 444 if ( $state == DOKU_LEXER_UNMATCHED ) { 445 $matches = explode('>',$match,2); 446 // Cut out variable options enclosed in [] 447 preg_match('/\[.*\]/', $matches[0], $options); 448 if (!empty($options[0])) { 449 $matches[0] = str_replace($options[0], '', $matches[0]); 450 } 451 $param = preg_split('/\s+/', $matches[0], 2, PREG_SPLIT_NO_EMPTY); 452 while(count($param) < 2) array_push($param, null); 453 // We shortcut html here. 454 if ($param[0] == 'html') $param[0] = 'html4strict'; 455 if ($param[0] == '-') $param[0] = null; 456 array_unshift($param, $matches[1]); 457 if (!empty($options[0])) { 458 $param [] = $this->parse_highlight_options ($options[0]); 459 } 460 $this->_addCall($type, $param, $pos); 461 } 462 return true; 463 } 464 465 function acronym($match, $state, $pos) { 466 $this->_addCall('acronym',array($match), $pos); 467 return true; 468 } 469 470 function smiley($match, $state, $pos) { 471 $this->_addCall('smiley',array($match), $pos); 472 return true; 473 } 474 475 function wordblock($match, $state, $pos) { 476 $this->_addCall('wordblock',array($match), $pos); 477 return true; 478 } 479 480 function entity($match, $state, $pos) { 481 $this->_addCall('entity',array($match), $pos); 482 return true; 483 } 484 485 function multiplyentity($match, $state, $pos) { 486 preg_match_all('/\d+/',$match,$matches); 487 $this->_addCall('multiplyentity',array($matches[0][0],$matches[0][1]), $pos); 488 return true; 489 } 490 491 function singlequoteopening($match, $state, $pos) { 492 $this->_addCall('singlequoteopening',array(), $pos); 493 return true; 494 } 495 496 function singlequoteclosing($match, $state, $pos) { 497 $this->_addCall('singlequoteclosing',array(), $pos); 498 return true; 499 } 500 501 function apostrophe($match, $state, $pos) { 502 $this->_addCall('apostrophe',array(), $pos); 503 return true; 504 } 505 506 function doublequoteopening($match, $state, $pos) { 507 $this->_addCall('doublequoteopening',array(), $pos); 508 $this->status['doublequote']++; 509 return true; 510 } 511 512 function doublequoteclosing($match, $state, $pos) { 513 if ($this->status['doublequote'] <= 0) { 514 $this->doublequoteopening($match, $state, $pos); 515 } else { 516 $this->_addCall('doublequoteclosing',array(), $pos); 517 $this->status['doublequote'] = max(0, --$this->status['doublequote']); 518 } 519 return true; 520 } 521 522 function camelcaselink($match, $state, $pos) { 523 $this->_addCall('camelcaselink',array($match), $pos); 524 return true; 525 } 526 527 /* 528 */ 529 function internallink($match, $state, $pos) { 530 // Strip the opening and closing markup 531 $link = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match); 532 533 // Split title from URL 534 $link = explode('|',$link,2); 535 if ( !isset($link[1]) ) { 536 $link[1] = null; 537 } else if ( preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) { 538 // If the title is an image, convert it to an array containing the image details 539 $link[1] = Doku_Handler_Parse_Media($link[1]); 540 } 541 $link[0] = trim($link[0]); 542 543 //decide which kind of link it is 544 545 if ( link_isinterwiki($link[0]) ) { 546 // Interwiki 547 $interwiki = explode('>',$link[0],2); 548 $this->_addCall( 549 'interwikilink', 550 array($link[0],$link[1],strtolower($interwiki[0]),$interwiki[1]), 551 $pos 552 ); 553 }elseif ( preg_match('/^\\\\\\\\[^\\\\]+?\\\\/u',$link[0]) ) { 554 // Windows Share 555 $this->_addCall( 556 'windowssharelink', 557 array($link[0],$link[1]), 558 $pos 559 ); 560 }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) ) { 561 // external link (accepts all protocols) 562 $this->_addCall( 563 'externallink', 564 array($link[0],$link[1]), 565 $pos 566 ); 567 }elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link[0]) ) { 568 // E-Mail (pattern above is defined in inc/mail.php) 569 $this->_addCall( 570 'emaillink', 571 array($link[0],$link[1]), 572 $pos 573 ); 574 }elseif ( preg_match('!^#.+!',$link[0]) ){ 575 // local link 576 $this->_addCall( 577 'locallink', 578 array(substr($link[0],1),$link[1]), 579 $pos 580 ); 581 }else{ 582 // internal link 583 $this->_addCall( 584 'internallink', 585 array($link[0],$link[1]), 586 $pos 587 ); 588 } 589 590 return true; 591 } 592 593 function filelink($match, $state, $pos) { 594 $this->_addCall('filelink',array($match, null), $pos); 595 return true; 596 } 597 598 function windowssharelink($match, $state, $pos) { 599 $this->_addCall('windowssharelink',array($match, null), $pos); 600 return true; 601 } 602 603 function media($match, $state, $pos) { 604 $p = Doku_Handler_Parse_Media($match); 605 606 $this->_addCall( 607 $p['type'], 608 array($p['src'], $p['title'], $p['align'], $p['width'], 609 $p['height'], $p['cache'], $p['linking']), 610 $pos 611 ); 612 return true; 613 } 614 615 function rss($match, $state, $pos) { 616 $link = preg_replace(array('/^\{\{rss>/','/\}\}$/'),'',$match); 617 618 // get params 619 list($link,$params) = explode(' ',$link,2); 620 621 $p = array(); 622 if(preg_match('/\b(\d+)\b/',$params,$match)){ 623 $p['max'] = $match[1]; 624 }else{ 625 $p['max'] = 8; 626 } 627 $p['reverse'] = (preg_match('/rev/',$params)); 628 $p['author'] = (preg_match('/\b(by|author)/',$params)); 629 $p['date'] = (preg_match('/\b(date)/',$params)); 630 $p['details'] = (preg_match('/\b(desc|detail)/',$params)); 631 $p['nosort'] = (preg_match('/\b(nosort)\b/',$params)); 632 633 if (preg_match('/\b(\d+)([dhm])\b/',$params,$match)) { 634 $period = array('d' => 86400, 'h' => 3600, 'm' => 60); 635 $p['refresh'] = max(600,$match[1]*$period[$match[2]]); // n * period in seconds, minimum 10 minutes 636 } else { 637 $p['refresh'] = 14400; // default to 4 hours 638 } 639 640 $this->_addCall('rss',array($link,$p),$pos); 641 return true; 642 } 643 644 function externallink($match, $state, $pos) { 645 $url = $match; 646 $title = null; 647 648 // add protocol on simple short URLs 649 if(substr($url,0,3) == 'ftp' && (substr($url,0,6) != 'ftp://')){ 650 $title = $url; 651 $url = 'ftp://'.$url; 652 } 653 if(substr($url,0,3) == 'www' && (substr($url,0,7) != 'http://')){ 654 $title = $url; 655 $url = 'http://'.$url; 656 } 657 658 $this->_addCall('externallink',array($url, $title), $pos); 659 return true; 660 } 661 662 function emaillink($match, $state, $pos) { 663 $email = preg_replace(array('/^</','/>$/'),'',$match); 664 $this->_addCall('emaillink',array($email, null), $pos); 665 return true; 666 } 667 668 function table($match, $state, $pos) { 669 switch ( $state ) { 670 671 case DOKU_LEXER_ENTER: 672 673 $this->CallWriter = new Table($this->CallWriter); 674 675 $this->_addCall('table_start', array($pos + 1), $pos); 676 if ( trim($match) == '^' ) { 677 $this->_addCall('tableheader', array(), $pos); 678 } else { 679 $this->_addCall('tablecell', array(), $pos); 680 } 681 break; 682 683 case DOKU_LEXER_EXIT: 684 $this->_addCall('table_end', array($pos), $pos); 685 /** @var Table $reWriter */ 686 $reWriter = $this->CallWriter; 687 $this->CallWriter = $reWriter->process(); 688 break; 689 690 case DOKU_LEXER_UNMATCHED: 691 if ( trim($match) != '' ) { 692 $this->_addCall('cdata',array($match), $pos); 693 } 694 break; 695 696 case DOKU_LEXER_MATCHED: 697 if ( $match == ' ' ){ 698 $this->_addCall('cdata', array($match), $pos); 699 } else if ( preg_match('/:::/',$match) ) { 700 $this->_addCall('rowspan', array($match), $pos); 701 } else if ( preg_match('/\t+/',$match) ) { 702 $this->_addCall('table_align', array($match), $pos); 703 } else if ( preg_match('/ {2,}/',$match) ) { 704 $this->_addCall('table_align', array($match), $pos); 705 } else if ( $match == "\n|" ) { 706 $this->_addCall('table_row', array(), $pos); 707 $this->_addCall('tablecell', array(), $pos); 708 } else if ( $match == "\n^" ) { 709 $this->_addCall('table_row', array(), $pos); 710 $this->_addCall('tableheader', array(), $pos); 711 } else if ( $match == '|' ) { 712 $this->_addCall('tablecell', array(), $pos); 713 } else if ( $match == '^' ) { 714 $this->_addCall('tableheader', array(), $pos); 715 } 716 break; 717 } 718 return true; 719 } 720} 721 722//------------------------------------------------------------------------ 723function Doku_Handler_Parse_Media($match) { 724 725 // Strip the opening and closing markup 726 $link = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match); 727 728 // Split title from URL 729 $link = explode('|',$link,2); 730 731 // Check alignment 732 $ralign = (bool)preg_match('/^ /',$link[0]); 733 $lalign = (bool)preg_match('/ $/',$link[0]); 734 735 // Logic = what's that ;)... 736 if ( $lalign & $ralign ) { 737 $align = 'center'; 738 } else if ( $ralign ) { 739 $align = 'right'; 740 } else if ( $lalign ) { 741 $align = 'left'; 742 } else { 743 $align = null; 744 } 745 746 // The title... 747 if ( !isset($link[1]) ) { 748 $link[1] = null; 749 } 750 751 //remove aligning spaces 752 $link[0] = trim($link[0]); 753 754 //split into src and parameters (using the very last questionmark) 755 $pos = strrpos($link[0], '?'); 756 if($pos !== false){ 757 $src = substr($link[0],0,$pos); 758 $param = substr($link[0],$pos+1); 759 }else{ 760 $src = $link[0]; 761 $param = ''; 762 } 763 764 //parse width and height 765 if(preg_match('#(\d+)(x(\d+))?#i',$param,$size)){ 766 !empty($size[1]) ? $w = $size[1] : $w = null; 767 !empty($size[3]) ? $h = $size[3] : $h = null; 768 } else { 769 $w = null; 770 $h = null; 771 } 772 773 //get linking command 774 if(preg_match('/nolink/i',$param)){ 775 $linking = 'nolink'; 776 }else if(preg_match('/direct/i',$param)){ 777 $linking = 'direct'; 778 }else if(preg_match('/linkonly/i',$param)){ 779 $linking = 'linkonly'; 780 }else{ 781 $linking = 'details'; 782 } 783 784 //get caching command 785 if (preg_match('/(nocache|recache)/i',$param,$cachemode)){ 786 $cache = $cachemode[1]; 787 }else{ 788 $cache = 'cache'; 789 } 790 791 // Check whether this is a local or remote image or interwiki 792 if (media_isexternal($src) || link_isinterwiki($src)){ 793 $call = 'externalmedia'; 794 } else { 795 $call = 'internalmedia'; 796 } 797 798 $params = array( 799 'type'=>$call, 800 'src'=>$src, 801 'title'=>$link[1], 802 'align'=>$align, 803 'width'=>$w, 804 'height'=>$h, 805 'cache'=>$cache, 806 'linking'=>$linking, 807 ); 808 809 return $params; 810} 811 812 813 814//Setup VIM: ex: et ts=4 : 815