1 <?php
2 
3 define('DOKU_INC', realpath(dirname(__FILE__)) . '/../../../../');
4 require_once(DOKU_INC.'inc/init.php');
5 session_write_close();
6 
7 class xcom_save  {
8     private $helper;
9     private $get_media_file = 'wiki.getAttachment';
10     private $mediaArray;
11     private $get_page = 'wiki.getPage';
12     private $save_media_file = 'wiki.putAttachment';
13     private $save_page = 'wiki.putPage';
14     private $remoteClient;
15     private $localClient;
16     private $page;
17     private $data_buffer;
18     private $user;
19 
20     function __construct($local_auth,$remote_auth,$page) {
21         $err = "";
22         $this->helper =  plugin_load('helper', 'xcom');
23 
24         $this->page = $page;
25 
26         if(!$this->page) {
27             $this->msg('nopage');
28             exit;
29         }
30         $secs =  25;
31         while(!($this->localClient = $this->ini_clients($local_auth,true))) {
32             if((time() - $time_start ) > $secs ) {
33             break;
34             }
35             usleep(50);
36         }
37         if(!$this->localClient) {
38              $err .= $this->msg('nolocal',1);
39         }
40         $time_start = time();
41         while(!($this->remoteClient = $this->ini_clients($remote_auth))) {
42             if((time() - $time_start ) > $secs ) {
43             break;
44             }
45             usleep(50);
46         }
47         if(!$this->remoteClient) {
48             $err .= $this->msg('noremote',1);
49         }
50         if($err) {
51            $err .= $this->msg('chkauth',1);
52            echo "$err\n";
53            exit;
54         }
55 
56       $this->msg('success');
57 
58        /*possible to query and save a single media id instead of a page id */
59        if($this->is_media_id($page)) {
60            $this->getMediaFile($page);
61            $this->logoff();
62            exit;
63        }
64 
65     }
66 
67     function msg($which, $ret=false, $nl="\n") {
68        if($ret) return $this->helper->getLang($which) . $nl;
69        echo $this->helper->getLang($which) . $nl;
70     }
71 
72     function ini_clients($credentials,$local=false) {
73         if(is_string($credentials)) {
74             $credentials = json_decode($credentials);
75             if($credentials instanceof stdClass) {
76                 if($local) $this->user = $credentials->user;
77                 return $this->xcom_connect($credentials->url,$credentials->user,$credentials->pwd ,0);
78             }
79        }
80        if(is_array($credentials)) {
81            if($local) $this->user = $credentials['user'];
82            return $this->xcom_connect($credentials['url'],$credentials['user'],$credentials['pwd'] ,0);
83        }
84            return false;
85     }
86     function is_media_id($id) {
87        if(preg_match('/\.(\w{3,4})$/',$id,$matches)) {
88           echo "$id ". $this->msg('ismedia',1," " . $matches[1] . "\n");
89 
90 
91           return true;
92        }
93        return false;
94 
95     }
96     function processMediaArray() {
97         if(!$this->mediaArray)  $this->getMedia();
98         if(!is_array($this->mediaArray)) {
99            $this->msg('nomedia',0, " $this->page.\n");
100            return;
101         }
102         $this->msg('reqmedia');
103         foreach($this->mediaArray as $mfile) {
104             $this->getMediaFile($mfile);
105         }
106     }
107 
108     function getMediaFile($mfile) {
109         $this->data_buffer = "";
110         $this->xcom_get_data( 'wiki.getAttachment',$this->remoteClient,true, array($mfile));
111         if($this->data_buffer) {
112           if(is_array($this->data_buffer)) {
113               echo print_r($this->data_buffer,true);
114             }
115            else {
116                 echo "$mfile " . $this->msg('fsize',true,"") . " " . strlen($this->data_buffer) ."\n";
117                 $this->saveMediaFile($mfile);
118           }
119         }
120         echo "\n";
121     }
122 
123 
124     function getPage() {
125         $auth = $this->xcom_get_data( 'wiki.aclCheck',$this->localClient,false,array($this->page));
126 
127         if($auth < 4) {
128             $this->msg('noperm',false," $this->page\n");
129             $this->logoff();
130             exit;
131         }
132         echo   $this->page . "\n";
133         $this->data_buffer = "";
134         $this->xcom_get_data( 'wiki.getPage',$this->remoteClient,true, array($this->page));
135          if(is_array($this->data_buffer)) {
136               echo print_r($this->data_buffer,true);
137               exit;
138          }
139          usleep(100);
140         $this->savePage();
141     }
142     function savePage() {
143         $resp = $this->xcom_get_data( 'wiki.putPage',$this->localClient,false, array($this->page,$this->data_buffer,array('sum'=>'imported')));
144 
145        if(!$resp) {
146             $this->msg('noimport',false," $this->page\n");
147             $this->logoff();
148             exit;
149         }
150         $this->msg('imported',false," $this->page\n");
151 
152     }
153 
154     function getMedia() {
155        $this->mediaArray=$this->xcom_get_data( 'plugin.xcom.getMedia',$this->remoteClient);
156     }
157 
158     private  function xcom_get_data($task,$client,$use_buffer=false, $params="") {
159 
160          if(!$params) {
161               if($params === false) {
162                   $params = array($task);
163               }
164               else $params = array($task,$this->page);
165          }
166          else {
167            array_unshift($params,$task);
168          }
169 
170            $secs =  5;
171            $time_start = time();
172            while(!($resp = call_user_func_array(array($client,"query"),$params))){
173            if($resp)  echo "resp=$resp\n";
174             if((time() - $time_start ) > $secs ) {
175             break;
176             }
177            usleep(50);
178         }
179 
180             if($use_buffer) {
181                 $this->data_buffer = $client->getResponse();
182                 return;
183              }
184 
185             return $client->getResponse();
186      }
187 
188     function saveMediaFile($id) {
189        $auth = $this->xcom_get_data( 'wiki.aclCheck',$this->localClient,false,array($id));
190 
191         if($auth < 8) {
192             $this->msg('uploadperm',false," $id\n");
193             return;
194         }
195 
196         global $conf;
197         $ftmp = $conf['tmpdir'] . '/' . md5($id.clientIP());
198         // save temporary file
199         @unlink($ftmp);
200         io_saveFile($ftmp, $this->data_buffer);
201         $this->media_save($ftmp,$id,$auth);
202   }
203 
204    function media_save($file_name,$id,$auth=255) {
205        $file = array('name'=>$file_name);
206        $ow = false;
207        $move='rename';
208 
209        $res = media_save($file, $id, $ow, $auth, $move) ;
210        if(is_array($res)) {
211          print_r($res);
212        }
213        else  $this->msg('msave',false," $id\n");
214  }
215 
216     function xcom_connect($url,$user,$pwd, $debug=false) {
217             $url = rtrim($url,'/') . '/lib/exe/xmlrpc.php';
218             $client = new IXR_Client($url);
219             $client->debug = $debug; // enable for debugging
220 
221             $resp = $client->query('dokuwiki.login',$user,$pwd);
222             $ok = $client->getResponse();
223 
224             if($ok) return $client;
225             return false;
226     }
227     function logoff() {
228 
229         $this->msg('logoff');
230         $resp =$this->xcom_get_data( 'dokuwiki.getVersion',$this->localClient,false,false);
231         $this->msg('localdw', false," $resp\n");
232         preg_match('/(\d+)-\d+-\d+/',$resp,$matches);
233         if($matches[1] >= 2014) {
234              $this->msg('logoff',false, " $resp\n");
235              $this->xcom_get_data( 'dokuwiki.logoff',$this->localClient,false,false);
236         }
237         else  $this->msg('nologoff');
238 
239        $resp =$this->xcom_get_data( 'dokuwiki.getVersion',$this->remoteClient,false,false);
240        $this->msg('remotedw', false," $resp\n");
241         preg_match('/(\d+)-\d+-\d+/',$resp,$matches);
242         if($matches[1] >= 2014) {
243              $this->msg('logoff',false, " $resp\n");
244              $this->xcom_get_data( 'dokuwiki.logoff',$this->remoteClient,false,false);
245         }
246         else $this->msg('nologoff');
247     }
248 }
249 global $INPUT;
250 
251 $xcom=new xcom_save($INPUT->post->str('local'),$INPUT->post->str('remote'),$INPUT->post->str('id'));
252 $xcom->getPage();
253 $xcom->getMedia() ;
254 $xcom->processMediaArray();
255 $xcom->logoff();
256 echo "\n";
257 flush();
258