Revision | f0414e3a0a62364920a90d4c3d42e4cbf48bf565 (tree) |
---|---|
Time | 2010-05-30 23:04:31 |
Author | miko2u <miko@cafe...> |
Commiter | miko2u |
add dav.inc.php.
@@ -1,8 +1,8 @@ | ||
1 | 1 | <?php |
2 | 2 | // PukiWiki Plus! - Yet another WikiWikiWeb clone. |
3 | -// $Id: funcplus.php,v 0.1.56 2009/05/07 00:36:00 upk Exp $ | |
3 | +// $Id: funcplus.php,v 0.1.57 2010/05/30 23:01:00 upk Exp $ | |
4 | 4 | // Copyright (C) |
5 | -// 2005-2009 PukiWiki Plus! Team | |
5 | +// 2005-2010 PukiWiki Plus! Team | |
6 | 6 | // License: GPL v2 or (at your option) any later version |
7 | 7 | // |
8 | 8 | // Plus! extension function(s) |
@@ -748,4 +748,48 @@ function strip_a($x) | ||
748 | 748 | $x = preg_replace('#<a class="ext" href="(.*?)" .*?>(.*?)<img src="' . IMAGE_URI . 'plus/ext.png".*?</a>#si','$2',$x); |
749 | 749 | return $x; |
750 | 750 | } |
751 | + | |
752 | +function is_webdav() | |
753 | +{ | |
754 | + global $log_ua; | |
755 | + static $status = false; | |
756 | + if ($status) return true; | |
757 | + | |
758 | + static $ua_dav = array( | |
759 | + 'Microsoft-WebDAV-MiniRedir\/', | |
760 | + 'Microsoft Data Access Internet Publishing Provider', | |
761 | + 'MS FrontPage', | |
762 | + '^WebDrive', | |
763 | + '^WebDAVFS\/', | |
764 | + '^gnome-vfs\/', | |
765 | + '^XML Spy', | |
766 | + '^Dreamweaver-WebDAV-SCM1', | |
767 | + ); | |
768 | + | |
769 | + switch($_SERVER['REQUEST_METHOD']) { | |
770 | + case 'OPTIONS': | |
771 | + case 'PROPFIND': | |
772 | + case 'MOVE': | |
773 | + case 'COPY': | |
774 | + case 'DELETE': | |
775 | + case 'PROPPATCH': | |
776 | + case 'MKCOL': | |
777 | + case 'LOCK': | |
778 | + case 'UNLOCK': | |
779 | + $status = true; | |
780 | + return $status; | |
781 | + default: | |
782 | + continue; | |
783 | + } | |
784 | + | |
785 | + $matches = array(); | |
786 | + foreach($ua_dav as $pattern) { | |
787 | + if (preg_match('/'.$pattern.'/', $log_ua, $matches)) { | |
788 | + $status = true; | |
789 | + return true; | |
790 | + } | |
791 | + } | |
792 | + | |
793 | + return false; | |
794 | +} | |
751 | 795 | ?> |
@@ -1,9 +1,9 @@ | ||
1 | 1 | <?php |
2 | 2 | // PukiWiki Plus! - Yet another WikiWikiWeb clone. |
3 | -// $Id: pukiwiki.php,v 1.21.19 2009/08/19 01:51:00 upk Exp $ | |
3 | +// $Id: pukiwiki.php,v 1.21.20 2010/05/30 23:01:00 upk Exp $ | |
4 | 4 | // |
5 | 5 | // PukiWiki Plus! 1.4.* |
6 | -// Copyright (C) 2002-2009 by PukiWiki Plus! Team | |
6 | +// Copyright (C) 2002-2010 by PukiWiki Plus! Team | |
7 | 7 | // http://pukiwiki.cafelounge.net/plus/ |
8 | 8 | // |
9 | 9 | // PukiWiki 1.4.* |
@@ -226,6 +226,12 @@ if ($is_protect) { | ||
226 | 226 | die('PLUS_PROTECT_MODE is set.'); |
227 | 227 | } |
228 | 228 | |
229 | +// WebDAV | |
230 | +if (is_webdav() && exist_plugin('dav')) { | |
231 | + do_plugin_action('dav'); | |
232 | + exit; | |
233 | +} | |
234 | + | |
229 | 235 | // Set Home |
230 | 236 | $auth_key = auth::get_user_info(); |
231 | 237 | if (!empty($auth_key['home'])) { |
@@ -0,0 +1,636 @@ | ||
1 | +<?php | |
2 | +/** | |
3 | + * WebDAV プラグイン | |
4 | + * | |
5 | + * Author: a-urasim@pu-toyama.ac.jp | |
6 | + * Version: 0.39 | |
7 | + * | |
8 | + * @copyright Copyright © 2010, Katsumi Saito <jo1upk@users.sourceforge.net> | |
9 | + * @version $Id: dav.inc.php,v 0.39.1 2010/05/30 20:36:00 upk Exp $ | |
10 | + * @license http://opensource.org/licenses/gpl-license.php GNU Public License (GPL2) | |
11 | + * | |
12 | + * 現状では、DOMDocument の実装上、PHP5以降でのみ稼働。 | |
13 | + * CentOS の場合は、php-xml パッケージを導入する必要あり。 | |
14 | + * | |
15 | + * == 稼働上の制限 == | |
16 | + * apache only: | |
17 | + * $_SERVER: 'HTTPS', 'HTTP_HOST', 'REQUEST_METHOD', 'PATH_INFO', 'REQUEST_URI' | |
18 | + * apache_getenv('SERVER_PORT'); | |
19 | + * | |
20 | + * == for Windows Vista/7, check == | |
21 | + * HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\BasicAuthLevel | |
22 | + * 0 - Basic authentication disabled | |
23 | + * 1 - Basic authentication enabled for SSL shares only | |
24 | + * 2 or greater - Basic authentication enabled for SSL shares | |
25 | + * and for non-SSL shares | |
26 | + * | |
27 | +*/ | |
28 | + | |
29 | +defined('PLUGIN_DAV_SHOWONLYEDITABLE') or define('PLUGIN_DAV_SHOWONLYEDITABLE', false); | |
30 | + | |
31 | +function plugin_dav_action() | |
32 | +{ | |
33 | + global $scriptname, $zslash, $log_ua; | |
34 | + | |
35 | + if (!exist_plugin('attach')) plugin_dav_error_exit(500,'attach plugin not found.'); | |
36 | + | |
37 | + $scriptname = SCRIPT_NAME; | |
38 | + // 区切り文字の全角 | |
39 | + $zslash = mb_convert_kana('/', 'A', SOURCE_ENCODING); | |
40 | + | |
41 | + header('Expires: Sat, 1 Jan 2000 00:00:00 GMT'); | |
42 | + header('Cache-Control: no-store, no-cache, must-revalidate'); | |
43 | + header('Cache-Control: post-check=0, pre-check=0', false); | |
44 | + header('Pragma: no-cache'); | |
45 | + | |
46 | + $req_headers = apache_request_headers(); | |
47 | + $path_info = (empty($_SERVER['PATH_INFO'])) ? '' : $_SERVER['PATH_INFO']; | |
48 | + | |
49 | + switch ($_SERVER['REQUEST_METHOD']) { | |
50 | + case 'OPTIONS': | |
51 | + header('DAV: 1'); | |
52 | + // OPTIONS,PROPFIND,GET,HEAD,PUT,DELETE,MOVE,COPY | |
53 | + header('Allow: OPTIONS,PROPFIND,GET,PUT,MOVE,COPY'); | |
54 | + header('MS-Author-Via: DAV'); | |
55 | + break; | |
56 | + case 'PROPFIND': | |
57 | + // 添付する際にパスワードまたは、管理者のみの場合は、認証を要求 | |
58 | + if (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) { | |
59 | + // PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'admin password' : 'password'; | |
60 | + if(!isset($req_headers['Authorization'])) plugin_dav_error_exit(401); | |
61 | + //$user = auth::check_auth_pw(); // 認証済かのチェック | |
62 | + //if (empty($user)) plugin_dav_error_exit(401); // 未認証なら認証を要求 | |
63 | + } | |
64 | + | |
65 | + if( empty($path_info)) { | |
66 | + plugin_dav_error_exit(301, NULL, plugin_dav_myurl1().'/'); | |
67 | + } | |
68 | + | |
69 | + $tree = plugin_dav_maketree($path_info); | |
70 | + if(!isset($tree)) plugin_dav_error_exit(404); | |
71 | + $ret = plugin_dav_makemultistat($tree, $_SERVER['REQUEST_URI'], $req_headers['Depth']); | |
72 | + | |
73 | + if(!isset($ret)) plugin_dav_error_exit(301, NULL, plugin_dav_myurl().'/'); | |
74 | + header('HTTP/1.1 207 Multi-Status'); | |
75 | + header('Content-Type: text/xml'); | |
76 | + echo $ret->saveXML(); | |
77 | + exit; | |
78 | + | |
79 | + case 'GET': | |
80 | + case 'HEAD': | |
81 | + // 通常のファイル参照時は、このメソッドでアクセスされる | |
82 | + $obj = & plugin_dav_getfileobj($path_info); | |
83 | + if($obj != NULL && $obj->exist) { | |
84 | + $obj->open(); | |
85 | + } | |
86 | + else if($_SERVER['REQUEST_METHOD'] == 'GET' && empty($path_info) && strpos($log_ua, 'MSIE') > 0) { | |
87 | + plugin_dav_officious_message(); | |
88 | + exit; | |
89 | + } | |
90 | + else plugin_dav_error_exit(404); | |
91 | + | |
92 | + break; | |
93 | + | |
94 | + case 'PUT': | |
95 | + $pass = NULL; | |
96 | + | |
97 | + if (auth::check_role('readonly')) plugin_dav_error_exit(403, 'PKWK_READONLY prohibits editing'); | |
98 | + | |
99 | + // 添付する際にパスワードまたは、管理者のみの場合は、認証を要求 | |
100 | + if (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) { | |
101 | + if(isset($req_headers['Authorization'])) | |
102 | + $pass = plugin_dav_getbasicpass($req_headers['Authorization']); | |
103 | + // else | |
104 | + // PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'admin password' : 'password'; | |
105 | + // plugin_dav_error_exit(401); | |
106 | + } | |
107 | + if (PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY && $pass !== TRUE && | |
108 | + ($pass === NULL || ! pkwk_login($pass))) | |
109 | + plugin_dav_error_exit(401); // 'admin only.' | |
110 | + | |
111 | + $obj = & plugin_dav_getfileobj($path_info, false); | |
112 | + | |
113 | + if(!isset($obj)) plugin_dav_error_exit(403, 'no page'); | |
114 | + if($obj->exist){ | |
115 | + unlink($tmpfilename); | |
116 | + plugin_dav_error_exit(403, 'already exist.'); | |
117 | + } | |
118 | + | |
119 | + $size = intval($req_headers['Content-Length']); | |
120 | + // Windows 7のクライアントは、まず0バイト書いて、 | |
121 | + // それをLOCKしてから、上書きしにくる。 | |
122 | + // しかし、Pukiwikiは基本上書き禁止。 | |
123 | + // そこで0バイトの時は無視する。 | |
124 | + if($size > 0){ | |
125 | + if($size > PLUGIN_ATTACH_MAX_FILESIZE) { | |
126 | + plugin_dav_error_exit(403, 'file size error'); | |
127 | + } | |
128 | + | |
129 | + $tmpfilename = tempnam('/tmp', 'dav'); | |
130 | + $fp = fopen($tmpfilename, 'wb'); | |
131 | + | |
132 | + $size = 0; | |
133 | + $putdata = fopen('php://input','rb'); | |
134 | + while ($data = fread($putdata,1024)){ | |
135 | + $size += strlen($data); | |
136 | + fwrite($fp,$data); | |
137 | + } | |
138 | + fclose($putdata); | |
139 | + fclose($fp); | |
140 | + | |
141 | + if(copy($tmpfilename, $obj->filename)) { | |
142 | + chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE); | |
143 | + } | |
144 | + | |
145 | + if(is_page($obj->page)) touch(get_filename($obj->page)); | |
146 | + $obj->getstatus(); | |
147 | + $obj->status['pass'] = ($pass !== TRUE && $pass !== NULL) ? md5($pass) : ''; | |
148 | + $obj->putstatus(); | |
149 | + unlink($tmpfilename); | |
150 | + } | |
151 | + | |
152 | + break; | |
153 | + | |
154 | + case 'DELETE': | |
155 | + // FIXME | |
156 | + // フォルダーは消せないくせに、消せたように処理してしまう。 | |
157 | + // | |
158 | + $pass = NULL; | |
159 | + | |
160 | + if (auth::check_role('readonly')) plugin_dav_error_exit(403, 'PKWK_READONLY prohibits editing'); | |
161 | + | |
162 | + // 添付する際にパスワードまたは、管理者のみの場合は、認証を要求 | |
163 | + if (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) { | |
164 | + if(isset($req_headers['Authorization'])) | |
165 | + $pass = plugin_dav_getbasicpass($req_headers['Authorization']); | |
166 | + // else | |
167 | + // PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'admin password' : 'password'; | |
168 | + // plugin_dav_error_exit(401); | |
169 | + } | |
170 | + if(PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY && $pass !== TRUE && | |
171 | + ($pass === NULL || ! pkwk_login($pass))) | |
172 | + plugin_dav_error_exit(401); // 'admin only.' | |
173 | + | |
174 | + $obj = & plugin_dav_getfileobj($path_info, false); | |
175 | + | |
176 | + if(!isset($obj)) plugin_dav_error_exit(403); | |
177 | + if($obj->getstatus() == FALSE) plugin_dav_error_exit(404); | |
178 | + | |
179 | + $obj->delete($pass); | |
180 | + if(file_exists($obj->filename)) { | |
181 | + plugin_dav_error_exit(406, "can't delete this file"); | |
182 | + } | |
183 | + | |
184 | + break; | |
185 | + | |
186 | + case 'MOVE': | |
187 | + case 'COPY': | |
188 | + // 添付ファイルのコピーと移動のみ | |
189 | + // 同じページ内での添付ファイルの移動もわざわざ消して書いている | |
190 | + // ページのコピーや移動は未実装 | |
191 | + | |
192 | + $pass = NULL; | |
193 | + | |
194 | + if (auth::check_role('readonly')) plugin_dav_error_exit(403, 'PKWK_READONLY prohibits editing'); | |
195 | + | |
196 | + // 添付する際にパスワードまたは、管理者のみの場合は、認証を要求 | |
197 | + if (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) { | |
198 | + if(isset($req_headers['Authorization'])) | |
199 | + $pass = plugin_dav_getbasicpass($req_headers['Authorization']); | |
200 | + // else | |
201 | + // PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'admin password' : 'password'; | |
202 | + // plugin_dav_error_exit(401); | |
203 | + } | |
204 | + if(PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY && $pass !== TRUE && | |
205 | + ($pass === NULL || ! pkwk_login($pass))) | |
206 | + plugin_dav_error_exit(401); // 'admin only.' | |
207 | + | |
208 | + // FROM (PATH_INFO) | |
209 | + if($_SERVER['REQUEST_METHOD'] == 'MOVE'){ | |
210 | + $obj1 = & plugin_dav_getfileobj($path_info, false); | |
211 | + } | |
212 | + else { | |
213 | + $obj1 = & plugin_dav_getfileobj($path_info, true); // readonly | |
214 | + } | |
215 | + if(!isset($obj1)) plugin_dav_error_exit(403, 'no src page.'); | |
216 | + if($obj1->getstatus() == FALSE) plugin_dav_error_exit(404); | |
217 | + | |
218 | + // TO (Destination) | |
219 | + $destname = $req_headers['Destination']; | |
220 | + if(strpos($destname, plugin_dav_myurl0()) === 0) { | |
221 | + $destname = substr($destname, strlen(plugin_dav_myurl0())); | |
222 | + } | |
223 | + if(strpos($destname, $scriptname) === 0) { | |
224 | + $destname = urldecode(substr($destname, strlen($scriptname))); | |
225 | + } else { | |
226 | + plugin_dav_error_exit(403, 'not dav directory.'); | |
227 | + } | |
228 | + | |
229 | + $obj2 = & plugin_dav_getfileobj($destname, false); | |
230 | + if (!isset($obj2)) plugin_dav_error_exit(403, 'no dst page.'); | |
231 | + if ($obj2->exist) plugin_dav_error_exit(403, 'already exist'); | |
232 | + | |
233 | + if(copy($obj1->filename, $obj2->filename)) { | |
234 | + chmod($obj2->filename, PLUGIN_ATTACH_FILE_MODE); | |
235 | + } else { | |
236 | + plugin_dav_error_exit(406, "can't copy it"); | |
237 | + } | |
238 | + | |
239 | + // COPY | |
240 | + if(is_page($obj2->page)) touch(get_filename($obj2->page)); | |
241 | + $obj2->getstatus(); | |
242 | + $obj2->status['pass'] = ($pass !== TRUE && $pass !== NULL) ? md5($pass) : ''; | |
243 | + $obj2->putstatus(); | |
244 | + | |
245 | + // MOVE(DELETE) | |
246 | + if($_SERVER['REQUEST_METHOD'] == 'MOVE') { | |
247 | + $obj1->delete($pass); | |
248 | + if(file_exists($obj1->filename)) | |
249 | + plugin_dav_error_exit(406, "can't delete this file"); | |
250 | + } | |
251 | + | |
252 | + break; | |
253 | + /* | |
254 | + case 'MKCOL': | |
255 | + // ページは作成可能 | |
256 | + // セキュリティは未検証 | |
257 | + // Windowsクライアントを考えると、 | |
258 | + // ページのリネームを考えないと無意味 | |
259 | + | |
260 | + if (auth::check_role('readonly')) plugin_dav_error_exit(403, 'PKWK_READONLY prohibits editing'); | |
261 | + | |
262 | + // 添付する際にパスワードまたは、管理者のみの場合は、認証を要求 | |
263 | + if (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) { | |
264 | + if(isset($req_headers['Authorization'])) | |
265 | + $pass = plugin_dav_getbasicpass($req_headers['Authorization']); | |
266 | + // else | |
267 | + // PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'admin password' : 'password'; | |
268 | + // plugin_dav_error_exit(401); | |
269 | + } | |
270 | + $path = $path_info; | |
271 | + if(!isset($path)) plugin_dav_error_exit(403); | |
272 | + // $path = mb_convert_encoding($path, SOURCE_ENCODING, 'UTF-8'); | |
273 | + | |
274 | + if(preg_match('/^\/(.+)\/$/', $path, $matches) != 1) | |
275 | + plugin_dav_error_exit(403); | |
276 | + | |
277 | + $page = str_replace($zslash, '/', $matches[1]); | |
278 | + if(is_page($page)) plugin_dav_error_exit(403); | |
279 | + | |
280 | + // ここの辺りにもう一つチェックが必要かも | |
281 | + page_write($page, "dav.php"); // write initial string to the page. | |
282 | + break; | |
283 | + */ | |
284 | + | |
285 | + case 'PROPPATCH': | |
286 | + // ダミールーチン: Windows 7のクライアントは、PROPPATCHが | |
287 | + // 失敗するとファイルを消しに来るため仕方なく。 | |
288 | + // | |
289 | + header('HTTP/1.1 207 Multi-Status'); | |
290 | + header('Content-Type: text/xml'); | |
291 | + $doc = plugin_dav_proppatch_dummy_response($_SERVER['REQUEST_URI']); | |
292 | + echo $doc->saveXML(); | |
293 | + exit; | |
294 | + | |
295 | + case 'MKCOL': | |
296 | + case 'LOCK': | |
297 | + case 'UNLOCK': | |
298 | + case 'POST': | |
299 | + plugin_dav_error_exit(501); // Method not Implemented | |
300 | + break; | |
301 | + default: | |
302 | + plugin_dav_error_exit(405); // Method not Allowed | |
303 | + } | |
304 | +} | |
305 | + | |
306 | +function plugin_dav_makemultistat($tree, $path, $depth) | |
307 | +{ | |
308 | + global $zslash; | |
309 | + | |
310 | + if(!isset($tree)) return NULL; | |
311 | + | |
312 | + // preg_match('/\/$/', $path) != 1 => 1:dir/ 0:dir/filename | |
313 | + // !=1 は、ファイル名の場合は、それを除外 | |
314 | + // dir の場合に処理する | |
315 | + if(is_array($tree) && preg_match('/\/$/', $path) != 1) return NULL; | |
316 | + | |
317 | + $ret = new DOMDocument(); | |
318 | + $ele = $ret->createElementNS('DAV:', 'D:multistatus'); | |
319 | + $ret->appendChild($ele); | |
320 | + | |
321 | + plugin_dav_makemultistat_sub($ret, $ele, $path, $tree); | |
322 | + if(is_array($tree) && $depth !== '0'){ | |
323 | + foreach($tree as $key => $value){ | |
324 | + //$str = mb_convert_encoding(str_replace('/', $zslash, $key), 'UTF-8'); | |
325 | + $str = str_replace('/', $zslash, $key); | |
326 | + $str = $path.rawurlencode($str); | |
327 | + if(is_array($value)) $str .= '/'; | |
328 | + plugin_dav_makemultistat_sub($ret, $ele, $str, $value); | |
329 | + } | |
330 | + } | |
331 | + return $ret; | |
332 | +} | |
333 | + | |
334 | +function plugin_dav_makemultistat_sub(&$doc, &$ele, $name, $type) | |
335 | +{ | |
336 | + $res = $doc->createElementNS('DAV:', 'D:response'); | |
337 | + $ele->appendChild($res); | |
338 | + $href = $doc->createElementNS('DAV:', 'D:href', $name); | |
339 | + $res->appendChild($href); | |
340 | + | |
341 | + $propstat = $doc->createElementNS('DAV:', 'D:propstat'); | |
342 | + $res->appendChild($propstat); | |
343 | + | |
344 | + $prop = $doc->createElementNS('DAV:', 'D:prop'); | |
345 | + $propstat->appendChild($prop); | |
346 | + | |
347 | + $resourcetype = $doc->createElementNS('DAV:', 'D:resourcetype'); | |
348 | + $prop->appendChild($resourcetype); | |
349 | + if(is_array($type)){ | |
350 | + $coll = $doc->createElementNS('DAV:', 'D:collection'); | |
351 | + $resourcetype->appendChild($coll); | |
352 | + } | |
353 | + else if($type->getstatus() && isset($type->size)){ | |
354 | + $getcontentlength = $doc->createElementNS('DAV:', 'D:getcontentlength'); | |
355 | + $getcontentlength->appendChild($doc->createTextNode(''.$type->size)); | |
356 | + $prop->appendChild($getcontentlength); | |
357 | + } | |
358 | + | |
359 | + $stat = $doc->createElementNS('DAV:', 'D:status', 'HTTP/1.1 200 OK'); | |
360 | + $propstat->appendChild($stat); | |
361 | +} | |
362 | + | |
363 | +function plugin_dav_error_exit($code, $msg = NULL, $url = NULL) | |
364 | +{ | |
365 | + global $auth_type, $realm; | |
366 | + | |
367 | + $array_msg = array( | |
368 | + 301 => array('msg1'=>'Moved', 'msg2'=>''), | |
369 | + 401 => array('msg1'=>'Authorization Required', 'msg2'=>''), | |
370 | + 403 => array('msg1'=>'Forbidden', 'msg2'=>'Your request is forbideen.'), | |
371 | + 404 => array('msg1'=>'Not Found', 'msg2'=>'The file/directory you request is not found.'), | |
372 | + 405 => array('msg1'=>'Method not Allowed', 'msg2'=>'Your request is not allowd.'), | |
373 | + 406 => array('msg1'=>'Not acceptable', 'msg2'=>'Your request is not acceptable'), | |
374 | + 500 => array('msg1'=>'Internal Server Error', 'msg2'=>'Internal Server Error.'), | |
375 | + 501 => array('msg1'=>'Method not Implemented', 'msg2'=>'The method you request is not implemented.'), | |
376 | + ); | |
377 | + | |
378 | + if (!array_key_exists($code,$array_msg)) $code = 500; | |
379 | + $msg1 = & $array_msg[$code]['msg1']; | |
380 | + $msg2 = & $array_msg[$code]['msg2']; | |
381 | + header('HTTP/1.1 '.$code.' '.$msg1); | |
382 | + | |
383 | + switch ($code) { | |
384 | + case 301: | |
385 | + header('Location: '.$url); | |
386 | + exit; | |
387 | + case 401: | |
388 | + switch ($auth_type) { | |
389 | + case 2: | |
390 | + header('WWW-Authenticate: Digest realm="'.$realm. | |
391 | + '", qop="auth", nonce="'.uniqid().'", opaque="'.md5($realm).'"'); | |
392 | + exit; | |
393 | + default: | |
394 | + header('WWW-Authenticate: Basic realm="'.$realm.'"'); | |
395 | + exit; | |
396 | + } | |
397 | + exit; | |
398 | + } | |
399 | + | |
400 | + echo '<html><head>'; | |
401 | + echo '<title>'.$code.' '.$msg1.'</title>'; | |
402 | + echo '</head><body>'; | |
403 | + echo '<h1>'.$code.' '.$msg1.'</h1>'; | |
404 | + echo '<p>'.$msg2.'</p>'; | |
405 | + if(isset($msg)) echo '<p>'.htmlspecialchars($msg).'</p>'; | |
406 | + echo '<p>This script should be used with WebDAV protocol.</p>'; | |
407 | + echo '</body></html>'; | |
408 | + exit; | |
409 | +} | |
410 | + | |
411 | +function plugin_dav_officious_message() | |
412 | +{ | |
413 | + global $scriptname; | |
414 | + | |
415 | + $myurl1 = plugin_dav_myurl1(); | |
416 | + $port = apache_getenv('SERVER_PORT'); | |
417 | + echo '<html>'; | |
418 | + echo '<head><title>officious message</title></head>'; | |
419 | + echo '<body>'; | |
420 | + echo '<p>Please use this script with WebDAV protocol.</p>'; | |
421 | + echo '<p>If your client OS is <font size=+2>Windows XP</font>,'; | |
422 | + | |
423 | + if( strrpos($scriptname, '/') != 0){ | |
424 | + echo ' you should place this script in document root directory'; | |
425 | + } | |
426 | + else if($_SERVER['HTTPS'] != 'on' && (!isset($port) || $port == 80)){ | |
427 | + $myurl2 = preg_replace('/^http:/', 'https:', $myurl1); | |
428 | + echo ' you may be able to click'; | |
429 | + echo ' <a style="behavior: url(#default#AnchorClick);"'; | |
430 | + echo ' Folder="'.$myurl1.'?">'.$myurl1.'?'; | |
431 | + echo '</a> or <a style="behavior: url(#default#AnchorClick);"'; | |
432 | + echo ' Folder="'.$myurl2.'/">'.$myurl2.'/'; | |
433 | + echo '</a>. <br>Or do <font size=+2>"Add Network Place"'; | |
434 | + echo ' in "My Network Place"</font>'; | |
435 | + } | |
436 | + else { | |
437 | + echo ' you may be able to click'; | |
438 | + echo ' <a style="behavior: url(#default#AnchorClick);"'; | |
439 | + echo ' Folder="'.$myurl1.'/">'.$myurl1.'/'; | |
440 | + echo '</a>. <br>Or do <font size=+2>"Add Network Place"'; | |
441 | + echo ' in "My Network Place"</font>'; | |
442 | + } | |
443 | + | |
444 | + echo '</p>'; | |
445 | + echo '<p>If your client OS is <font size=+2>Windows 7</font>, '; | |
446 | + | |
447 | + if($_SERVER['HTTPS'] != 'on' && (!isset($port) || $port == 80)){ | |
448 | + $myurl2 = preg_replace('/^http:/', 'https:', $myurl1); | |
449 | + echo 'you can try <font size=+2>"net use w: '.$myurl1.'"</font>'; | |
450 | + echo ' or <font size=+2>"net use w: '.$myurl2.'".</font>'; | |
451 | + echo ' ("w:" is arbitary drive letter.)'; | |
452 | + echo '<br>Or you are rarely(at the very first time after booting?)'; | |
453 | + echo ' be able to click'; | |
454 | + echo ' <a style="behavior: url(#default#AnchorClick);"'; | |
455 | + echo ' Folder="'.$myurl1.'">'.$myurl1.'</a>'; | |
456 | + echo ' or <a style="behavior: url(#default#AnchorClick);"'; | |
457 | + echo ' Folder="'.$myurl2.'">'.$myurl2.'</a>.'; | |
458 | + echo '<br>(http: can be used only when the value in the regsitry key'; | |
459 | + echo ' "HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\BasicAuthLevel" is "2")'; | |
460 | + } | |
461 | + else { | |
462 | + echo 'you can try <font size=+2>"net use w: '.$myurl1.'"</font>'; | |
463 | + echo ' ("w:" is arbitary drive letter.)'; | |
464 | + echo '<br>Or you are rarely(at the very first time after booting?)'; | |
465 | + echo ' be able to click'; | |
466 | + echo ' <a style="behavior: url(#default#AnchorClick);"'; | |
467 | + echo ' Folder="'.$myurl1.'">'.$myurl1.'</a>.'; | |
468 | + } | |
469 | + | |
470 | + echo '</p>'; | |
471 | + echo '</body>'; | |
472 | + echo '</html>'; | |
473 | +} | |
474 | + | |
475 | +function plugin_dav_myurl0() | |
476 | +{ | |
477 | + // $_SERVER['HTTPS'] - https かどうかの判定用 | |
478 | + // get_script_absuri(); | |
479 | + // rc - http://jo1upk.blogdns.net:80 | |
480 | + $url = ($_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'; | |
481 | + $url .= $_SERVER['HTTP_HOST']; | |
482 | + $port = apache_getenv('SERVER_PORT'); | |
483 | + if(isset($port) && $port != 443 && $_SERVER['HTTPS'] == 'on') | |
484 | + $url .= ':'.$port; | |
485 | + else if(isset($port) && $port != 80 && $_SERVER['HTTPS'] != 'on') | |
486 | + $url .= ':'.$port; | |
487 | + return $url; | |
488 | +} | |
489 | +function plugin_dav_myurl1() | |
490 | +{ | |
491 | + global $scriptname; | |
492 | + return plugin_dav_myurl0() . $scriptname; | |
493 | +} | |
494 | +function plugin_dav_myurl() | |
495 | +{ | |
496 | + return plugin_dav_myurl0() . $_SERVER['REQUEST_URI']; | |
497 | +} | |
498 | + | |
499 | +// このルーチンを何とかすると、 | |
500 | +// 全角スラッシュの件が何とかなるかも。 | |
501 | +function plugin_dav_maketree0() | |
502 | +{ | |
503 | + global $whatsnew, $attach_link; | |
504 | + | |
505 | + $root = array(); | |
506 | + $pagelist = auth::get_existpages(); | |
507 | + foreach($pagelist as $page){ | |
508 | + if(check_non_list($page)) continue; | |
509 | + if($page == $whatsnew) continue; | |
510 | + if(PLUGIN_DAV_SHOWONLYEDITABLE && !is_editable($page)) continue; | |
511 | + | |
512 | + $root[$page] = array(); | |
513 | + } | |
514 | + | |
515 | + // FIXME | |
516 | + // 認証時は、この制限を回避するようにする。 | |
517 | + // 現状は、添付ファイル非表示の場合は抑止 | |
518 | + if (!$attach_link) return $root; | |
519 | + | |
520 | + $attaches = & new AttachPages(''); | |
521 | + foreach($attaches->pages as $key => $val){ | |
522 | + if(check_non_list($key)) continue; | |
523 | + if(!check_readable($key, false, false)) continue; | |
524 | + if(PLUGIN_DAV_SHOWONLYEDITABLE && !is_editable($key)) continue; | |
525 | + | |
526 | + if(!isset($root[$key])) $root[$key] = array(); | |
527 | + if(is_array($root[$key])){ | |
528 | + foreach($val->files as $file => $arr){ | |
529 | + if(isset($arr[0])) $root[$key][$file] = $arr[0]; | |
530 | + } | |
531 | + } | |
532 | + } | |
533 | + | |
534 | + return $root; | |
535 | +} | |
536 | + | |
537 | +function plugin_dav_maketree($path) | |
538 | +{ | |
539 | + global $zslash; | |
540 | + $page = null; | |
541 | + | |
542 | + $tree = plugin_dav_maketree0(); | |
543 | + if(empty($path)) return $tree; | |
544 | + | |
545 | + // $path = mb_convert_encoding($path, SOURCE_ENCODING, 'UTF-8'); | |
546 | + | |
547 | + $pieces = explode('/', $path); | |
548 | + if(!empty($pieces[0])) return NULL; | |
549 | + $count = count($pieces); | |
550 | + for($i = 1; $i < $count; $i++){ | |
551 | + if(empty($pieces[$i])){ | |
552 | + if(is_array($tree)){ | |
553 | + continue; | |
554 | + } | |
555 | + else | |
556 | + return NULL; | |
557 | + } | |
558 | + else if(is_array($tree)){ | |
559 | + $pieces[$i] = str_replace($zslash, '/', $pieces[$i]); | |
560 | + | |
561 | + if(isset($tree[$pieces[$i]])) | |
562 | + $tree = $tree[$pieces[$i]]; | |
563 | + else | |
564 | + return NULL; | |
565 | + | |
566 | + if(is_array($tree)){ | |
567 | + if($page == null) $page = $pieces[$i]; | |
568 | + else $page .= '/'.$pieces[$i]; | |
569 | + } | |
570 | + } | |
571 | + else | |
572 | + return NULL; | |
573 | + } | |
574 | + | |
575 | + if(isset($page) && !check_readable($page, false, false)) plugin_dav_error_exit(401); // 'user/password' | |
576 | + | |
577 | + return $tree; | |
578 | +} | |
579 | + | |
580 | +function plugin_dav_getfileobj($path, $readonly=true) | |
581 | +{ | |
582 | + global $zslash; | |
583 | + | |
584 | + if(!isset($path)) return NULL; | |
585 | + | |
586 | + // $path = mb_convert_encoding($path, SOURCE_ENCODING, 'UTF-8'); | |
587 | + | |
588 | + if(preg_match('/^\/(.+)\/([^\/]+)$/', $path, $matches) != 1) | |
589 | + return NULL; | |
590 | + | |
591 | + $page = str_replace($zslash, '/', $matches[1]); | |
592 | + if(!is_page($page)) return NULL; | |
593 | + if(!$readonly && !is_editable($page)) return NULL; | |
594 | + | |
595 | + if(!check_readable($page, false, false)) plugin_dav_error_exit(401); // 'user/password' | |
596 | + if(!$readonly && !check_editable($page, false, false)) plugin_dav_error_exit(401); // 'user/password' | |
597 | + | |
598 | + return new AttachFile($page, $matches[2]); | |
599 | +} | |
600 | + | |
601 | +function plugin_dav_getbasicpass($str) | |
602 | +{ | |
603 | + if(preg_match('/^Basic (.+)$/', $str, $matches) != 1) | |
604 | + return NULL; | |
605 | + $str2 = base64_decode($matches[1]); | |
606 | + if($str2 === false) return NULL; | |
607 | + if(preg_match('/^[^:]+:(.+)$/', $str2, $matches2) != 1) | |
608 | + return NULL; | |
609 | + if(!isset($matches2[1])) return NULL; | |
610 | + if($matches2[1] == '') return NULL; | |
611 | + return $matches2[1]; | |
612 | +} | |
613 | + | |
614 | +function plugin_dav_proppatch_dummy_response($path) | |
615 | +{ | |
616 | + $doc = new DOMDocument(); | |
617 | + $ele = $doc->createElementNS('DAV:', 'D:multistatus'); | |
618 | + $doc->appendChild($ele); | |
619 | + $res = $doc->createElementNS('DAV:', 'D:response'); | |
620 | + $ele->appendChild($res); | |
621 | + $href = $doc->createElementNS('DAV:', 'D:href', $path); | |
622 | + $res->appendChild($href); | |
623 | + $propstat = $doc->createElementNS('DAV:', 'D:propstat'); | |
624 | + $res->appendChild($prospstat); | |
625 | + $prop = $doc->createElementNS('DAV:', 'D:prop'); | |
626 | + $propstat->appendChild($prop); | |
627 | + $prop->appendChild($doc->createElementNS('urn:schemas-microsoft-com:', 'Z:Win32CreationTime')); | |
628 | + $prop->appendChild($doc->createElementNS('urn:schemas-microsoft-com:', 'Z:Win32LastAccessTime')); | |
629 | + $prop->appendChild($doc->createElementNS('urn:schemas-microsoft-com:', 'Z:Win32LastModifiedTime')); | |
630 | + $prop->appendChild($doc->createElementNS('urn:schemas-microsoft-com:', 'Z:Win32FileAttributes')); | |
631 | + $stat = $doc->createElementNS('DAV:', 'D:status', 'HTTP/1.1 200 OK'); | |
632 | + $propstat->appendChild($stat); | |
633 | + return $doc; | |
634 | +} | |
635 | + | |
636 | +?> |