1<?php 2 3if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/'); 4include_once(DOKU_INC . 'inc/init.php'); 5if(file_exists(DOKU_INC . 'inc/Remote/Api.php')) { 6require_once(DOKU_INC . 'inc/Remote/ApiCore.php'); 7require_once(DOKU_INC . 'inc/Remote/Api.php'); 8require_once(DOKU_INC . 'inc/IXR_Library.php'); 9} 10else { 11 require_once(DOKU_INC . 'inc/remote.php'); 12 require_once(DOKU_INC . 'inc/RemoteAPICore.php'); 13} 14//require_once('./scripts/createMetaTable.php'); 15global $xcom_timezone, $xcom_current,$xcom_prefix,$conf; 16define ('PAGES', realpath(DOKU_INC . $conf['savedir'])); 17$xcom_timezone = 'UTC'; // default timezone is set to Coordinated Univeral Time. You can reset your timezone here 18class remote_plugin_xcom extends DokuWiki_Remote_Plugin { 19 private $api, $server; 20 public function _getMethods() { 21 return array( 22 'getTime' => array( 23 'args' => array('int'), 24 'return' => 'date' 25 ), 26 'getMedia' => array( 27 'args' => array('string','string'), 28 'return' => 'array', 29 'doc' => 'returns list of media in page id named in args1, args 2 is optional namespace' 30 ), 31 'listNamespaces' => array( 32 'args' => array('string','array'), 33 'return' => 'array', 34 'doc' => 'returns list of wiki namespaces' 35 ), 36 'pageVersions' => array( 37 'args' => array('string','int'), 38 'return' => 'array', 39 'doc' => 'returns list of page versions' 40 ), 41 'getPageInfo' => array( 42 'args' => array('string'), 43 'return' => 'array', 44 'doc' => 'Returns a struct with info about the page, latest version.', 45 'name' => 'pageInfo' 46 ), 47 ' GetMetaData' => array( 48 'args' => 'string', 49 'return' => 'string', 50 'doc' => 'Returns metadata of one or more wiki pages', 51 'name' => 'GetMetaData' 52 ), 53 ); 54 } 55 56 function __construct() { 57 $iswin = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; 58 if(!defined('DIRECTORY_SEPARATOR')) { 59 $iswin ? define("DIRECTORY_SEPARATOR", "\\") : define("DIREC TORY_SEPARATOR", "/"); 60 } 61 if(class_exists("dokuwiki\Remote\APICore")) { 62 $this->api = new dokuwiki\Remote\APICore(new dokuwiki\Remote\Api()); 63 } 64 else $this->api = new RemoteAPICore(new RemoteApi()); 65 } 66 public function getTime($a) { 67 //return date("Y-m-d s",$a); 68 return date("Y-m-d H:i:s",$a); 69 70 } 71 72 73 public function listNamespaces($namespace="",$mask="") { 74 global $conf; 75 $rootns = $conf['savedir']; 76 $rootns = ltrim($rootns,'./'); 77 if($rootns == 'data') { 78 $rootns = DOKU_INC . $rootns; 79 } 80 81 if(!$namespace) { 82 $namespace = $rootns; 83 } 84 else $namespace = $rootns . '/pages/'. $namespace; 85 $namespace = rtrim($namespace, '/'); 86 $folder_list = array(); 87 88 $regex=''; 89 $mask = trim($mask); 90 if($mask) { 91 $mask= json_decode($mask); 92 for($i=0; $i<count($mask) ;$i++) { 93 $mask[$i] = preg_quote($mask[$i]); 94 } 95 if(count($mask) > 1) { 96 $regex = implode('|',$mask); 97 } 98 else if(is_array($mask)) { 99 $regex = $mask[0]; 100 } 101 else $regex = $mask; 102 $regex = "($regex)\b"; 103 } 104 105 $result =$this->find_all_files($namespace,$regex); 106 107 $regex = '#' . preg_quote($rootns) .'#'; 108 109 for($i=0;$i<count($result); $i++) { 110 $result[$i] = preg_replace($regex,"",$result[$i]); 111 $result[$i] = preg_replace("/\/?pages/","",$result[$i]); 112 $result[$i] = str_replace('/',':',$result[$i]); 113 114 } 115 return $result; 116 117 118 } 119 120 /** 121 * Based on find_all_files() by kodlee at kodleeshare dot net 122 * at http://ca3.php.net/scandir: 123 */ 124 function find_all_files($dir,$regex="") 125 { 126 $root = scandir($dir); 127 128 foreach($root as $value) 129 { 130 if($value === '.' || $value === '..') {continue;} 131 if($regex) if(preg_match('#'. $regex .'#',"$dir/$value")) {continue;} 132 if(is_dir("$dir/$value") && is_readable("$dir/$value")) { 133 $result[]="$dir/$value"; 134 foreach($this->find_all_files("$dir/$value",$regex) as $value) 135 { if(!$regex) { 136 $result[]="$value"; 137 } 138 else if(! preg_match('#'. $regex .'#',"$dir/$value")) { 139 $result[]="$value"; 140 } 141 142 } 143 } 144 } 145 if(isset($result)) return $result; 146 return array(); 147 } 148 149 public function getMedia($id,$namespace="") { 150 if($namespace) { 151 $id = "$namespace:$id"; 152 } 153 $path = metaFN($id,'.meta'); 154 155 156 if(@file_exists($path)) { 157 $inf_str = file_get_contents($path); 158 $inf = @unserialize($inf_str); 159 if($inf['current']['relation']['media']) { 160 return array_keys($inf['current']['relation']['media']); 161 } 162 163 $filename = wikiFN($id); 164 if(@file_exists($filename)) { 165 $str = file_get_contents($filename ); 166 if(strpos($str,'{{') === false) return "0"; 167 preg_match_all('/{{(.*?)}}/ms',$str,$matches); 168 $media = array(); 169 foreach($matches[1] as $file) { 170 $result = explode('|', $file); 171 $result = explode('?',$result[0]); 172 $result = trim($result[0]); 173 if(strpos($result,'http://')=== false && strpos($result,'>') === false ){ 174 $media[$result] = 1; 175 } 176 } 177 $media = array_keys($media); 178 if(!empty($media) ) { 179 return $media; 180 } 181 } 182 183 return "no media data in $path"; 184 } 185 return "no data for $id"; 186 } 187 188 /** 189 * Returns a list of available revisions of a given wiki page 190 * Number of returned pages is set by $conf['recent'] 191 * However not accessible pages are skipped, so less than $conf['recent'] could be returned 192 * 193 * @author Michael Klier <chi@chimeric.de> 194 * 195 * @param string $id page id 196 * @param int $first skip the first n changelog lines 197 * 0 = from current(if exists) 198 * 1 = from 1st old rev 199 * 2 = from 2nd old rev, etc 200 * @return array 201 */ 202 public function pageVersions($id, $first = 0) 203 { 204 header("Access-Control-Allow-Origin: *"); 205 return json_encode($this->api->pageVersions($id, $first)); 206} 207 208 209 210 211 /** 212 * Return some basic data about a page 213 * 214 * @param string $id page id 215 * @param string|int $rev revision timestamp or empty string 216 * @return array 217 * @throws AccessDeniedException no access for page 218 * @throws RemoteException page not exist 219 */ 220 public function pageInfo($id, $rev = '') { 221 $info = $this->api-> pageInfo($id, $rev = ''); 222 $info['lastModified'] = $this->getTime($info['lastModified']); 223 return json_encode($info); 224 } 225 226 private function resolvePageId($id) 227 { 228 $id = cleanID($id); 229 if (empty($id)) { 230 global $conf; 231 $id = cleanID($conf['start']); 232 } 233 return $id; 234 } 235 236 function GetMetaData($id) { 237 global $xcom_timezone, $xcom_current,$xcom_prefix,$conf; 238 $contents=""; 239 date_default_timezone_set($xcom_timezone); 240 $xcom_prefix = preg_replace("/.*?\/data\/meta/", "", $conf['metadir']); 241 $xcom_prefix = ($depth = str_replace('/', ':', $xcom_prefix)) ? $depth : ''; 242 if($id === ':' || preg_match("/\:\*$/",$id)) { 243 $id = rtrim($id,':*'); 244 $ns = $conf['metadir'] .'/'. $id; 245 246 chdir($ns); 247 $this->recurse('.',$contents); 248 } 249 else { 250 251 $file = metaFN($id,'.meta'); 252 $this->get_data($file,$id,$contents); 253 } 254 255 256 $contents = str_replace("<table.*?>\n</table>","",$contents); 257 return $contents; 258 259} 260 261 262function recurse($dir,&$contents) { 263 global $xcom_prefix; 264 $dh = opendir($dir); 265 if (!$dh) return; 266 $cur_dir = '/pages' . preg_replace('#^.*?data/meta#',"", getcwd()); 267 while (($file = readdir($dh)) !== false) { 268 if ($file == '.' || $file == '..') continue; 269 270 if (is_dir("$dir/$file")) { 271 $this->recurse("$dir/$file",$contents); 272 } 273 if (preg_match("/\.meta$/", $file)) { 274 $store_name = preg_replace('/^\./', $xcom_prefix, "$dir/$file"); 275 $id_name = PAGES ."$cur_dir${store_name}"; 276 $id_name = preg_replace('/\.meta$/', '.txt',$id_name); 277 $this->get_data("$dir/$file",$id_name,$contents); 278 $contents .= "\n"; 279 } 280 } 281 282 closedir($dh); 283} 284function get_data($file,$id_path,&$contents) { 285 global $xcom_current; 286 $data = file_get_contents($file); 287 $data_array = @unserialize(file_get_contents($file)); 288 $creator =""; $creator_id=""; 289 290 if ($data_array === false || !is_array($data_array)) return; 291 if (!isset($data_array['current'])) return; 292 $contents .= "\n<p>\n"; 293 $contents .= "\n" . '<table style="border-top:2px solid">' ."\n"; 294 $contents .= "<tr><td colspan='2'>$id_path</td></tr>\n"; 295 $contents .= "<tr><td colspan='2'>$file</td></tr>\n"; 296 $xcom_current = $data_array['current']; 297 $keys = array('title','date','creator','last_change','relation'); 298 foreach ($keys AS $header) { 299 switch($header) { 300 case 'title': 301 $title = $this->getcurrent($header, null); 302 $contents .= "<tr><td colspan='2'>Title: <b>$title</b></td></tr>\n"; 303 break; 304 305 case 'date': 306 $this->process_dates($this->getcurrent('date', 'created'),$this->getcurrent('date', 'modified'),$contents); 307 break; 308 case 'user': 309 if($creator || $creator_id) break; 310 case 'creator': 311 $creator = $this->getcurrent('creator', null); 312 $creator_id = $this->getcurrent('user', null); 313 $this->process_users($creator,$creator_id,$contents); 314 break; 315 316 case 'last_change': 317 $last_change = $this->getSimpleKeyValue($this->getcurrent($header, null),"last_change",$contents); 318 if($last_change) { 319 $contents .= "<tr><td colspan='3' ></td>\n"; 320 $contents .= "<tr><td colspan='2' style='border-left: 2px solid #4169E1; color:#4169E1' ><b>Last Change</b></td>\n"; 321 $contents .= "<td>$last_change</td></tr>\n"; 322 } 323 break; 324 case 'contributor': 325 $this->contributors = $this->getSimpleKeyValue($this->getcurrent($header, null),$contents); 326 break; 327 case 'relation': 328 $isreferencedby = $this->getcurrent($header,'isreferencedby'); 329 $references = $this->getcurrent($header,'references'); 330 $media = $this->getcurrent($header,'media'); 331 $firstimage = $this->getcurrent($header,'firstimage'); 332 $haspart = $this->getcurrent($header,'haspart'); 333 $subject = $this->getcurrent($header,'subject'); 334 $this->process_relation($isreferencedby,$references,$media,$firstimage,$haspart,$subject,$contents); 335 break; 336 default: 337 338 break; 339 } 340 341 } 342 $contents .= "\n</table></p>\n"; 343 $xcom_current = array(); 344} 345 346/* 347* @param array $ar metadata field 348* @param string $which which field 349*/ 350function getSimpleKeyValue($ar,$which="",&$contents) { 351 $retv = ""; 352 $types = array('C'=>'<u>C</u>reate','E'=>'<u>E</u>dit','e' =>'minor <u>e</u>dit','D'=>'<u>D</u>elete', 353 'R'=>'<u>R</u>evert'); 354 if(!is_array($ar)) return false; 355 $border = ""; 356 foreach ($ar As $key=>$val) { 357 if(!empty($val)) { 358 if($which == 'last_change') { 359 $border = " style='border-left: 2px solid #4169E1;'"; 360 if($key == 'date') { 361 $val = date("r", $val); 362 } 363 if($key == 'type') { 364 $val = $types[$val]; 365 } 366 } 367 368 if(empty($val)) { 369 $retv .= "<tr><td $border>$key:</td><td>$val</td></tr>\n"; 370 } 371 else $retv .= "<tr><td $border>$key:</td><td>$val</td></tr>\n"; 372 } 373 } 374 return $retv; 375} 376 377function process_users($creator,$user,&$contents) { 378 if(empty($creator)) { 379 $contents .= "\n"; return; 380 } 381 $contents .= "<tr><td>Created by:</td><td> $creator (userid: $user)</tr></td>\n"; 382} 383 384function process_dates($created, $modified,&$contents) { 385 $retv = ""; 386 387 if ($created) { 388 $rfc_cr = date("r", $created); 389 $contents .= "<tr><td>Date created:</td><td>".$rfc_cr. 390 "</td><td>$created</td></tr>\n"; 391 } 392 393 if ($modified) { 394 $rfc_mod = date("r", $modified); 395 $contents .= "<tr><td>Last modified:</td><td>" . $rfc_mod . 396 "</td><td>$modified</td></tr>\n"; 397 } 398 399} 400 401function insertListInTable($list,$type,&$contents) { 402 $border = " style='border-left: 2px solid green;'"; 403 if($list) $contents .= "<tr><td $border>$type</td><td>$list</td></tr>\n"; 404} 405function process_relation($isreferencedby,$references,$media,$firstimage,$haspart,$subject,&$contents) { 406 if(!empty($isreferencedby) || !empty($references) || !empty($media) || !empty($firstimage) 407 && !empty($haspart ) &&!empty($subject)) { 408 $border = " style='border-left: 2px solid green;'"; 409 $contents .= "<tr><td colspan='3' ></td>\n"; 410 $contents .= "<tr><td colspan='2' $border><b><span style='color:green'>Relation</span></b></td>\n"; 411 } 412 else $border = ""; 413 if(!empty($isreferencedby)) { 414 $list = $this->create_list(array_keys($isreferencedby),$contents); 415 $this->insertListInTable($list,'Backlinks (isreferencedby)',$contents); 416 } 417 if(!empty($references)) { 418 $list = $this->create_list(array_keys($references),$contents); 419 $this->insertListInTable($list,'Links (references)',$contents); 420 } 421 if(!empty($media)) { 422 $list = $this->create_list(array_keys($media),$contents); 423 $this->insertListInTable($list,'Media',$contents); 424 } 425 if(!empty($firstimage)) { 426 $contents .= "<tr><td $border>First Image</td><td>$firstimage</td></tr>"; 427 } 428 if(!empty($haspart)) { 429 $list = $this->create_list(array_keys($haspart),$contents); 430 $this->insertListInTable($list,'haspart',$contents); 431 } 432 if(!empty($subject)) { 433 $list = $this->create_list(array_keys($subject),$contents); 434 $this->insertListInTable($list,'Subject',$contents); 435 } 436 437} 438 439function create_list($ar,&$contents) { 440 $list = "\n<ol>\n"; 441 for($i=0; $i<count($ar); $i++) { 442 $list .= '<li>'. $ar[$i] . "</li>\n"; 443 } 444 $list .= "</ol>\n"; 445 return $list; 446} 447function getcurrent($which, $other) { 448 global $xcom_current; 449 if (!isset($xcom_current)) return ""; 450 if ($other) { 451 if (isset($xcom_current[$which][$other])) { 452 return $xcom_current[$which][$other]; 453 } 454 } 455 if (isset($xcom_current[$which]) && $other === null) { 456 return $xcom_current[$which]; 457 } 458 return ""; 459} 460} 461 462 463