OSDN Git Service

Remove media selector, use media query
[pukiwiki/pukiwiki.git] / lib / backup.php
1 <?php
2 /**
3  *
4  * PukiWiki - Yet another WikiWikiWeb clone.
5  *
6  * backup.php
7  *
8  * バックアップを管理する
9  *
10  * @package org.pukiwiki
11  * @access  public
12  * @author
13  * @create
14  * Copyright (C)
15  *   2002-2016 PukiWiki Development Team
16  *   2001-2002 Originally written by yu-ji
17  * License: GPL v2 or (at your option) any later version
18  **/
19
20 /**
21  * make_backup
22  * バックアップを作成する
23  *
24  * @access    public
25  * @param     String    $page        ページ名
26  * @param     Boolean   $delete      TRUE:バックアップを削除する
27  *
28  * @return    Void
29  */
30
31 function make_backup($page, $is_delete, $wikitext)
32 {
33         global $cycle, $maxage;
34         global $do_backup, $del_backup;
35         global $auth_user;
36
37         if (PKWK_READONLY || ! $do_backup) return;
38
39         if ($del_backup && $is_delete) {
40                 _backup_delete($page);
41                 return;
42         }
43
44         if (! is_page($page)) return;
45
46         $lastmod = _backup_get_filetime($page);
47         $backups = get_backup($page);
48         $is_author_differ = false;
49         $need_backup_by_time = $lastmod == 0 || UTIME - $lastmod > 60 * 60 * $cycle;
50         if (!$need_backup_by_time) {
51                 // Backup file is saved recently, but the author may differ.
52                 $last_content = get_source($page, TRUE, TRUE);
53                 $m = array();
54                 $prev_author = null;
55                 if (preg_match('/^#author\("([^"]+)","([^"]*)","([^"]*)"\)/m', $last_content, $m)) {
56                         $prev_author = preg_replace('/^[^:]+:/', '', $m[2]);
57                 }
58                 if ($prev_author !== $auth_user) {
59                         $is_author_differ = true;
60                 }
61         }
62         if ($need_backup_by_time || $is_author_differ || $is_delete)
63         {
64                 $backups = get_backup($page);
65                 $count   = count($backups) + 1;
66                 // 直後に1件追加するので、(最大件数 - 1)を超える要素を捨てる
67                 if ($count > $maxage)
68                         array_splice($backups, 0, $count - $maxage);
69
70                 $strout = '';
71                 foreach($backups as $age=>$data) {
72                         $strout .= PKWK_SPLITTER . ' ' . $data['time'] . "\n"; // Splitter format
73                         $strout .= join('', $data['data']);
74                         unset($backups[$age]);
75                 }
76                 $strout = preg_replace("/([^\n])\n*$/", "$1\n", $strout);
77
78                 // Escape 'lines equal to PKWK_SPLITTER', by inserting a space
79                 $body = preg_replace('/^(' . preg_quote(PKWK_SPLITTER) . "\s\d+)$/", '$1 ', get_source($page));
80                 $body = PKWK_SPLITTER . ' ' . get_filetime($page) . "\n" . join('', $body);
81                 $body = preg_replace("/\n*$/", "\n", $body);
82                 $body_on_delete = '';
83                 if ($is_delete) {
84                         $body_on_delete = PKWK_SPLITTER . ' ' . UTIME . "\n" . $wikitext;
85                         $body_on_delete = preg_replace("/\n*$/", "\n", $body_on_delete);
86                 }
87                 $fp = _backup_fopen($page, 'wb')
88                         or die_message('Cannot open ' . htmlsc(_backup_get_filename($page)) .
89                         '<br />Maybe permission is not writable or filename is too long');
90                 _backup_fputs($fp, $strout);
91                 _backup_fputs($fp, $body);
92                 _backup_fputs($fp, $body_on_delete);
93                 _backup_fclose($fp);
94         }
95 }
96
97 /**
98  * get_backup
99  * バックアップを取得する
100  * $age = 0または省略 : 全てのバックアップデータを配列で取得する
101  * $age > 0           : 指定した世代のバックアップデータを取得する
102  *
103  * @access    public
104  * @param     String    $page        ページ名
105  * @param     Integer   $age         バックアップの世代番号 省略時は全て
106  *
107  * @return    String    バックアップ       ($age != 0)
108  *            Array     バックアップの配列 ($age == 0)
109  */
110 function get_backup($page, $age = 0)
111 {
112         $lines = _backup_file($page);
113         if (! is_array($lines)) return array();
114
115         $_age = 0;
116         $retvars = $match = array();
117         $regex_splitter = '/^' . preg_quote(PKWK_SPLITTER) . '\s(\d+)$/';
118         foreach($lines as $index => $line) {
119                 if (preg_match($regex_splitter, $line, $match)) {
120                         // A splitter, tells new data of backup will come
121                         ++$_age;
122                         if ($age > 0 && $_age > $age)
123                                 return $retvars[$age];
124
125                         // Allocate
126                         $retvars[$_age] = array('time'=>$match[1], 'data'=>array());
127                 } else if (preg_match('/^\s*#author\("([^"]+)","([^"]+)","([^"]*)"\)/', $line, $match)) {
128                         $retvars[$_age]['author_datetime'] = $match[1];
129                         $retvars[$_age]['author'] = $match[2];
130                         $retvars[$_age]['author_fullname'] = $match[3];
131                         $retvars[$_age]['data'][] = $line;
132                 } else {
133                         // The first ... the last line of the data
134                         $retvars[$_age]['data'][] = $line;
135                 }
136                 unset($lines[$index]);
137         }
138
139         return $retvars;
140 }
141
142 /**
143  * _backup_get_filename
144  * バックアップファイル名を取得する
145  *
146  * @access    private
147  * @param     String    $page        ページ名
148  *
149  * @return    String    バックアップのファイル名
150  */
151 function _backup_get_filename($page)
152 {
153         return BACKUP_DIR . encode($page) . BACKUP_EXT;
154 }
155
156 /**
157  * _backup_file_exists
158  * バックアップファイルが存在するか
159  *
160  * @access    private
161  * @param     String    $page        ページ名
162  *
163  * @return    Boolean   TRUE:ある FALSE:ない
164  */
165 function _backup_file_exists($page)
166 {
167         return file_exists(_backup_get_filename($page));
168 }
169
170 /**
171  * _backup_get_filetime
172  * バックアップファイルの更新時刻を得る
173  *
174  * @access    private
175  * @param     String    $page        ページ名
176  *
177  * @return    Integer   ファイルの更新時刻(GMT)
178  */
179
180 function _backup_get_filetime($page)
181 {
182         return _backup_file_exists($page) ?
183                 filemtime(_backup_get_filename($page)) - LOCALZONE : 0;
184 }
185
186 /**
187  * _backup_delete
188  * バックアップファイルを削除する
189  *
190  * @access    private
191  * @param     String    $page        ページ名
192  *
193  * @return    Boolean   FALSE:失敗
194  */
195 function _backup_delete($page)
196 {
197         return unlink(_backup_get_filename($page));
198 }
199
200 /////////////////////////////////////////////////
201
202 if (extension_loaded('zlib')) {
203         // ファイルシステム関数
204         // zlib関数を使用
205         define('BACKUP_EXT', '.gz');
206
207 /**
208  * _backup_fopen
209  * バックアップファイルを開く
210  *
211  * @access    private
212  * @param     String    $page        ページ名
213  * @param     String    $mode        モード
214  *
215  * @return    Boolean   FALSE:失敗
216  */
217         function _backup_fopen($page, $mode)
218         {
219                 return gzopen(_backup_get_filename($page), $mode);
220         }
221
222 /**
223  * _backup_fputs
224  * バックアップファイルに書き込む
225  *
226  * @access    private
227  * @param     Integer   $zp          ファイルポインタ
228  * @param     String    $str         文字列
229  *
230  * @return    Boolean   FALSE:失敗 その他:書き込んだバイト数
231  */
232         function _backup_fputs($zp, $str)
233         {
234                 return gzputs($zp, $str);
235         }
236
237 /**
238  * _backup_fclose
239  * バックアップファイルを閉じる
240  *
241  * @access    private
242  * @param     Integer   $zp          ファイルポインタ
243  *
244  * @return    Boolean   FALSE:失敗
245  */
246         function _backup_fclose($zp)
247         {
248                 return gzclose($zp);
249         }
250
251 /**
252  * _backup_file
253  * バックアップファイルの内容を取得する
254  *
255  * @access    private
256  * @param     String    $page        ページ名
257  *
258  * @return    Array     ファイルの内容
259  */
260         function _backup_file($page)
261         {
262                 return _backup_file_exists($page) ?
263                         gzfile(_backup_get_filename($page)) :
264                         array();
265         }
266 }
267 /////////////////////////////////////////////////
268 else
269 {
270         // ファイルシステム関数
271         define('BACKUP_EXT', '.txt');
272
273 /**
274  * _backup_fopen
275  * バックアップファイルを開く
276  *
277  * @access    private
278  * @param     String    $page        ページ名
279  * @param     String    $mode        モード
280  *
281  * @return    Boolean   FALSE:失敗
282  */
283         function _backup_fopen($page, $mode)
284         {
285                 return fopen(_backup_get_filename($page), $mode);
286         }
287
288 /**
289  * _backup_fputs
290  * バックアップファイルに書き込む
291  *
292  * @access    private
293  * @param     Integer   $zp          ファイルポインタ
294  * @param     String    $str         文字列
295  *
296  * @return    Boolean   FALSE:失敗 その他:書き込んだバイト数
297  */
298         function _backup_fputs($zp, $str)
299         {
300                 return fputs($zp, $str);
301         }
302
303 /**
304  * _backup_fclose
305  * バックアップファイルを閉じる
306  *
307  * @access    private
308  * @param     Integer   $zp          ファイルポインタ
309  *
310  * @return    Boolean   FALSE:失敗
311  */
312         function _backup_fclose($zp)
313         {
314                 return fclose($zp);
315         }
316
317 /**
318  * _backup_file
319  * バックアップファイルの内容を取得する
320  *
321  * @access    private
322  * @param     String    $page        ページ名
323  *
324  * @return    Array     ファイルの内容
325  */
326         function _backup_file($page)
327         {
328                 return _backup_file_exists($page) ?
329                         file(_backup_get_filename($page)) :
330                         array();
331         }
332 }