2 // PukiWiki - Yet another WikiWikiWeb clone
5 // 2002-2017 PukiWiki Development Team
6 // 2001-2002 Originally written by yu-ji
7 // License: GPL v2 or (at your option) any later version
9 // Image refernce plugin
10 // Include an attached image-file as an inline-image
13 if (! defined('FILE_ICON'))
15 '<img src="' . IMAGE_DIR . 'file.png" width="20" height="20"' .
16 ' alt="file" style="border-width:0px" />');
18 /////////////////////////////////////////////////
21 // Horizontal alignment
22 define('PLUGIN_REF_DEFAULT_ALIGN', 'left'); // 'left', 'center', 'right'
25 define('PLUGIN_REF_WRAP_TABLE', FALSE); // TRUE, FALSE
28 define('PLUGIN_REF_URL_GET_IMAGE_SIZE', FALSE); // FALSE, TRUE
30 // UPLOAD_DIR のデータ(画像ファイルのみ)に直接アクセスさせる
31 define('PLUGIN_REF_DIRECT_ACCESS', FALSE); // FALSE or TRUE
32 // - これは従来のインラインイメージ処理を互換のために残すもので
33 // あり、高速化のためのオプションではありません
34 // - UPLOAD_DIR をWebサーバー上に露出させており、かつ直接アクセス
35 // できる(アクセス制限がない)状態である必要があります
36 // - Apache などでは UPLOAD_DIR/.htaccess を削除する必要があります
37 // - ブラウザによってはインラインイメージの表示や、「インライン
38 // イメージだけを表示」させた時などに不具合が出る場合があります
40 /////////////////////////////////////////////////
42 // Image suffixes allowed
43 define('PLUGIN_REF_IMAGE', '/\.(gif|png|jpe?g|swf)$/i');
46 define('PLUGIN_REF_USAGE', "([pagename/]attached-file-name[,parameters, ... ][,title])");
48 function plugin_ref_inline()
50 // Not reached, because of "$aryargs[] = & $body" at plugin.php
51 // if (! func_num_args())
52 // return '&ref(): Usage:' . PLUGIN_REF_USAGE . ';';
54 $params = plugin_ref_body(func_get_args());
56 if (isset($params['_error']) && $params['_error'] != '') {
58 return '&ref(): ' . $params['_error'] . ';';
60 return $params['_body'];
64 function plugin_ref_convert()
66 if (! func_num_args())
67 return '<p>#ref(): Usage:' . PLUGIN_REF_USAGE . "</p>\n";
69 $params = plugin_ref_body(func_get_args());
71 if (isset($params['_error']) && $params['_error'] != '') {
72 return "<p>#ref(): {$params['_error']}</p>\n";
75 if ((PLUGIN_REF_WRAP_TABLE && ! $params['nowrap']) || $params['wrap']) {
78 // Mozilla 1.x = x (wrap,aroundが効かない)
80 // Netscape 6 = x (wrap,aroundが効かない)
81 // IE 6 = x (wrap,aroundが効かない)
83 // Mozilla 1.x = x (wrapで寄せが効かない)
84 // Opera 6 = x (wrapで寄せが効かない)
85 // Netscape 6 = x (wrapで寄せが効かない)
87 $margin = ($params['around'] ? '0px' : 'auto');
88 $margin_align = ($params['_align'] == 'center') ? '' : ";margin-{$params['_align']}:0px";
89 $params['_body'] = <<<EOD
90 <table class="style_table" style="margin:$margin$margin_align">
92 <td class="style_td">{$params['_body']}</td>
98 if ($params['around']) {
99 $style = ($params['_align'] == 'right') ? 'float:right' : 'float:left';
101 $style = "text-align:{$params['_align']}";
105 return "<div class=\"img_margin\" style=\"$style\">{$params['_body']}</div>\n";
108 function plugin_ref_body($args)
111 global $WikiName, $BracketName; // compat
113 $script = get_base_uri();
116 'left' => FALSE, // 左寄せ
117 'center' => FALSE, // 中央寄せ
118 'right' => FALSE, // 右寄せ
119 'wrap' => FALSE, // TABLEで囲む
120 'nowrap' => FALSE, // TABLEで囲まない
121 'around' => FALSE, // 回り込み
122 'noicon' => FALSE, // アイコンを表示しない
123 'nolink' => FALSE, // 元ファイルへのリンクを張らない
124 'noimg' => FALSE, // 画像を展開しない
125 'zoom' => FALSE, // 縦横比を保持する
126 '_size' => FALSE, // サイズ指定あり
135 // 添付ファイルのあるページ: defaultは現在のページ名
136 $page = isset($vars['page']) ? $vars['page'] : '';
141 // 添付ファイルまでのパスおよび(実際の)ファイル名
144 // 第一引数: "[ページ名および/]添付ファイル名"、あるいは"URL"を取得
145 $name = array_shift($args);
146 $is_url = is_url($name);
150 if (! is_dir(UPLOAD_DIR)) {
151 $params['_error'] = 'No UPLOAD_DIR';
156 // ファイル名にページ名(ページ参照パス)が合成されているか
157 // (Page_name/maybe-separated-with/slashes/ATTACHED_FILENAME)
158 if (preg_match('#^(.+)/([^/]+)$#', $name, $matches)) {
159 if ($matches[1] == '.' || $matches[1] == '..') {
160 $matches[1] .= '/'; // Restore relative paths
163 $page = get_fullname(strip_bracket($matches[1]), $page); // strip is a compat
164 $file = UPLOAD_DIR . encode($page) . '_' . encode($name);
165 $is_file = is_file($file);
167 // 第二引数以降が存在し、それはrefのオプション名称などと一致しない
168 } else if (isset($args[0]) && $args[0] != '' && ! isset($params[$args[0]])) {
169 $e_name = encode($name);
171 // Try the second argument, as a page-name or a path-name
172 $_arg = get_fullname(strip_bracket($args[0]), $page); // strip is a compat
173 $file = UPLOAD_DIR . encode($_arg) . '_' . $e_name;
174 $is_file_second = is_file($file);
176 // If the second argument is WikiName, or double-bracket-inserted pagename (compat)
177 $is_bracket_bracket = preg_match("/^($WikiName|\[\[$BracketName\]\])$/", $args[0]);
179 if ($is_file_second && $is_bracket_bracket) {
180 // Believe the second argument (compat)
185 // Try default page, with default params
186 $is_file_default = is_file(UPLOAD_DIR . encode($page) . '_' . $e_name);
188 // Promote new design
189 if ($is_file_default && $is_file_second) {
190 // Because of race condition NOW
191 $params['_error'] = htmlsc('The same file name "' .
192 $name . '" at both page: "' . $page . '" and "' . $_arg .
193 '". Try ref(pagename/filename) to specify one of them');
195 // Because of possibility of race condition, in the future
196 $params['_error'] = 'The style ref(filename,pagename) is ambiguous ' .
197 'and become obsolete. ' .
198 'Please try ref(pagename/filename)';
203 // Simple single argument
204 $file = UPLOAD_DIR . encode($page) . '_' . encode($name);
205 $is_file = is_file($file);
208 $params['_error'] = htmlsc('File not found: "' .
209 $name . '" at page "' . $page . '"');
216 foreach ($args as $arg)
217 ref_check_arg($arg, $params);
223 $is_image : 画像のときTRUE
224 $info : 画像ファイルのときgetimagesize()の'size'
226 添付ファイルのとき : ファイルの最終更新日とサイズ
229 $title = $url = $url2 = $info = '';
230 $width = $height = 0;
233 if ($is_url) { // URL
234 if (PKWK_DISABLE_INLINE_IMAGE_FROM_URI) {
235 //$params['_error'] = 'PKWK_DISABLE_INLINE_IMAGE_FROM_URI prohibits this';
237 $url = htmlsc($name);
238 $params['_body'] = '<a href="' . $url . '">' . $url . '</a>';
242 $url = $url2 = htmlsc($name);
243 $title = htmlsc(preg_match('/([^\/]+)$/', $name, $matches) ? $matches[1] : $url);
245 $is_image = (! $params['noimg'] && preg_match(PLUGIN_REF_IMAGE, $name));
247 if ($is_image && PLUGIN_REF_URL_GET_IMAGE_SIZE && (bool)ini_get('allow_url_fopen')) {
248 $size = @getimagesize($name);
249 if (is_array($size)) {
258 $title = htmlsc($name);
260 $is_image = (! $params['noimg'] && preg_match(PLUGIN_REF_IMAGE, $name));
262 // Count downloads with attach plugin
263 $url = $script . '?plugin=attach' . '&refer=' . rawurlencode($page) .
264 '&openfile=' . rawurlencode($name); // Show its filename at the last
270 // URI for in-line image output
271 if (! PLUGIN_REF_DIRECT_ACCESS) {
272 // With ref plugin (faster than attach)
273 $url = $script . '?plugin=ref' . '&page=' . rawurlencode($page) .
274 '&src=' . rawurlencode($name); // Show its filename at the last
276 // Try direct-access, if possible
280 $width = $height = 0;
281 $size = @getimagesize($file);
282 if (is_array($size)) {
287 $info = get_date('Y/m/d H:i:s', filemtime($file) - LOCALZONE) .
288 ' ' . sprintf('%01.1f', round(filesize($file)/1024, 1)) . 'KB';
293 if (! empty($params['_args'])) {
295 foreach ($params['_args'] as $arg) {
296 if (preg_match('/^([0-9]+)x([0-9]+)$/', $arg, $matches)) {
297 $params['_size'] = TRUE;
298 $params['_w'] = $matches[1];
299 $params['_h'] = $matches[2];
301 } else if (preg_match('/^([0-9.]+)%$/', $arg, $matches) && $matches[1] > 0) {
302 $params['_%'] = $matches[1];
309 if (! empty($_title)) {
310 $title = htmlsc(join(',', $_title));
311 if ($is_image) $title = make_line_rules($title);
318 if ($params['_size']) {
319 if ($width == 0 && $height == 0) {
320 $width = $params['_w'];
321 $height = $params['_h'];
322 } else if ($params['zoom']) {
323 $_w = $params['_w'] ? $width / $params['_w'] : 0;
324 $_h = $params['_h'] ? $height / $params['_h'] : 0;
325 $zoom = max($_w, $_h);
327 $width = (int)($width / $zoom);
328 $height = (int)($height / $zoom);
331 $width = $params['_w'] ? $params['_w'] : $width;
332 $height = $params['_h'] ? $params['_h'] : $height;
336 $width = (int)($width * $params['_%'] / 100);
337 $height = (int)($height * $params['_%'] / 100);
339 if ($width && $height) $info = "width=\"$width\" height=\"$height\" ";
343 $params['_align'] = PLUGIN_REF_DEFAULT_ALIGN;
344 foreach (array('right', 'left', 'center') as $align) {
345 if ($params[$align]) {
346 $params['_align'] = $align;
351 if ($is_image) { // 画像
352 $params['_body'] = "<img src=\"$url\" alt=\"$title\" title=\"$title\" $info/>";
353 if (! $params['nolink'] && $url2)
354 $params['_body'] = "<a href=\"$url2\" title=\"$title\">{$params['_body']}</a>";
356 $icon = $params['noicon'] ? '' : FILE_ICON;
357 $params['_body'] = "<a href=\"$url\" title=\"$info\">$icon$title</a>";
364 function ref_check_arg($val, & $params)
367 $params['_done'] = TRUE;
371 if (! $params['_done']) {
372 foreach (array_keys($params) as $key) {
373 if (strpos($key, strtolower($val)) === 0) {
374 $params[$key] = TRUE;
378 $params['_done'] = TRUE;
381 $params['_args'][] = $val;
384 // Output an image (fast, non-logging <==> attach plugin)
385 function plugin_ref_action()
389 $usage = 'Usage: plugin=ref&page=page_name&src=attached_image_name';
391 if (! isset($vars['page']) || ! isset($vars['src']))
392 return array('msg'=>'Invalid argument', 'body'=>$usage);
394 $page = $vars['page'];
395 $filename = $vars['src'] ;
397 $ref = UPLOAD_DIR . encode($page) . '_' . encode(preg_replace('#^.*/#', '', $filename));
398 if(! file_exists($ref))
399 return array('msg'=>'Attach file not found', 'body'=>$usage);
401 $is_image = preg_match(PLUGIN_REF_IMAGE, $filename);
403 return array('msg'=>'Seems not an image', 'body'=>$usage);
405 $got = @getimagesize($ref);
406 if (! isset($got[2])) $got[2] = FALSE;
408 case 1: $type = 'image/gif' ; break;
409 case 2: $type = 'image/jpeg'; break;
410 case 3: $type = 'image/png' ; break;
411 case 4: $type = 'application/x-shockwave-flash'; break;
413 return array('msg'=>'Seems not an image', 'body'=>$usage);
416 // Care for Japanese-character-included file name
417 $legacy_filename = mb_convert_encoding($filename, 'UTF-8', SOURCE_ENCODING);
419 switch(UA_NAME . '/' . UA_PROFILE){
421 $legacy_filename = mb_convert_encoding($filename, 'SJIS', SOURCE_ENCODING);
425 $utf8filename = mb_convert_encoding($filename, 'UTF-8', SOURCE_ENCODING);
426 $size = filesize($ref);
429 pkwk_common_headers();
430 header('Content-Disposition: inline; filename="' . $legacy_filename
431 .'"; filename*=utf-8\'\'' . rawurlencode($utf8filename));
432 header('Content-Length: ' . $size);
433 header('Content-Type: ' . $type);
434 // Disable output bufferring
435 while (ob_get_level()) {