• R/O
  • HTTP
  • SSH
  • HTTPS

fswiki-lite: Commit

FSWikiLite


Commit MetaInfo

Revision0f1154e9e9e25a1ddadfd673cca6f844eb4a5979 (tree)
Time2018-04-11 17:34:05
Authorkgsoft <kgsoft@871d...>
Commiterkgsoft

Log Message

FSWiki3.6.5ベースにコードを変更。

Change Summary

Incremental Difference

--- a/edit.cgi
+++ b/edit.cgi
@@ -13,7 +13,7 @@ if($in{"p"} eq ""){
1313 $in{"p"} = "FrontPage";
1414 }
1515
16-if($in{"p"}=~ /[\|:\[\]]/){
16+if(!&Util::check_pagename($in{"p"})){
1717 &Util::error("ページ名に使用できない文字が含まれています。");
1818 }
1919
@@ -36,7 +36,7 @@ if($in{"a"} eq "edit"){
3636 &attach_delete();
3737
3838 } else {
39- redirect("FrontPage");
39+ &Wiki::redirect("FrontPage");
4040 }
4141
4242 #-------------------------------------------------------------------------------
@@ -50,7 +50,7 @@ sub edit_page {
5050
5151 if($source ne ""){
5252 $preview = 1;
53- } elsif(&Wiki::exists_page($page)){
53+ } elsif(&Wiki::page_exists($page)){
5454 $source = &Wiki::get_page($page);
5555 $time = &Wiki::get_last_modified($page);
5656 }
@@ -81,10 +81,10 @@ sub edit_page {
8181 closedir(DIR);
8282 foreach my $attach (@attachfiles){
8383 $attach =~ /^\Q$main::ATTACH_DIR\E\/(.+)\.(.+)$/;
84- my $pagename = $1;
85- my $filename = $2;
86- print &Wiki::Plugin::ref(&Util::url_decode($filename));
87- printf ("[<a href=\"$EDIT_SCRIPT?a=delconf&p=%s&f=%s\">削除</a>]\n",$pagename,$filename);
84+ my $pagename = &Util::url_decode($1);
85+ my $filename = &Util::url_decode($2);
86+ print &Wiki::Plugin::ref($filename);
87+ printf("[<a href=\"%s\">削除</a>]\n",&Wiki::create_url({a=>delconf,p=>$pagename,f=>$filename}));
8888 }
8989
9090 print "<form action=\"$EDIT_SCRIPT\" method=\"post\" enctype=\"multipart/form-data\">\n";
@@ -124,25 +124,25 @@ sub save_page {
124124 # ページの削除
125125 if($source eq ""){
126126 # 更新の重複チェック
127- if(&Wiki::exists_page($page)){
127+ if(&Wiki::page_exists($page)){
128128 if($in{"t"} != &Wiki::get_last_modified($page)){
129129 &Util::error("このページは既に更新されています。");
130130 } else {
131131 &Wiki::remove_page($page);
132132 }
133133 }
134- &redirect("FrontPage");
134+ &Wiki::redirect("FrontPage");
135135
136136 # ページの作成または更新
137137 } else {
138138 # 更新の重複チェック
139- if(&Wiki::exists_page($page)){
139+ if(&Wiki::page_exists($page)){
140140 if($in{"t"} != &Wiki::get_last_modified($page)){
141141 &Util::error("このページは既に更新されています。");
142142 }
143143 }
144144 &Wiki::save_page($page,$source);
145- &redirect($page);
145+ &Wiki::redirect($page);
146146 }
147147 }
148148 }
@@ -172,7 +172,7 @@ sub attach_file {
172172 print DATA $file;
173173 close(DATA);
174174
175- &redirectURL("$EDIT_SCRIPT?a=edit&p=".&Util::url_encode($page));
175+ &Wiki::redirectURL(&Wiki::create_url({a=>edit,p=>$page}));
176176 }
177177
178178 #-------------------------------------------------------------------------------
@@ -187,10 +187,10 @@ sub attach_delete_confirm {
187187 }
188188
189189 &print_header("添付ファイルの削除");
190- printf ("<p><a href=\"$MAIN_SCRIPT?p=%s\">%s</a>から".
191- "<a href=\"$DOWNLOAD_SCRIPT?p=%s&f=%s\">%s</a>を削除してよろしいですか?</p>\n",
192- &Util::url_encode($page),&Util::escapeHTML($page),
193- &Util::url_encode($page),&Util::url_encode($file),&Util::escapeHTML($file));
190+ printf ("<p><a href=\"%s\">%s</a>から".
191+ "<a href=\"%s\">%s</a>を削除してよろしいですか?</p>\n",
192+ &Wiki::create_url({p=>$page}),&Util::escapeHTML($page),
193+ &Wiki::create_url({p=>$page,f=>$file},$main::DOWNLOAD_SCRIPT),&Util::escapeHTML($file));
194194
195195 print "<form action=\"$EDIT_SCRIPT\" method=\"POST\">\n";
196196 print " <input type=\"submit\" name=\"do_delete\" value=\" 削 除 \">\n";
@@ -215,5 +215,5 @@ sub attach_delete {
215215 my $filename = sprintf("$ATTACH_DIR/%s.%s",&Util::url_encode($page),&Util::url_encode($file));
216216 unlink($filename);
217217
218- &redirectURL("$EDIT_SCRIPT?a=edit&p=".&Util::url_encode($page));
218+ &Wiki::redirectURL(&Wiki::create_url({a=>edit,p=>$page}));
219219 }
--- a/lib/common.pl
+++ b/lib/common.pl
@@ -8,37 +8,6 @@ require "./lib/jcode.pl";
88 require "./lib/mimew.pl";
99 require "./lib/setup.pl";
1010 #-------------------------------------------------------------------------------
11-# 引数で渡したページに遷移
12-#-------------------------------------------------------------------------------
13-sub redirect {
14- my $page = shift;
15- my $url = "$MAIN_SCRIPT?p=".&Util::url_encode($page);
16- &redirectURL($url);
17-}
18-
19-#-------------------------------------------------------------------------------
20-# 引数で渡したURLに遷移
21-#-------------------------------------------------------------------------------
22-sub redirectURL {
23- my $url = shift;
24-
25- print "Content-Type: text/html;charset=EUC-JP\n";
26- print "Pragma: no-cache\n";
27- print "Cache-Control: no-cache\n\n";
28- print "<html>\n";
29- print " <head>\n";
30- print " <title>moving...</title>\n";
31- print " <meta http-equiv=\"Refresh\" content=\"0;URL=$url\">\n";
32- print " </head>\n";
33- print " <body>\n";
34- print " Wait or <a href=\"$url\">Click Here!!</a>\n";
35- print " </body>\n";
36- print "</html>\n";
37-
38- exit;
39-}
40-
41-#-------------------------------------------------------------------------------
4211 # ヘッダを表示
4312 #-------------------------------------------------------------------------------
4413 sub print_header {
@@ -57,163 +26,220 @@ sub print_header {
5726
5827 print "<div class=\"adminmenu\">\n";
5928 print " <span class=\"adminmenu\">\n";
60- print " <a href=\"$MAIN_SCRIPT?p=FrontPage\">FrontPage</a>\n";
61- print " <a href=\"$EDIT_SCRIPT?a=new\">新規</a>\n";
29+ print " <a href=\"".&Wiki::create_url({p=>"FrontPage"})."\">FrontPage</a>\n";
30+ print " <a href=\"".&Wiki::create_url({a=>"new"})."\">新規</a>\n";
6231 if($show==1){
63- print " <a href=\"$EDIT_SCRIPT?a=edit&p=".&Util::url_encode($in{"p"})."\">編集</a>\n";
32+ print " <a href=\"".&Wiki::create_url({a=>"edit",p=>$in{"p"}})."\">編集</a>\n";
6433 }
65- print " <a href=\"$MAIN_SCRIPT?a=search\">検索</a>\n";
66- print " <a href=\"$MAIN_SCRIPT?a=list\">一覧</a>\n";
67- print " <a href=\"$MAIN_SCRIPT?p=Help\">ヘルプ</a>\n";
34+ print " <a href=\"".&Wiki::create_url({a=>"search"})."\">検索</a>\n";
35+ print " <a href=\"".&Wiki::create_url({a=>"list"})."\">一覧</a>\n";
36+ print " <a href=\"".&Wiki::create_url({p=>"Help"})."\">ヘルプ</a>\n";
6837 print " </span>\n";
6938 print "</div>\n";
7039
7140 print "<h1>".&Util::escapeHTML($title)."</h1>\n";
72- if(&Wiki::exists_page("Menu")){
41+ if(&Wiki::page_exists("Menu")){
7342 print "<div class=\"main\">\n";
7443 }
75-
7644 }
7745
7846 #-------------------------------------------------------------------------------
7947 # フッタを表示
8048 #-------------------------------------------------------------------------------
8149 sub print_footer {
82- if(&Wiki::exists_page("Menu")){
50+ if(&Wiki::page_exists("Menu")){
8351 print "</div>\n";
8452 print "<div class=\"sidebar\">\n";
8553 print &Wiki::process_wiki(&Wiki::get_page("Menu"));
8654 print "</div>\n";
8755 }
88- print "<div class=\"footer\">Powered by <a href=\"$main::SITE_URL\">FreeStyleWikiLite $main::VERSION</a></div>\n";
56+ print "<div class=\"footer\">Powered by <a href=\"".$main::SITE_URL."\">FreeStyleWikiLite ".$main::VERSION."</a></div>\n";
8957 print "</body></html>\n";
9058 }
9159
60+#-------------------------------------------------------------------------------
61+# 旧Ver(0.0.11)互換性維持
62+# 次期バージョンで削除されます。
63+#-------------------------------------------------------------------------------
64+sub redirect { return &Wiki::redirect($@); }
65+sub redirectURL { return &Wiki::redirectURL($@); }
66+
67+package Wiki;
68+sub exists_page { return &page_exists(shift); }
69+sub send_mail { return &Util::send_mail($@); }
70+
71+package HTMLParser;
72+
73+package Util;
74+sub parse_plugin { return &Wiki::parse_inline_plugin($@); }
75+
9276 ###############################################################################
9377 #
9478 # Wiki関連の関数を提供するパッケージ
9579 #
9680 ###############################################################################
9781 package Wiki;
98-#-------------------------------------------------------------------------------
99-# ページを取得
100-#-------------------------------------------------------------------------------
101-sub get_page {
102- my $page = &Util::url_encode(shift);
103-
104- open(DATA,"$main::DATA_DIR/$page.wiki") or &Util::error("$main::DATA_DIR/$page.wikiのオープンに失敗しました。");
105- my $content = "";
106- while(<DATA>){
107- $content .= $_;
108- }
109- close(DATA);
110-
111- return $content;
82+
83+local @current_parser = [];
84+
85+#==============================================================================
86+# プラグインの情報を取得します
87+#==============================================================================
88+sub get_plugin_info {
89+ my $name = shift;
90+ return defined($main::P_PLUGIN->{$name}) ? {FUNCTION=>$main::P_PLUGIN->{$name}, TYPE=>'paragraph'} :
91+ defined($main::I_PLUGIN->{$name}) ? {FUNCTION=>$main::I_PLUGIN->{$name}, TYPE=>'inline' } :
92+ defined($main::B_PLUGIN->{$name}) ? {FUNCTION=>$main::B_PLUGIN->{$name}, TYPE=>'block' } :
93+ {};
11294 }
113-#-------------------------------------------------------------------------------
114-# ページを保存
115-#-------------------------------------------------------------------------------
116-sub save_page {
117- my $page = shift;
118- my $source = shift;
95+
96+#==============================================================================
97+# Wikiソースを渡してHTMLを取得します
98+#==============================================================================
99+sub process_wiki {
100+ my $source = shift;
101+ my $mainflg = shift;
102+ my $parser = HTMLParser->new($mainflg);
119103
120- $page = &Util::trim($page);
121- $source =~ s/\r\n/\n/g;
122- $source =~ s/\r/\n/g;
104+ # 裏技用(プラグイン内部からパーサを使う場合)
105+ push(@current_parser, $parser);
123106
124- my $enc_page = &Util::url_encode($page);
125- my $action = 'MODIFY';
126- unless(-e "$main::DATA_DIR/$enc_page.wiki"){
127- $action = 'CREATE';
128- }
129-
130- # バックアップファイルを作成
131- if(-e "$main::DATA_DIR/$enc_page.wiki"){
132- open(BACKUP,">$main::BACKUP_DIR/$enc_page.bak") or &Util::error("$main::BACKUP_DIR/$enc_page.bakのオープンに失敗しました。");
133- open(DATA ,"$main::DATA_DIR/$enc_page.wiki") or &Util::error("$main::DATA_DIR/$enc_page.wikiのオープンに失敗しました。");
134- while(<DATA>){
135- print BACKUP $_;
136- }
137- close(DATA);
138- close(BACKUP);
139- }
107+ $parser->parse($source);
140108
141- # 入力内容を保存
142- open(DATA,">$main::DATA_DIR/$enc_page.wiki") or &Util::error("$main::DATA_DIR/$enc_page.wikiのオープンに失敗しました。");
143- print DATA $source;
144- close(DATA);
109+ # パーサの参照を解放
110+ pop(@current_parser);
145111
146- &send_mail($action,$page);
112+ return $parser->{html};
147113 }
148-#-------------------------------------------------------------------------------
149-# ページを削除
150-#-------------------------------------------------------------------------------
151-sub remove_page {
152- my $page = shift;
153- my $enc_page = &Util::url_encode($page);
154- unlink("$main::DATA_DIR/$enc_page.wiki") or &Util::error("$main::DATA_DIR/$enc_page.wikiの削除に失敗しました。");
155-
156- &send_mail('DELETE',$page);
114+
115+#==============================================================================
116+# パース中の場合、現在有効なHTMLParserのインスタンスを返却します。
117+# パース中の内容をプラグインから変更したい場合に使用します。
118+#==============================================================================
119+sub get_current_parser {
120+ return $current_parser[$#current_parser];
157121 }
158-#-------------------------------------------------------------------------------
159-# メール送信
160-#-------------------------------------------------------------------------------
161-sub send_mail {
162- my $action = shift;
163- my $page = shift;
164- my $enc_page = &Util::url_encode($page);
165-
166- if($main::ADMIN_MAIL eq "" || $main::SEND_MAIL eq ""){
167- return;
168- }
169-
170- my $subject = "";
171- if($action eq 'CREATE'){
172- $subject = "[FSWikiLite]$pageが作成されました";
173-
174- } elsif($action eq 'MODIFY'){
175- $subject = "[FSWikiLite]$pageが更新されました";
176-
177- } elsif($action eq 'DELETE'){
178- $subject = "[FSWikiLite]$pageが削除されました";
122+
123+#===============================================================================
124+# インラインプラグインをパースしてコマンドと引数に分割
125+#===============================================================================
126+sub parse_inline_plugin {
127+ my $text = shift;
128+ my ($cmd, @args_tmp) = split(/ /,$text);
129+ my $args_txt = &Util::trim(join(" ",@args_tmp));
130+ if($cmd =~ s/\}\}(.*?)$//){
131+ return { command=>$cmd, args=>[], post=>"$1 $args_txt"};
179132 }
180133
181- # MIMEエンコード
182- $subject = &main::mimeencode($subject);
183-
184- my $head = "Subject: $subject\n".
185- "From: $main::ADMIN_MAIL\n".
186- "Content-Transfer-Encoding: 7bit\n".
187- "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n".
188- "Reply-To: $main::ADMIN_MAIL\n".
189- "\n";
190-
191- my $body = "IP:".$ENV{'REMOTE_ADDR'}."\n".
192- "UA:".$ENV{'HTTP_USER_AGENT'}."\n";
134+ my @ret_args;
135+ my $tmp = "";
136+ my $escape = 0;
137+ my $quote = 0;
138+ my $i = 0;
193139
194- if($action eq 'MODIFY' || $action eq 'DELETE'){
195- if(-e "$main::BACKUP_DIR/$enc_page.bak"){
196- $body .= "以下は変更前のソースです。\n".
197- "-----------------------------------------------------\n";
198- open(BACKUP,"$main::BACKUP_DIR/$enc_page.bak");
199- while(my $line = <BACKUP>){
200- $body .= $line;
140+ for($i = 0; $i<length($args_txt); $i++){
141+ my $c = substr($args_txt,$i,1);
142+ if($quote!=1 && $c eq ","){
143+ if($quote==3){
144+ $tmp .= '}';
201145 }
202- close(BACKUP);
146+ push(@ret_args,$tmp);
147+ $tmp = "";
148+ $quote = 0;
149+ } elsif($quote==1 && $c eq "\\"){
150+ if($escape==0){
151+ $escape = 1;
152+ } else {
153+ $tmp .= $c;
154+ $escape = 0;
155+ }
156+ } elsif($quote==0 && $c eq '"'){
157+ if($tmp eq ""){
158+ $quote = 1;
159+ } else {
160+ $tmp .= $c;
161+ }
162+ } elsif($quote==1 && $c eq '"'){
163+ if($escape==1){
164+ $tmp .= $c;
165+ $escape = 0;
166+ } else {
167+ $quote = 2;
168+ }
169+ } elsif(($quote==0 || $quote==2) && $c eq '}'){
170+ $quote = 3;
171+ } elsif($quote==3){
172+ if($c eq '}'){
173+ last;
174+ } else {
175+ $tmp .= '}'.$c;
176+ $quote = 0;
177+ }
178+ } elsif($quote==2){
179+ return {error=>"インラインプラグインの構文が不正です。"};
180+ } else {
181+ $tmp .= $c;
182+ $escape = 0;
203183 }
204184 }
205185
206- # 文字コードの変換(jcode.plを使用する)
207- &jcode::convert(\$body,'jis');
186+ if($quote!=3){
187+ my $info = &Wiki::get_plugin_info($cmd);
188+ return undef if (defined($info->{TYPE}) && $info->{TYPE} ne 'block');
189+ }
208190
209- open(MAIL,"| $main::SEND_MAIL $main::ADMIN_MAIL");
210- print MAIL $head;
211- print MAIL $body;
212- close(MAIL);
191+ if($tmp ne ""){
192+ push(@ret_args,$tmp);
193+ }
194+
195+ return { command=>$cmd, args=>\@ret_args,
196+ post=>substr($args_txt, $i + 1, length($args_txt) - $i)};
213197 }
214-#-------------------------------------------------------------------------------
198+
199+#==============================================================================
200+# ページ表示のURLを生成
201+#==============================================================================
202+sub create_page_url {
203+ my $page = shift;
204+ return create_url({p=>$page});
205+}
206+
207+#==============================================================================
208+# 任意のURLを生成
209+#==============================================================================
210+sub create_url {
211+ my $params = shift;
212+ my $script = shift;
213+ my $url = '';
214+ my $query = '';
215+ my $action = '';
216+ foreach my $key (keys(%$params)){
217+ my $val = $params->{$key};
218+ if ($key eq 'a') {
219+ $action = $val;
220+ }
221+ if($query ne ''){
222+ $query .= '&amp;';
223+ }
224+ $query .= Util::url_encode($key)."=".Util::url_encode($val);
225+ }
226+ if(!defined($script)){
227+ if ($action =~ /^(edit|new|delconf)$/){
228+ $script = $main::EDIT_SCRIPT;
229+ }else{
230+ $script = $main::MAIN_SCRIPT;
231+ }
232+ }
233+ $url = $script;
234+ if($query ne ''){
235+ $url .= '?'.$query;
236+ }
237+ return $url;
238+}
239+
240+#==============================================================================
215241 # ページの一覧を取得
216-#-------------------------------------------------------------------------------
242+#==============================================================================
217243 sub get_page_list {
218244 opendir(DIR, $main::DATA_DIR);
219245 my ($fileentry, @files);
@@ -240,12 +266,12 @@ sub get_page_list {
240266 return @pages;
241267 }
242268
243-#-------------------------------------------------------------------------------
269+#==============================================================================
244270 # ページの更新日時を取得
245-#-------------------------------------------------------------------------------
271+#==============================================================================
246272 sub get_last_modified {
247273 my $page = shift;
248- if(&exists_page($page)){
274+ if(&page_exists($page)){
249275 my $file = sprintf("%s/%s.wiki",$main::DATA_DIR,&Util::url_encode($page));
250276 my @stat = stat($file);
251277 return $stat[9];
@@ -254,10 +280,61 @@ sub get_last_modified {
254280 }
255281 }
256282
257-#-------------------------------------------------------------------------------
283+#==============================================================================
284+# ページを取得
285+#==============================================================================
286+sub get_page {
287+ my $page = &Util::url_encode(shift);
288+
289+ open(DATA,"$main::DATA_DIR/$page.wiki") or &Util::error("$main::DATA_DIR/$page.wikiのオープンに失敗しました。");
290+ my $content = "";
291+ while(<DATA>){
292+ $content .= $_;
293+ }
294+ close(DATA);
295+
296+ return $content;
297+}
298+#==============================================================================
299+# ページを保存
300+#==============================================================================
301+sub save_page {
302+ my $page = shift;
303+ my $source = shift;
304+
305+ $page = &Util::trim($page);
306+ $source =~ s/\r\n/\n/g;
307+ $source =~ s/\r/\n/g;
308+
309+ my $enc_page = &Util::url_encode($page);
310+ my $action = 'MODIFY';
311+ unless(-e "$main::DATA_DIR/$enc_page.wiki"){
312+ $action = 'CREATE';
313+ }
314+
315+ # バックアップファイルを作成
316+ if(-e "$main::DATA_DIR/$enc_page.wiki"){
317+ open(BACKUP,">$main::BACKUP_DIR/$enc_page.bak") or &Util::error("$main::BACKUP_DIR/$enc_page.bakのオープンに失敗しました。");
318+ open(DATA ,"$main::DATA_DIR/$enc_page.wiki") or &Util::error("$main::DATA_DIR/$enc_page.wikiのオープンに失敗しました。");
319+ while(<DATA>){
320+ print BACKUP $_;
321+ }
322+ close(DATA);
323+ close(BACKUP);
324+ }
325+
326+ # 入力内容を保存
327+ open(DATA,">$main::DATA_DIR/$enc_page.wiki") or &Util::error("$main::DATA_DIR/$enc_page.wikiのオープンに失敗しました。");
328+ print DATA $source;
329+ close(DATA);
330+
331+ &Util::send_mail($action,$page);
332+}
333+
334+#==============================================================================
258335 # ページが存在するかどうか
259-#-------------------------------------------------------------------------------
260-sub exists_page {
336+#==============================================================================
337+sub page_exists {
261338 my $page = &Util::url_encode(shift);
262339 if(-e "$main::DATA_DIR/$page.wiki"){
263340 return 1;
@@ -266,16 +343,46 @@ sub exists_page {
266343 }
267344 }
268345
269-#-------------------------------------------------------------------------------
270-# Wikiソースを渡してHTMLを取得します
271-#-------------------------------------------------------------------------------
272-sub process_wiki {
273- my $source = shift;
274- my $main = shift;
275- my $parser = HTMLParser->new($main);
276- $parser->parse($source);
346+#==============================================================================
347+# 引数で渡したページに遷移
348+#==============================================================================
349+sub redirect {
350+ my $page = shift;
351+ my $url = &Wiki::create_url({p=>$page});
352+ &redirectURL($url);
353+}
354+
355+#==============================================================================
356+# 引数で渡したURLに遷移
357+#==============================================================================
358+sub redirectURL {
359+ my $url = shift;
277360
278- return $parser->{html};
361+ print "Content-Type: text/html;charset=EUC-JP\n";
362+ print "Pragma: no-cache\n";
363+ print "Cache-Control: no-cache\n\n";
364+ print "<html>\n";
365+ print " <head>\n";
366+ print " <title>moving...</title>\n";
367+ print " <meta http-equiv=\"Refresh\" content=\"0;URL=$url\">\n";
368+ print " </head>\n";
369+ print " <body>\n";
370+ print " Wait or <a href=\"$url\">Click Here!!</a>\n";
371+ print " </body>\n";
372+ print "</html>\n";
373+
374+ exit;
375+}
376+
377+#==============================================================================
378+# ページを削除
379+#==============================================================================
380+sub remove_page {
381+ my $page = shift;
382+ my $enc_page = &Util::url_encode($page);
383+ unlink("$main::DATA_DIR/$enc_page.wiki") or &Util::error("$main::DATA_DIR/$enc_page.wikiの削除に失敗しました。");
384+
385+ &Util::send_mail('DELETE',$page);
279386 }
280387
281388 ###############################################################################
@@ -294,14 +401,18 @@ sub new {
294401
295402 if(!defined($mainflg) || $mainflg eq ""){ $mainflg = 0; }
296403
404+ $self->{dl_flag} = 0;
405+ $self->{dt} = "";
406+ $self->{dd} = "";
407+
297408 $self->{html} = "";
298409 $self->{pre} = "";
299410 $self->{quote} = "";
300411 $self->{table} = 0;
301412 $self->{level} = 0;
413+ $self->{list} = 0;
302414 $self->{para} = 0;
303415 $self->{p_cnt} = 0;
304- $self->{explan} = 0;
305416 $self->{main} = $mainflg;
306417 return bless $self,$class;
307418 }
@@ -313,7 +424,9 @@ sub parse {
313424 my $self = shift;
314425 my $source = shift;
315426
427+ $self->start_parse;
316428 $source =~ s/\r//g;
429+
317430 my @lines = split(/\n/,$source);
318431
319432 foreach my $line (@lines){
@@ -327,20 +440,63 @@ sub parse {
327440 my $word3 = substr($line,0,3);
328441
329442 # 空行
330- if($line eq ""){
443+ if($line eq "" && !$self->{block}){
331444 $self->l_paragraph();
332445 next;
333446 }
334447
448+ # ブロック書式のエスケープ
449+ if($word2 eq "\\\\" || $word1 eq "\\"){
450+ my @obj = $self->parse_line(substr($line, 1));
451+ $self->l_text(\@obj);
452+ next;
453+ }
454+
335455 # パラグラフプラグイン
336- if($line =~ /^{{((.|\s)+?)}}$/){
337- my $plugin = &Util::parse_plugin($1);
338- my $class = $main::P_PLUGIN->{$plugin->{command}};
339- if(defined($class)){
456+ if($line =~ /^\{\{(.+\}\})$/){
457+ if(!$self->{block}){
458+ my $plugin = &Wiki::parse_inline_plugin($1);
459+ my $info = &Wiki::get_plugin_info($plugin->{command});
460+ if($info->{TYPE} eq "paragraph"){
461+ $self->l_plugin($plugin);
462+ } else {
463+ my @obj = $self->parse_line($line);
464+ $self->l_text(\@obj);
465+ }
466+ next;
467+ }
468+ } elsif($line =~ /^\{\{(.+)$/){
469+ if ($self->{block}) {
470+ my $plugin = &Wiki::parse_inline_plugin($1);
471+ my $info = &Wiki::get_plugin_info($plugin->{command});
472+ $self->{block}->{level}++ if($info->{TYPE} eq "block");
473+ $self->{block}->{args}->[0] .= $line."\n";
474+ next;
475+ }
476+ my $plugin = &Wiki::parse_inline_plugin($1);
477+ my $info = &Wiki::get_plugin_info($plugin->{command});
478+ if($info->{TYPE} eq "block"){
479+ unshift(@{$plugin->{args}}, "");
480+ $self->{block} = $plugin;
481+ $self->{block}->{level} = 0;
482+ } else {
483+ my @obj = $self->parse_line($line);
484+ $self->l_text(\@obj);
485+ }
486+ next;
487+ }
488+ if($self->{block}){
489+ if($line eq "}}"){
490+ if ($self->{block}->{level} > 0) {
491+ $self->{block}->{level}--;
492+ $self->{block}->{args}->[0] .= $line."\n";
493+ next;
494+ }
495+ my $plugin = $self->{block};
496+ delete($self->{block});
340497 $self->l_plugin($plugin);
341498 } else {
342- my @obj = $self->parse_line($line);
343- $self->l_text(\@obj);
499+ $self->{block}->{args}->[0] .= $line."\n";
344500 }
345501 next;
346502 }
@@ -403,10 +559,10 @@ sub parse {
403559 $self->{dd} .= substr($line,3);
404560 next;
405561 }
562+ if($self->{dt} ne "" || $self->{dd} ne ""){
563+ $self->multi_explanation;
564+ }
406565 if(index($line,"::")==0){
407- if($self->{dt} ne "" || $self->{dd} ne ""){
408- $self->multi_explanation;
409- }
410566 $self->{dt} = substr($line,2);
411567 $self->{dl_flag} = 1;
412568 next;
@@ -423,7 +579,7 @@ sub parse {
423579 $line .= " ";
424580 }
425581 my @spl = map {/^"(.*)"$/ ? scalar($_ = $1, s/\"\"/\"/g, $_) : $_}
426- ($line =~ /,\s*(\"[^\"]*(?:\"\"[^\"]*)*\"|[^,]*)/g);
582+ ($line =~ /,\s*(\"[^\"]*(?:\"\"[^\"]*)*\"|[^,]*)/g);
427583 my @array;
428584 foreach my $value (@spl){
429585 my @cell = $self->parse_line($value);
@@ -444,6 +600,13 @@ sub parse {
444600 # 複数行の説明
445601 $self->multi_explanation;
446602
603+ # パース中のブロックプラグインがあった場合、とりあえず評価しておく?
604+ if($self->{block}){
605+ my $plugin = $self->{block};
606+ delete($self->{block});
607+ $self->l_plugin($plugin);
608+ }
609+
447610 $self->end_parse;
448611 }
449612
@@ -467,121 +630,222 @@ sub multi_explanation {
467630 # 1行分をパース
468631 #===============================================================================
469632 sub parse_line {
470- my $self = shift;
471- my $source = shift;
472- my @array = ();
473-
474- # プラグイン
475- if($source =~ /{{((.|\s)+?)}}/){
476- my $pre = $`;
477- my $post = $';
478- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
479- my $plugin = &Util::parse_plugin($1);
480- my $class = $main::I_PLUGIN->{$plugin->{command}};
481- if(defined($class)){
482- push @array,$self->plugin($plugin);
483- } else {
484- push @array,$self->text("{{$1}}");
633+ my ($self, $source) = @_;
634+
635+ return () if (not defined $source);
636+
637+ my @array = ();
638+ my $pre = q{};
639+ my @parsed = ();
640+
641+ # $source が空になるまで繰り返す。
642+ SOURCE:
643+ while ($source ne q{}) {
644+
645+ # どのインライン Wiki 書式の先頭にも match しない場合
646+ if (!($source =~ /^(.*?)((?:\{\{|\[\[?|https?:|mailto:|f(?:tp:|ile:)|'''?|==|__|<<).*)$/)) {
647+ # WikiName検索・置換処理のみ実施して終了する
648+ push @array, $self->_parse_line_wikiname($pre . $source);
649+ return @array;
485650 }
486- if($post ne ""){ push(@array,$self->parse_line($post)); }
487-
488- # ボールド、イタリック、取り消し線、下線
489- } elsif($source =~ /((''')|('')|(==)|(__))(.+?)(\1)/){
490- my $pre = $`;
491- my $post = $';
492- my $type = $1;
493- my $label = $6;
494- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
495- if($type eq "'''"){
496- push @array,$self->bold($label);
497- } elsif($type eq "__"){
498- push @array,$self->underline($label);
499- } elsif($type eq "''"){
500- push @array,$self->italic($label);
501- } elsif($type eq "=="){
502- push @array,$self->denialline($label);
651+
652+ $pre .= $1; # match しなかった先頭部分は溜めておいて後で処理する
653+ $source = $2; # match 部分は後続処理にて詳細チェックを行う
654+ @parsed = ();
655+
656+ # プラグイン
657+ if ($source =~ /^\{\{/) {
658+ $source = $';
659+ my $plugin = &Wiki::parse_inline_plugin($source);
660+ unless($plugin){
661+ push @parsed, '{{';
662+ push @parsed, $self->parse_line($source);
663+ } else {
664+ my $info = &Wiki::get_plugin_info($plugin->{command});
665+ if($info->{TYPE} eq "inline"){
666+ push @parsed, $self->plugin($plugin);
667+ } else {
668+ push @parsed, $self->parse_line("<<".$plugin->{command}."プラグインは存在しません。>>");
669+ }
670+ if ($source ne "") {
671+ $source = $plugin->{post};
672+ }
673+ }
503674 }
504- if($post ne ""){ push(@array,$self->parse_line($post)); }
505-
506- # ページ別名リンク
507- } elsif($source =~ /\[\[([^\[]+?)\|(.+?)\]\]/){
508- my $pre = $`;
509- my $post = $';
510- my $label = $1;
511- my $page = $2;
512- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
513- push @array,$self->wiki_anchor($page,$label);
514- if($post ne ""){ push(@array,$self->parse_line($post)); }
515-
516- # URL別名リンク
517- } elsif($source =~ /\[([^\[]+?)\|((http|https|ftp|mailto):[a-zA-Z0-9\.,%~^_+\-%\/\?\(\)!\$&=:;\*#\@']*)\]/
518- || $source =~ /\[([^\[]+?)\|(file:[^\[\]]*)\]/
519- || $source =~ /\[([^\[]+?)\|((\/|\.\/|\.\.\/)+[a-zA-Z0-9\.,%~^_+\-%\/\?\(\)!\$&=:;\*#\@']*)\]/){
520- my $pre = $`;
521- my $post = $';
522- my $label = $1;
523- my $url = $2;
524- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
525- if(index($url,'"') >= 0 || index($url,'><') >= 0 || index($url, 'javascript:') >= 0){
526- push @array,"<span class=\"error\">不正なリンクです。</span>";
527- } else {
528- push @array,$self->url_anchor($url,$label);
675+
676+ # ページ別名リンク
677+ elsif ($source =~ /^\[\[([^\[]+?)\|([^\|\[]+?)\]\]/) {
678+ my $label = $1;
679+ my $page = $2;
680+ $source = $';
681+ push @parsed, $self->wiki_anchor($page, $label);
529682 }
530- if($post ne ""){ push(@array,$self->parse_line($post)); }
531-
532- # URLリンク
533- } elsif($source =~ /(http|https|ftp|mailto):[a-zA-Z0-9\.,%~^_+\-%\/\?\(\)!\$&=:;\*#\@']*/
534- || $source =~ /\[([^\[]+?)\|(file:[^\[\]]*)\]/){
535- my $pre = $`;
536- my $post = $';
537- my $url = $&;
538- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
539- if(index($url,'"') >= 0 || index($url,'><') >= 0 || index($url, 'javascript:') >= 0){
540- push @array,"<span class=\"error\">不正なリンクです。</span>";
541- } else {
542- push @array,$self->url_anchor($url);
683+
684+ # URL別名リンク
685+ elsif ($source
686+ =~ /^\[([^\[]+?)\|((?:http|https|ftp|mailto):[a-zA-Z0-9\.,%~^_+\-%\/\?\(\)!&=:;\*#\@'\$]*)\]/
687+ || $source =~ /^\[([^\[]+?)\|(file:[^\[\]]*)\]/
688+ || $source
689+ =~ /^\[([^\[]+?)\|((?:\/|\.\/|\.\.\/)+[a-zA-Z0-9\.,%~^_+\-%\/\?\(\)!&=:;\*#\@'\$]*)\]/
690+ )
691+ {
692+ my $label = $1;
693+ my $url = $2;
694+ $source = $';
695+ if ( index($url, q{"}) >= 0
696+ || index($url, '><') >= 0
697+ || index($url, 'javascript:') >= 0)
698+ {
699+ push @parsed, $self->parse_line('<<不正なリンクです。>>');
700+ }
701+ else {
702+ push @parsed, $self->url_anchor($url, $label);
703+ }
543704 }
544- if($post ne ""){ push(@array,$self->parse_line($post)); }
545-
546- # ページリンク
547- } elsif($source =~ /\[\[([^\|]+?)\]\]/){
548- my $pre = $`;
549- my $post = $';
550- my $page = $1;
551- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
552- push @array,$self->wiki_anchor($page);
553- if($post ne ""){ push(@array,$self->parse_line($post)); }
554-
555- # 任意のURLリンク
556- } elsif($source =~ /\[([^\[]+?)\|(.+?)\]/){
557- my $pre = $`;
558- my $post = $';
559- my $label = $1;
560- my $url = $2;
561- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
562- if(index($url,'"') >= 0 || index($url,'><') >= 0 || index($url, 'javascript:') >= 0){
563- push @array,"<span class=\"error\">不正なリンクです。</span>";
564- } else {
565- push @array,$self->url_anchor($url,$label);
705+
706+ # URLリンク
707+ elsif ($source
708+ =~ /^(?:https?|ftp|mailto):[a-zA-Z0-9\.,%~^_+\-%\/\?\(\)!&=:;\*#\@'\$]*/
709+ || $source =~ /^file:[^\[\]]*/)
710+ {
711+ my $url = $&;
712+ $source = $';
713+ if ( index($url, q{"}) >= 0
714+ || index($url, '><') >= 0
715+ || index($url, 'javascript:') >= 0)
716+ {
717+ push @parsed, $self->parse_line('<<不正なリンクです。>>');
718+ }
719+ else {
720+ push @parsed, $self->url_anchor($url);
721+ }
722+ }
723+
724+ # ページリンク
725+ elsif ($source =~ /^\[\[([^\|]+?)\]\]/) {
726+ my $page = $1;
727+ $source = $';
728+ push @parsed, $self->wiki_anchor($page);
729+ }
730+
731+ # 任意のURLリンク
732+ elsif ($source =~ /^\[([^\[]+?)\|(.+?)\]/) {
733+ my $label = $1;
734+ my $url = $2;
735+ $source = $';
736+ if ( index($url, q{"}) >= 0
737+ || index($url, '><') >= 0
738+ || index($url, 'javascript:') >= 0)
739+ {
740+ push @parsed, $self->parse_line('<<不正なリンクです。>>');
741+ }
742+ else {
743+ # URIを作成
744+ my $uri = &main::MyBaseUrl().$ENV{"PATH_INFO"};
745+ push @parsed, $self->url_anchor($uri . '/../' . $url, $label);
746+ }
747+ }
748+
749+ # ボールド、イタリック、取り消し線、下線
750+ elsif ($source =~ /^('''?|==|__)(.+?)\1/) {
751+ my $type = $1;
752+ my $label = $2;
753+ $source = $';
754+ if ($type eq q{'''}) {
755+ push @parsed, $self->bold($label);
756+ }
757+ elsif ($type eq q{__}) {
758+ push @parsed, $self->underline($label);
759+ }
760+ elsif ($type eq q{''}) {
761+ push @parsed, $self->italic($label);
762+ }
763+ else { ## elsif ($type eq q{==}) {
764+ push @parsed, $self->denialline($label);
765+ }
766+ }
767+
768+ # エラーメッセージ
769+ elsif ($source =~ /^<<(.+?)>>/) {
770+ my $label = $1;
771+ $source = $';
772+ push @parsed, $self->error($label);
773+ }
774+
775+ # インライン Wiki 書式全体には macth しなかったとき
776+ else {
777+ # 1 文字進む。
778+ if ($source =~ /^(.)/) {
779+ $pre .= $1;
780+ $source = $';
781+ }
782+
783+ # parse 結果を @array に保存する処理を飛ばして繰り返し。
784+ next SOURCE;
785+ }
786+
787+ # インライン Wiki 書式全体に macth した後の
788+ # parse 結果を @array に保存する処理。
789+
790+ # もし $pre が溜まっているなら、WikiNameの処理を実施。
791+ if ($pre ne q{}) {
792+ push @array, $self->_parse_line_wikiname($pre);
793+ $pre = q{};
794+ }
795+
796+ push @array, @parsed;
797+ }
798+
799+ # もし $pre が溜まっているなら、WikiNameの処理を実施。
800+ if ($pre ne q{}) {
801+ push @array, $self->_parse_line_wikiname($pre);
802+ }
803+
804+ return @array;
805+}
806+
807+#========================================================================
808+# parse_line() から呼び出され、WikiNameの検索・置換処理を行います。
809+#========================================================================
810+sub _parse_line_wikiname {
811+ my $self = shift;
812+ my $source = shift;
813+
814+ return () if (not defined $source);
815+
816+ my @array = ();
817+
818+ # $source が空になるまで繰り返す。
819+ while ($source ne q{}) {
820+
821+ # WikiName
822+ if ($main::WIKI_NAME == 1 && $source =~ /[A-Z]+?[a-z]+?(?:[A-Z]+?[a-z]+)+/) {
823+ my $pre = $`;
824+ my $page = $&;
825+ $source = $';
826+ if ($pre ne q{}) {
827+ push @array, $self->_parse_line_wikiname($pre);
828+ }
829+ push @array, $self->wiki_anchor($page);
830+ }
831+
832+ # WikiName も見つからなかったとき
833+ else {
834+ push @array, $self->text($source);
835+ return @array;
566836 }
567- if($post ne ""){ push(@array,$self->parse_line($post)); }
568-
569- # WikiName
570- } elsif($main::WIKI_NAME==1 && $source =~ /[A-Z]+?[a-z]+?([A-Z]+?[a-z]+)+/){
571- my $pre = $`;
572- my $post = $';
573- my $page = $&;
574- if($pre ne ""){ push(@array,$self->parse_line($pre)); }
575- push @array,$self->wiki_anchor($page);
576- if($post ne ""){ push(@array,$self->parse_line($post)); }
577-
578- } else {
579- push @array,$self->text($source);
580837 }
581-
582838 return @array;
583839 }
584840
841+#===============================================================================
842+# <p>
843+# パースを開始前に呼び出されます。
844+# サブクラスで必要な処理がある場合はオーバーライドしてください。
845+# </p>
846+#===============================================================================
847+sub start_parse {}
848+
585849 #==============================================================================
586850 # リスト
587851 #==============================================================================
@@ -595,30 +859,39 @@ sub l_list {
595859 $self->{para} = 0;
596860 }
597861
862+ if($self->{list} == 1 && $level <= $self->{level}){
863+ $self->end_list;
864+ }
865+ $self->{list} = 0;
866+
598867 $self->end_verbatim;
599868 $self->end_table;
600869 $self->end_quote;
601- $self->end_explan;
602870
603871 my $html = join("",@$obj);
604- my $plus = 1;
605-
606- if($level < $self->{level}){ $plus = -1; }
607- if($level==$self->{level}){
608- $self->{html} .= "</li>\n";
609- }
610- while($level != $self->{level}){
611- if($plus==1){
872+
873+ if($level > $self->{level}){
874+ while($level != $self->{level}){
612875 $self->{html} .= "<ul>\n";
613876 push(@{$self->{close_list}},"</ul>\n");
614- } else {
615- $self->{html} .= "</li>\n";
877+ $self->{level}++;
878+ }
879+ } elsif($level <= $self->{level}){
880+ while($level-1 != $self->{level}){
881+ if($self->{'list_close_'.$self->{level}} == 1){
882+ $self->{html} .= "</li>\n";
883+ $self->{'list_close_'.$self->{level}} = 0;
884+ }
885+ if($level == $self->{level}){
886+ last;
887+ }
616888 $self->{html} .= pop(@{$self->{close_list}});
889+ $self->{level}--;
617890 }
618- $self->{level} += $plus;
619891 }
620892
621893 $self->{html} .= "<li>".$html;
894+ $self->{'list_close_'.$level} = 1;
622895 }
623896
624897 #==============================================================================
@@ -634,29 +907,39 @@ sub l_numlist {
634907 $self->{para} = 0;
635908 }
636909
910+ if($self->{list} == 0 && $level <= $self->{level}){
911+ $self->end_list;
912+ }
913+ $self->{list} = 1;
914+
637915 $self->end_verbatim;
638916 $self->end_table;
639917 $self->end_quote;
640- $self->end_explan;
641918
642919 my $html = join("",@$obj);
643- my $plus = 1;
644920
645- if($level < $self->{level}){ $plus = -1; }
646- if($level==$self->{level}){
647- $self->{html} .= "</li>\n";
648- }
649- while($level != $self->{level}){
650- if($plus==1){
921+ if($level > $self->{level}){
922+ while($level != $self->{level}){
651923 $self->{html} .= "<ol>\n";
652924 push(@{$self->{close_list}},"</ol>\n");
653- } else {
654- $self->{html} .= "</li>\n";
925+ $self->{level}++;
926+ }
927+ } elsif($level <= $self->{level}){
928+ while($level-1 != $self->{level}){
929+ if($self->{'list_close_'.$self->{level}} == 1){
930+ $self->{html} .= "</li>\n";
931+ $self->{'list_close_'.$self->{level}} = 0;
932+ }
933+ if($level == $self->{level}){
934+ last;
935+ }
655936 $self->{html} .= pop(@{$self->{close_list}});
937+ $self->{level}--;
656938 }
657- $self->{level} += $plus;
658939 }
940+
659941 $self->{html} .= "<li>".$html;
942+ $self->{'list_close_'.$level} = 1;
660943 }
661944
662945 #==============================================================================
@@ -664,12 +947,13 @@ sub l_numlist {
664947 #==============================================================================
665948 sub end_list {
666949 my $self = shift;
667- if ($self->{level}!=0) {
668- $self->{html} .= "</li>\n";
669- while($self->{level}!=0){
670- $self->{html} .= pop(@{$self->{close_list}});
671- $self->{level} += -1;
950+ while($self->{level} != 0){
951+ if($self->{'list_close_'.($self->{level})} == 1){
952+ $self->{html} .= "</li>\n";
953+ $self->{'list_close_'.$self->{level}} = 0;
672954 }
955+ $self->{html} .= pop(@{$self->{close_list}});
956+ $self->{level}--;
673957 }
674958 }
675959
@@ -690,20 +974,20 @@ sub l_headline {
690974 $self->end_verbatim;
691975 $self->end_table;
692976 $self->end_quote;
693- $self->end_explan;
694977
695978 my $html = join("",@$obj);
696979
980+ # メインの表示領域でないとき
697981 if(!$self->{main}){
698982 $self->{html} .= "<h".($level+1).">".$html."</h".($level+1).">\n";
983+
984+ # メインの表示領域の場合はアンカを出力
699985 } else {
700986 if($level==2){
701- $self->{html} .= "<h".($level+1)."><a name=\"p".$self->{p_cnt}."\">".
702- "<span class=\"sanchor\">_</span></a>".$html."</h".($level+1).">\n";
987+ $self->{html} .= "<h".($level+1)."><a name=\"p".$self->{p_cnt}."\"><span class=\"sanchor\">&nbsp;</span>".
988+ $html."</a></h".($level+1).">\n";
703989 } else {
704- $self->{html} .= "<h".($level+1).">".
705- "<a name=\"p".$self->{p_cnt}."\">".$html."</a>".
706- "</h".($level+1).">\n";
990+ $self->{html} .= "<h".($level+1)."><a name=\"p".$self->{p_cnt}."\">".$html."</a></h".($level+1).">\n";
707991 }
708992 }
709993 $self->{p_cnt}++;
@@ -715,11 +999,15 @@ sub l_headline {
715999 sub l_line {
7161000 my $self = shift;
7171001
1002+ if($self->{para}==1){
1003+ $self->{html} .= "</p>\n";
1004+ $self->{para} = 0;
1005+ }
1006+
7181007 $self->end_list;
7191008 $self->end_verbatim;
7201009 $self->end_table;
7211010 $self->end_quote;
722- $self->end_explan;
7231011
7241012 $self->{html} .= "<hr>\n";
7251013 }
@@ -734,11 +1022,12 @@ sub l_paragraph {
7341022 $self->end_verbatim;
7351023 $self->end_table;
7361024 $self->end_quote;
737- $self->end_explan;
7381025
7391026 if($self->{para}==1){
7401027 $self->{html} .= "</p>\n";
7411028 $self->{para} = 0;
1029+ } elsif($main::BR_MODE==1){
1030+ $self->{html} .= "<br>\n";
7421031 }
7431032 }
7441033
@@ -757,15 +1046,15 @@ sub l_verbatim {
7571046 $self->end_list;
7581047 $self->end_table;
7591048 $self->end_quote;
760- $self->end_explan;
7611049
1050+ $text =~ s/^\s//;
7621051 $self->{pre} .= Util::escapeHTML($text)."\n";
7631052 }
7641053
7651054 sub end_verbatim {
7661055 my $self = shift;
7671056 if($self->{pre} ne ""){
768- $self->{html} .= "<pre>".$self->{pre}."</pre>";
1057+ $self->{html} .= "<pre>".$self->{pre}."</pre>\n";
7691058 $self->{pre} = "";
7701059 }
7711060 }
@@ -779,26 +1068,31 @@ sub l_table {
7791068 $self->end_list;
7801069 $self->end_verbatim;
7811070 $self->end_quote;
782- $self->end_explan;
1071+
1072+ my $tag = "td";
7831073
7841074 if($self->{table}==0){
7851075 $self->{table}=1;
7861076 $self->{html} .= "<table>\n";
787- $self->{html} .= "<tr>\n";
788- foreach(@$row){
789- my $html = join("",@$_);
790- $self->{html} .= "<th>".$html."</th>\n";
791- }
792- $self->{html} .= "</tr>\n";
1077+ $tag = "th";
7931078 } else {
7941079 $self->{table}=2;
795- $self->{html} .= "<tr>\n";
796- foreach(@$row){
797- my $html = join("",@$_);
798- $self->{html} .= "<td>".$html."</td>\n";
1080+ }
1081+
1082+ my @columns = ();
1083+ foreach(@$row){
1084+ my $html = join("",@$_);
1085+ if($#columns != -1 && $html eq '&lt;&lt;'){
1086+ @columns[$#columns]->{colspan}++;
1087+ } else {
1088+ push(@columns, {colspan => 1, html => $html});
7991089 }
800- $self->{html} .= "</tr>\n";
8011090 }
1091+ $self->{html} .= "<tr>\n";
1092+ foreach(@columns){
1093+ $self->{html} .= "<$tag colspan=\"".$_->{colspan}."\">".$_->{html}."</$tag>\n";
1094+ }
1095+ $self->{html} .= "</tr>\n";
8021096 }
8031097
8041098 sub end_table {
@@ -818,7 +1112,6 @@ sub end_parse {
8181112 $self->end_verbatim;
8191113 $self->end_table;
8201114 $self->end_quote;
821- $self->end_explan;
8221115
8231116 if($self->{para}==1){
8241117 $self->{html} .= "</p>\n";
@@ -836,7 +1129,6 @@ sub l_text {
8361129 $self->end_verbatim;
8371130 $self->end_table;
8381131 $self->end_quote;
839- $self->end_explan;
8401132 my $html = join("",@$obj);
8411133
8421134 if($self->{para}==0){
@@ -844,6 +1136,11 @@ sub l_text {
8441136 $self->{para} = 1;
8451137 }
8461138 $self->{html} .= $html;
1139+
1140+ # brモードに設定されている場合は<br>を足す
1141+ if($main::BR_MODE==1){
1142+ $self->{html} .= "<br>\n";
1143+ }
8471144 }
8481145
8491146 #==============================================================================
@@ -855,7 +1152,6 @@ sub l_quotation {
8551152 $self->end_list;
8561153 $self->end_verbatim;
8571154 $self->end_table;
858- $self->end_explan;
8591155 my $html = join("",@$obj);
8601156 $self->{quote} .= "<p>".$html."</p>\n";
8611157 }
@@ -876,33 +1172,15 @@ sub l_explanation {
8761172 my $obj1 = shift;
8771173 my $obj2 = shift;
8781174
879- if($self->{para}==1){
880- $self->{html} .= "</p>";
881- $self->{para} = 0;
882- }
883-
8841175 $self->end_list;
8851176 $self->end_verbatim;
8861177 $self->end_table;
8871178 $self->end_quote;
8881179
889- if($self->{explan}==0){
890- $self->{explan}=1;
891- $self->{html} .= "<dl>\n";
892- }
893-
8941180 my $html1 = join("",@$obj1);
8951181 my $html2 = join("",@$obj2);
8961182
897- $self->{html} .= "<dt>".$html1."</dt>\n<dd>".$html2."</dd>\n";
898-}
899-
900-sub end_explan {
901- my $self = shift;
902- if($self->{explan}!=0){
903- $self->{explan} = 0;
904- $self->{html} .= "</dl>\n";
905- }
1183+ $self->{html} .= "<dl>\n<dt>".$html1."</dt>\n<dd>".$html2."</dd>\n</dl>\n";
9061184 }
9071185
9081186 #==============================================================================
@@ -953,7 +1231,7 @@ sub url_anchor {
9531231 $name = $url;
9541232 }
9551233
956- if($url eq $name && $url=~/\.(gif|jpg|jpeg|bmp|png)$/i){
1234+ if($url eq $name && $url=~/\.(gif|jpg|jpeg|bmp|png)$/i && $main::DISPLAY_IMAGE==1){
9571235 return "<img src=\"".$url."\">";
9581236 } else {
9591237 return "<a href=\"$url\">".Util::escapeHTML($name)."</a>";
@@ -968,16 +1246,36 @@ sub wiki_anchor {
9681246 my $page = shift;
9691247 my $name = shift;
9701248
1249+ my $anchor = undef;
1250+ my $ppage = $page;
1251+
9711252 if(!defined($name) || $name eq ""){
9721253 $name = $page;
9731254 }
9741255
975- if(&Wiki::exists_page($page)){
976- return "<a href=\"$main::MAIN_SCRIPT?p=".&Util::url_encode($page)."\" class=\"wikipage\">".
1256+ if(&Wiki::page_exists($page)){
1257+ #アンカーを含むページが存在する場合はリンクを優先
1258+ return "<a href=\"".&Wiki::create_page_url($page)."\" class=\"wikipage\">".
9771259 &Util::escapeHTML($name)."</a>";
9781260 } else {
979- return "<span class=\"nopage\">".&Util::escapeHTML($name)."</span>".
980- "<a href=\"$main::MAIN_SCRIPT?p=".&Util::url_encode($page)."\">?</a>";
1261+ #最後の"#"以降をアンカーとする
1262+ if($page =~ m/#([^#]+)$/) {
1263+ $page = $`;
1264+ $anchor = $1;
1265+ }
1266+ if(defined($anchor) && $page eq '') {
1267+ #同一ページのアンカーリンク
1268+ return "<a href=\"#$anchor\" class=\"wikipage\">".
1269+ &Util::escapeHTML($name)."</a>";
1270+ } elsif(&Wiki::page_exists($page)) {
1271+ #指定ページのアンカーリンク
1272+ return "<a href=\"".&Wiki::create_page_url($page).(defined($anchor)?"#".$anchor:"")."\" class=\"wikipage\">".
1273+ &Util::escapeHTML($name)."</a>";
1274+ } else {
1275+ #新規ページ作成用リンク
1276+ return "<span class=\"nopage\">".&Util::escapeHTML($name)."</span>".
1277+ "<a href=\"".&Wiki::create_page_url($page)."\">?</a>";
1278+ }
9811279 }
9821280 }
9831281
@@ -997,7 +1295,7 @@ sub plugin {
9971295 my $self = shift;
9981296 my $plugin = shift;
9991297
1000- my $func_ref = $main::I_PLUGIN->{$plugin->{command}};
1298+ my $func_ref = &Wiki::get_plugin_info($plugin->{command})->{FUNCTION};
10011299 my $result = &$func_ref(@{$plugin->{args}});
10021300 if(defined($result) && $result ne ""){
10031301 return ($result);
@@ -1022,9 +1320,8 @@ sub l_plugin {
10221320 $self->end_verbatim;
10231321 $self->end_table;
10241322 $self->end_quote;
1025- $self->end_explan;
10261323
1027- my $func_ref = $main::P_PLUGIN->{$plugin->{command}};
1324+ my $func_ref = &Wiki::get_plugin_info($plugin->{command})->{FUNCTION};
10281325 my $result = &$func_ref(@{$plugin->{args}});
10291326 if(defined($result) && $result ne ""){
10301327 $self->{html} .= $result;
@@ -1035,13 +1332,14 @@ sub l_plugin {
10351332 # イメージ
10361333 #==============================================================================
10371334 sub l_image {
1038- my $self = shift;
1039- my $page = shift;
1040- my $file = shift;
1041- my $wiki = $self->{wiki};
1335+ my $self = shift;
1336+ my $page = shift;
1337+ my $file = shift;
1338+ my $width = shift;
1339+ my $height = shift;
10421340
10431341 if($self->{para}==1){
1044- $self->{html} .= "</p>";
1342+ $self->{html} .= "</p>\n";
10451343 $self->{para} = 0;
10461344 }
10471345
@@ -1049,12 +1347,24 @@ sub l_image {
10491347 $self->end_verbatim;
10501348 $self->end_table;
10511349 $self->end_quote;
1052- $self->end_explan;
10531350
1054- $self->{html} .= "<img src=\"".$wiki->config('script_name')."?action=ATTACH&amp;".
1055- "page=".&Util::url_encode($page)."&amp;file=".&Util::url_encode($file)."\">";
1351+ $self->{html} .= "<div class=\"image\">";
1352+ $self->{html} .= "<img src=\"".&Wiki::create_url({'p'=>$page,'f'=>$file},$main::DOWNLOAD_SCRIPT)."\"";
1353+ $self->{html} .= " width=\"$width\"" if ($width ne "");
1354+ $self->{html} .= " height=\"$height\"" if ($height ne "");
1355+ $self->{html} .= "/>";
1356+ $self->{html} .= "</div>\n";
10561357 }
10571358
1359+#==============================================================================
1360+# エラーメッセージ
1361+#==============================================================================
1362+sub error {
1363+ my $self = shift;
1364+ my $label = shift;
1365+
1366+ return "<span class=\"error\">".Util::escapeHTML($label)."</span>";
1367+}
10581368
10591369 ################################################################################
10601370 #
@@ -1067,6 +1377,8 @@ package Util;
10671377 #===============================================================================
10681378 sub url_encode {
10691379 my $retstr = shift;
1380+ &jcode::convert(\$retstr,"euc");
1381+
10701382 $retstr =~ s/([^ 0-9A-Za-z])/sprintf("%%%.2X", ord($1))/eg;
10711383 $retstr =~ tr/ /+/;
10721384 return $retstr;
@@ -1077,6 +1389,7 @@ sub url_encode {
10771389 #===============================================================================
10781390 sub url_decode{
10791391 my $retstr = shift;
1392+
10801393 $retstr =~ tr/+/ /;
10811394 $retstr =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
10821395 return $retstr;
@@ -1087,6 +1400,8 @@ sub url_decode{
10871400 #===============================================================================
10881401 sub escapeHTML {
10891402 my($retstr) = shift;
1403+ &jcode::convert(\$retstr,"euc");
1404+
10901405 my %table = (
10911406 '&' => '&amp;',
10921407 '"' => '&quot;',
@@ -1094,6 +1409,9 @@ sub escapeHTML {
10941409 '>' => '&gt;',
10951410 );
10961411 $retstr =~ s/([&\"<>])/$table{$1}/go;
1412+ $retstr =~ s/&amp;#([0-9]{1,5});/&#$1;/go;
1413+ $retstr =~ s/&#(0*(0|9|10|13|38|60|62));/&amp;#$1;/g;
1414+# $retstr =~ s/&amp;([a-zA-Z0-9]{2,8});/&$1;/go;
10971415 return $retstr;
10981416 }
10991417
@@ -1132,6 +1450,25 @@ sub delete_tag {
11321450 }
11331451
11341452 #===============================================================================
1453+# ページ名が使用可能かどうかチェックします。
1454+#===============================================================================
1455+sub check_pagename {
1456+ my $pagename = shift;
1457+
1458+ #ページ名をチェック
1459+ if( !defined($pagename)
1460+ || $pagename eq "" # 空
1461+ || $pagename =~ /[\|\[\]]/ # |[]
1462+ || $pagename =~ /^:/ # コロンで始まる
1463+ || $pagename =~ /[^:]:[^:]/ # コロン単体での使用
1464+ || $pagename =~ /^\s+$/ # 空白のみ
1465+ ){
1466+ return 0;
1467+ }
1468+ return 1;
1469+}
1470+
1471+#===============================================================================
11351472 # 数値かどうかチェックします。
11361473 #===============================================================================
11371474 sub check_numeric {
@@ -1143,6 +1480,63 @@ sub check_numeric {
11431480 }
11441481 }
11451482
1483+#==============================================================================
1484+# メール送信
1485+#==============================================================================
1486+sub send_mail {
1487+ my $action = shift;
1488+ my $page = shift;
1489+ my $enc_page = &Util::url_encode($page);
1490+
1491+ if($main::ADMIN_MAIL eq "" || $main::SEND_MAIL eq ""){
1492+ return;
1493+ }
1494+
1495+ my $subject = "";
1496+ if($action eq 'CREATE'){
1497+ $subject = "[FSWikiLite]$pageが作成されました";
1498+
1499+ } elsif($action eq 'MODIFY'){
1500+ $subject = "[FSWikiLite]$pageが更新されました";
1501+
1502+ } elsif($action eq 'DELETE'){
1503+ $subject = "[FSWikiLite]$pageが削除されました";
1504+ }
1505+
1506+ # MIMEエンコード
1507+ $subject = &main::mimeencode($subject);
1508+
1509+ my $head = "Subject: $subject\n".
1510+ "From: $main::ADMIN_MAIL\n".
1511+ "Content-Transfer-Encoding: 7bit\n".
1512+ "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n".
1513+ "Reply-To: $main::ADMIN_MAIL\n".
1514+ "\n";
1515+
1516+ my $body = "IP:".$ENV{'REMOTE_ADDR'}."\n".
1517+ "UA:".$ENV{'HTTP_USER_AGENT'}."\n";
1518+
1519+ if($action eq 'MODIFY' || $action eq 'DELETE'){
1520+ if(-e "$main::BACKUP_DIR/$enc_page.bak"){
1521+ $body .= "以下は変更前のソースです。\n".
1522+ "-----------------------------------------------------\n";
1523+ open(BACKUP,"$main::BACKUP_DIR/$enc_page.bak");
1524+ while(my $line = <BACKUP>){
1525+ $body .= $line;
1526+ }
1527+ close(BACKUP);
1528+ }
1529+ }
1530+
1531+ # 文字コードの変換(jcode.plを使用する)
1532+ &jcode::convert(\$body,'jis');
1533+
1534+ open(MAIL,"| $main::SEND_MAIL $main::ADMIN_MAIL");
1535+ print MAIL $head;
1536+ print MAIL $body;
1537+ close(MAIL);
1538+}
1539+
11461540 #===============================================================================
11471541 # エラーを通知
11481542 #===============================================================================
@@ -1170,7 +1564,7 @@ sub handyphone {
11701564 if(!defined($ua)){
11711565 return 0;
11721566 }
1173- if($ua=~/^DoCoMo\// || $ua=~ /^J-PHONE\// || $ua=~ /UP\.Browser/){
1567+ if($ua=~/^DoCoMo\// || $ua=~ /^J-PHONE\// || $ua=~ /UP\.Browser/ || $ua=~ /\(DDIPOCKET\;/ || $ua=~ /\(WILLCOM\;/ || $ua=~ /^Vodafone\// || $ua=~ /^SoftBank\//){
11741568 return 1;
11751569 } else {
11761570 return 0;
@@ -1178,59 +1572,18 @@ sub handyphone {
11781572 }
11791573
11801574 #===============================================================================
1181-# インラインプラグインをパースしてコマンドと引数に分割
1575+# スマートフォンかどうかチェックします。
11821576 #===============================================================================
1183-sub parse_plugin {
1184- my $text = shift;
1185- my ($cmd,@args_tmp) = split(/ /,$text);
1186- my $args_txt = &Util::trim(join(" ",@args_tmp));
1187-
1188- my @ret_args;
1189- my $tmp = "";
1190- my $escape = 0;
1191- my $quote = 0;
1192-
1193- for(my $i=0;$i<length($args_txt);$i++){
1194- my $c = substr($args_txt,$i,1);
1195-
1196- if($quote!=1 && $c eq ","){
1197- if($tmp ne ""){
1198- push(@ret_args,$tmp);
1199- $tmp = "";
1200- $quote = 0;
1201- }
1202- } elsif($quote==1 && $c eq "\\"){
1203- if($escape==0){
1204- $escape = 1;
1205- } else {
1206- $tmp .= $c;
1207- $escape = 0;
1208- }
1209- } elsif($quote==0 && $c eq '"'){
1210- if($tmp eq ""){
1211- $quote = 1;
1212- } else {
1213- $tmp .= $c;
1214- }
1215- } elsif($quote==1 && $c eq '"'){
1216- if($escape==1){
1217- $tmp .= $c;
1218- $escape = 0;
1219- } else {
1220- $quote = 2;
1221- }
1222- } elsif($quote==2){
1223- return {error=>"インラインプラグインの構文が不正です。"};
1224- } else {
1225- $tmp .= $c;
1226- }
1577+sub smartphone {
1578+ my $ua = $ENV{'HTTP_USER_AGENT'};
1579+ if(!defined($ua)){
1580+ return 0;
12271581 }
1228-
1229- if($tmp ne ""){
1230- push(@ret_args,$tmp);
1582+ if($ua =~ /Android/ || $ua =~ /iPhone/){
1583+ return 1;
1584+ } else {
1585+ return 0;
12311586 }
1232-
1233- return {command=>$cmd,args=>\@ret_args};
12341587 }
12351588
12361589 1;
--- a/lib/setup.pl
+++ b/lib/setup.pl
@@ -13,6 +13,8 @@ $THEME_URL = './theme/default/default.css';
1313 $ADMIN_MAIL = '';
1414 $SEND_MAIL = '';
1515 $WIKI_NAME = 0;
16+$BR_MODE = 0;
17+$DISPLAY_IMAGE = 1;
1618 $MAIN_SCRIPT = 'wiki.cgi';
1719 $EDIT_SCRIPT = 'edit.cgi';
1820 $CATEGORY_SCRIPT = 'category.cgi';
@@ -22,7 +24,7 @@ $SITE_TITLE = 'FSWikiLite';
2224 #===============================================================================
2325 # プロダクト情報
2426 #===============================================================================
25-$VERSION = '0.0.12';
27+$VERSION = '0.1.0';
2628 $SITE_URL = 'http://fswiki.osdn.jp/cgi-bin/wiki.cgi';
2729
2830 #===============================================================================
--- a/plugin/core.pl
+++ b/plugin/core.pl
@@ -16,9 +16,14 @@ BEGIN {
1616 $main::P_PLUGIN->{search} = \&Wiki::Plugin::search;
1717
1818 # インラインプラグインのエントリ
19- $main::I_PLUGIN->{category} = \&Wiki::Plugin::category;
20- $main::I_PLUGIN->{lastmodified} = \&Wiki::Plugin::lastmodified;
21- $main::I_PLUGIN->{ref} = \&Wiki::Plugin::ref;
19+ $main::I_PLUGIN->{category} = \&Wiki::Plugin::category;
20+ $main::I_PLUGIN->{lastmodified} = \&Wiki::Plugin::lastmodified;
21+ $main::I_PLUGIN->{ref} = \&Wiki::Plugin::ref;
22+ $main::I_PLUGIN->{raw} = \&Wiki::Plugin::raw;
23+
24+ # ブロックプラグインのエントリ
25+ $main::B_PLUGIN->{pre} = \&Wiki::Plugin::pre;
26+ $main::B_PLUGIN->{bq} = \&Wiki::Plugin::bq;
2227 }
2328
2429 #==============================================================================
@@ -26,21 +31,48 @@ BEGIN {
2631 #==============================================================================
2732 sub recent {
2833 my $max = shift;
29- $max = 0 if($max eq "");
34+ my $way = shift;
35+
36+ # 表示方式を決定
37+ if($way eq ""){
38+ $way = "H";
39+ }
40+ if($max eq "V" || $max eq "v"){
41+ $way = "V";
42+ $max = 0;
43+ } elsif($max eq "H" || $max eq "h"){
44+ $way = "H";
45+ $max = 0;
46+ } elsif($max eq ""){
47+ $max = 0;
48+ }
49+
50+ # 表示内容を作成
3051 my $buf = "";
52+ my $content = "";
3153
3254 my @pages = &Wiki::get_page_list();
3355 my $count = 0;
3456
35- $buf .= "<ul>\n";
3657 foreach my $page (@pages){
37- $buf .= "<li><a href=\"$main::MAIN_SCRIPT?p=".&Util::url_encode($page->{NAME})."\">".
38- &Util::escapeHTML($page->{NAME})."</a></li>\n";
58+ $content = "<a href=\"".&Wiki::create_url({p=>$page->{NAME}})."\">".&Util::escapeHTML($page->{NAME})."</a>";
59+ if($way eq "H" || $way eq "h"){
60+ if($count!=0){
61+ $buf .= " / ";
62+ }
63+ $buf .= $content;
64+ } else {
65+ if($count==0){
66+ $buf .= "<ul>\n";
67+ }
68+ $buf .= "<li>".$content."</li>\n";
69+ }
3970 $count++;
4071 last if($count==$max && $max!=0);
4172 }
42- $buf .= "</ul>\n";
43-
73+ if($count>0 && $way ne "H" && $way ne "h"){
74+ $buf .= "</ul>\n";
75+ }
4476 return $buf;
4577 }
4678
@@ -79,7 +111,7 @@ sub recentdays {
79111 $buf .= "<ul>\n";
80112 }
81113
82- $buf .= "<li><a href=\"$main::MAIN_SCRIPT?p=".&Util::url_encode($page->{NAME})."\">".
114+ $buf .= "<li><a href=\"".&Wiki::create_url({p=>$page->{NAME}})."\">".
83115 &Util::escapeHTML($page->{NAME})."</a></li>\n";
84116 }
85117
@@ -96,9 +128,9 @@ sub recentdays {
96128 sub category {
97129 my $category = shift;
98130 if($category eq ""){
99- return "カテゴリが指定されていません。";
131+ return "<span class=\"error\">カテゴリが指定されていません。</span>";
100132 } else {
101- return "[<a href=\"$main::CATEGORY_SCRIPT?c=".&Util::url_encode($category)."\">".
133+ return "[<a href=\"".&Wiki::create_url({c=>$category},$main::CATEGORY_SCRIPT)."\">".
102134 "カテゴリ:".&Util::escapeHTML($category)."</a>]";
103135 }
104136 }
@@ -107,8 +139,8 @@ sub category {
107139 # ページの最終更新日時を表示するプラグイン。
108140 #=============================================================================
109141 sub lastmodified {
110- my $page = $main::in{"p"};
111- if(&Wiki::exists_page($page)){
142+ my $page = shift || $main::in{"p"};
143+ if(&Wiki::page_exists($page)){
112144 return "最終更新時間:".&Util::format_date(&Wiki::get_last_modified($page));
113145 } else {
114146 return undef;
@@ -136,7 +168,7 @@ sub category_list {
136168
137169 # カテゴリにマッチしたらリスティング
138170 if($line =~ /{{category\s+$category}}/){
139- $buf .= "<li><a href=\"$main::MAIN_SCRIPT?p=".&Util::url_encode($page->{NAME})."\">".
171+ $buf .= "<li><a href=\"".&Wiki::create_url({p=>$page->{NAME}})."\">".
140172 &Util::escapeHTML($page->{NAME})."</a></li>";
141173 last;
142174 }
@@ -156,7 +188,7 @@ sub category_list {
156188 next if($line =~ /^(\t| |\/\/)/);
157189
158190 # カテゴリにマッチしたらリスティング
159- while($line =~ /{{category\s+(.+?)}}/g){
191+ while($line =~ /\{\{category\s+(.+?)\}\}/g){
160192 $category->{$1}->{$page->{NAME}} = 1;
161193 }
162194 }
@@ -166,7 +198,7 @@ sub category_list {
166198 $buf .= "<h2>".&Util::escapeHTML($name)."</h2>\n";
167199 $buf .= "<ul>\n";
168200 foreach my $page (sort(keys(%{$category->{$name}}))){
169- $buf .= "<li><a href=\"$main::MAIN_SCRIPT?p=".&Util::url_encode($page)."\">".
201+ $buf .= "<li><a href=\"".&Wiki::create_url({p=>$page})."\">".
170202 &Util::escapeHTML($page)."</a></li>\n";
171203 }
172204 $buf .= "</ul>\n";
@@ -179,59 +211,81 @@ sub category_list {
179211 # 添付ファイルへのリンクを表示するためのプラグイン。
180212 #=============================================================================
181213 sub ref {
182- my $page = $main::in{"p"};
183- my $file = shift;
214+ my $file = shift;
215+ my $page = shift;
216+ my $alias = shift;
184217
185218 if($file eq ""){
186- return "ファイルが指定されていません。";
219+ return "<p class=\"error\">ファイルが指定されていません。</p>\n";
220+ }
221+ if(!defined($page) || $page eq ""){
222+ $page = $main::in{"p"};
223+ }
224+ if(!defined($alias) || $alias eq ""){
225+ $alias = $file;
187226 }
188227
189228 my $filename = sprintf("$main::ATTACH_DIR/%s.%s",
190229 &Util::url_encode($page),&Util::url_encode($file));
191230 unless(-e $filename){
192- return "ファイルが存在しません。";
231+ return "<p class=\"error\">ファイルが存在しません。</p>\n";
193232 }
194233
195- return sprintf("<a href=\"$main::DOWNLOAD_SCRIPT?p=%s&f=%s\">%s</a>",
196- &Util::url_encode($page),&Util::url_encode($file),$file);
234+ return "<a href=\"".&Wiki::create_url({p=>$page,f=>$file},$main::DOWNLOAD_SCRIPT)."\">".&Util::escapeHTML($alias)."</a>";
197235 }
198236
199237 #=============================================================================
200238 # 添付ファイルを画像として表示するためのプラグイン。
201239 #=============================================================================
202240 sub ref_image {
203- my $page = $main::in{"p"};
204- my $file = shift;
241+ my $file = shift;
242+ my $page = "";
243+
244+ my @options = @_;
245+ my $width = "";
246+ my $height = "";
205247
206248 if($file eq ""){
207- return "ファイルが指定されていません。";
249+ return "<p class=\"error\">ファイルが指定されていません。</p>\n";
250+ }
251+ foreach my $option (@options){
252+ if($option =~ /^w([0-9]+)$/){
253+ $width = $1;
254+ } elsif($option =~ /^h([0-9]+)$/){
255+ $height = $1;
256+ } else {
257+ $page = $option;
258+ }
259+ }
260+ if($page eq ""){
261+ $page = $main::in{"p"};
208262 }
209263
210264 my $filename = sprintf("$main::ATTACH_DIR/%s.%s",
211265 &Util::url_encode($page),&Util::url_encode($file));
212266 unless(-e $filename){
213- return "<p>ファイルが存在しません。</p>\n";
267+ return "<p class=\"error\">ファイルが存在しません。</p>\n";
214268 }
215269
216- return sprintf("<div><img src=\"$main::DOWNLOAD_SCRIPT?p=%s&f=%s\"></div>",
217- &Util::url_encode($page),&Util::url_encode($file));
270+ &Wiki::get_current_parser()->l_image($page, $file, $width, $height);
271+ return undef;
218272 }
219273
220274 #=============================================================================
221275 # 添付ファイルを画像として表示するためのプラグイン。
222276 #=============================================================================
223277 sub ref_text {
224- my $page = $main::in{"p"};
225278 my $file = shift;
279+ my $page = shift || $main::in{"p"};
226280
227281 if($file eq ""){
228- return "ファイルが指定されていません。";
282+ return "<p class=\"error\">ファイルが指定されていません。</p>\n";
229283 }
230284
231285 my $filename = sprintf("$main::ATTACH_DIR/%s.%s",
232286 &Util::url_encode($page),&Util::url_encode($file));
233287 unless(-e $filename){
234- return "<p>ファイルが存在しません。</p>\n";
288+ return "<p class=\"error\">ファイルが存在しません。</p>\n";
235289 }
236290
237291 my $text = "";
@@ -256,11 +310,24 @@ sub ref_text {
256310 # 出力されるHTMLはちょっと手抜きです…
257311 #=============================================================================
258312 sub outline {
259- my $page = $main::in{'p'};
260- my $source = &Wiki::get_page($page);
313+ my $page = shift;
314+ my $url = "";
315+
316+ if (!defined($page)) {
317+ $page = $main::in{'p'};
318+ } else {
319+ $url = &Wiki::create_url({p=>$page});
320+ }
321+
322+ my $source = "";
261323 my $level = 0;
262324 my $count = 0;
263325 my $buf = "";
326+
327+ if(&Wiki::page_exists($page)){
328+ $source = &Wiki::get_page($page);
329+ }
330+
264331 foreach my $line (split(/\n/,$source)){
265332 if($line=~/^(!{1,3})(.+)$/){
266333 my $find_level = 4 - length($1);
@@ -276,7 +343,7 @@ sub outline {
276343 }
277344 my $section = &Util::delete_tag(&Wiki::process_wiki($2));
278345
279- $buf .= "<li><a href=\"#p$count\">$section</a></li>\n";
346+ $buf .= "<li><a href=\"".$url."#p$count\">$section</a></li>\n";
280347 $count++;
281348 }
282349 }
@@ -291,11 +358,62 @@ sub outline {
291358 # 検索フォームを表示するためのプラグイン
292359 #=============================================================================
293360 sub search {
294- return "<form action=\"$main::MAIN_SCRIPT\" method=\"GET\">\n".
361+ my $way = shift;
362+ my $or_checked = $main::in{'t'} eq 'or';
363+ my $with_content = $main::in{'c'} eq 'true';
364+ return "<form action=\"".&Wiki::create_url({},$main::MAIN_SCRIPT)."\" method=\"GET\">\n".
295365 " キーワード <input type=\"text\" name=\"w\" size=\"20\" value=\"".&Util::escapeHTML($main::in{'w'})."\">\n".
366+ ($way eq "v" ? "<br>" : "").
367+ " <input type=\"radio\" name=\"t\" id=\"and\" value=\"and\"".(!$or_checked?" checked":"")."><label for=\"and\">AND</label>".
368+ " <input type=\"radio\" name=\"t\" id=\"or\" value=\"or\"".($or_checked?" checked":"")."><label for=\"or\">OR</label>".
369+ ($way eq "v" ? "<br>" : "").
370+ " <input type=\"checkbox\" name=\"c\" id=\"contents\" value=\"true\"".($with_content?" checked":"")."><label for=\"contents\">ページ内容も含める</label>".
296371 " <input type=\"submit\" value=\" 検 索 \">\n".
297372 " <input type=\"hidden\" name=\"a\" value=\"search\">\n".
298373 "</form>\n";
299374 }
300375
376+#=============================================================================
377+# 引数で指定した文字列をそのまま表示するインラインプラグイン
378+#=============================================================================
379+sub raw {
380+ my $text = shift;
381+ return &Util::escapeHTML($text);
382+}
383+
384+#=============================================================================
385+# preタグを出力する複数行プラグイン
386+#=============================================================================
387+sub pre {
388+ my $text = shift;
389+ my $option = shift;
390+
391+ my $count = 1;
392+ my $buf = "<pre>";
393+ my @lines = split(/\n/, $text);
394+ my $len = length($#lines + 1);
395+ foreach my $line (@lines){
396+ if($option eq "num"){
397+ $buf .= sprintf("%0${len}d", $count) . "|";
398+ }
399+ $buf .= Util::escapeHTML($line) . "\n";
400+ $count++;
401+ }
402+
403+ return $buf . "</pre>";
404+}
405+
406+#=============================================================================
407+# blockquoteタグを出力する複数行プラグイン
408+#=============================================================================
409+sub bq {
410+ my $text = shift;
411+ my $buf = "<blockquote>";
412+ foreach my $line (split(/(\r\n)|\n|\r/,&Util::escapeHTML($text))){
413+ $buf .= "<p>$line<p>";
414+ }
415+ $buf .= "</blockquote>";
416+ return $buf;
417+}
418+
301419 1;
--- a/wiki.cgi
+++ b/wiki.cgi
@@ -33,7 +33,7 @@ sub list_page {
3333 &print_header("一覧");
3434 print "<ul>\n";
3535 foreach my $page (@pages){
36- print "<li><a href=\"$MAIN_SCRIPT?p=".&Util::url_encode($page->{NAME})."\">".
36+ print "<li><a href=\"".&Wiki::create_page_url($page->{NAME})."\">".
3737 &Util::escapeHTML($page->{NAME})."</a>".
3838 " - ".&Util::format_date($page->{TIME})."</li>\n";
3939 }
@@ -46,7 +46,7 @@ sub list_page {
4646 #-------------------------------------------------------------------------------
4747 sub show_page {
4848
49- unless(&Wiki::exists_page($in{"p"})){
49+ unless(&Wiki::page_exists($in{"p"})){
5050 undef %in;
5151 $in{"a"} = "edit";
5252 require $EDIT_SCRIPT;
@@ -58,7 +58,7 @@ sub show_page {
5858
5959 &print_header($in{"p"},1);
6060
61- if(&Wiki::exists_page("Header")){
61+ if(&Wiki::page_exists("Header")){
6262 print "<div class=\"header\">\n";
6363 print &Wiki::process_wiki(&Wiki::get_page("Header"));
6464 print "</div>\n";
@@ -68,7 +68,7 @@ sub show_page {
6868 print $html;
6969 print "</div>\n";
7070
71- if(&Wiki::exists_page("Footer")){
71+ if(&Wiki::page_exists("Footer")){
7272 print "<div class=\"comment\">\n";
7373 print &Wiki::process_wiki(&Wiki::get_page("Footer"));
7474 print "</div>\n";
@@ -83,29 +83,85 @@ sub show_page {
8383 sub search_page {
8484
8585 &print_header("検索");
86- print "<form action=\"$MAIN_SCRIPT\" method=\"GET\">\n";
87- print " キーワード <input type=\"text\" name=\"w\" size=\"20\" value=\"".&Util::escapeHTML($in{'w'})."\">\n";
88- print " <input type=\"submit\" value=\" 検 索 \">\n";
89- print " <input type=\"hidden\" name=\"a\" value=\"search\">\n";
90- print "</form>\n";
86+ print &Wiki::Plugin::search();
9187
92- if($in{'w'} ne ""){
93- my @pages = &Wiki::get_page_list();
94- my $find = 0;
95- print "<ul>\n";
96- foreach my $page (@pages){
97- my $source = $page->{NAME}."\n".&Wiki::get_page($page->{NAME});
98- if(index($source,$in{'w'})!=-1){
99- print " <li><a href=\"$MAIN_SCRIPT?p=".&Util::url_encode($page->{NAME})."\">".&Util::escapeHTML($page->{NAME})."</a></li>\n";
100- $find = 1;
88+ my $buf = "";
89+ my $or_search = $in{'t'} eq 'or';
90+ my $with_content = $in{'c'} eq 'true';
91+ my $word = &Util::trim($in{'w'});
92+
93+ my $ignore_case = 1;
94+ my $conv_upper_case = ($ignore_case and $word =~ /[A-Za-z]/);
95+
96+ $word = uc $word if ($conv_upper_case);
97+ my @words = grep { $_ ne '' } split(/ +| +/, $word);
98+ if (@words) {
99+ #---------------------------------------------------------------------------
100+ # 検索実行
101+ my @list = &Wiki::get_page_list();
102+ my $res = '';
103+ PAGE:
104+ foreach my $page (@list){
105+ my $name = $page->{NAME};
106+ # ページ名も検索対象にする
107+ my $page = $name;
108+ $page .= "\n".&Wiki::get_page($name) if ($with_content);
109+ my $pageref = ($conv_upper_case) ? \(my $page2 = uc $page) : \$page;
110+ my $index;
111+
112+ if ($or_search) {
113+ # OR検索 -------------------------------------------------------
114+ WORD:
115+ foreach(@words){
116+ next WORD if (($index = index $$pageref, $_) == -1);
117+ $res .= "<li>".
118+ "<a href=\"".&Wiki::create_page_url($name)."\">".&Util::escapeHTML($name)."</a>".
119+ " - ".
120+ &Util::escapeHTML(&get_match_content($page, $index)).
121+ "</li>\n";
122+ next PAGE;
101123 }
124+ } else {
125+ # AND検索 ------------------------------------------------------
126+ WORD:
127+ foreach(@words){
128+ next PAGE if (($index = index $$pageref, $_) == -1);
129+ }
130+ $res .= "<li>".
131+ "<a href=\"".&Wiki::create_page_url($name)."\">".Util::escapeHTML($name)."</a>".
132+ " - ".
133+ Util::escapeHTML(&get_match_content($page, $index)).
134+ "</li>\n";
102135 }
103- if($find==0){
104- print "<li>該当するページは存在しません。</li>\n";
105- }
106- print "</ul>\n";
136+ }
137+ print "$buf<ul>\n$res</ul>\n" if ($res ne '');
107138 }
108139
109140 &print_footer();
110141 }
111142
143+#-------------------------------------------------------------------------------
144+# 検索にマッチした行を取り出す関数
145+#-------------------------------------------------------------------------------
146+sub get_match_content {
147+ my $content = shift;
148+ my $index = shift;
149+
150+ # 検索にマッチした行の先頭文字の位置を求める。
151+ # ・$content の $index 番目の文字から先頭方向に改行文字を探す。
152+ # ・$index の位置を含む行の先頭文字の位置は改行文字の次なので +1 する。
153+ # ・先頭方向に改行文字が無かったら最初の行なので、結果は 0(先頭)。
154+ # (見つからないと rindex() = -1 になるので、+1 してちょうど 0)
155+ my $pre_index = rindex($content, "\n", $index) + 1;
156+
157+ # 検索にマッチした行の末尾文字の位置を求める。
158+ # ・$content の $index 番目の文字から末尾方向に改行文字を探す。
159+ my $post_index = index($content, "\n", $index);
160+
161+ # 末尾方向に改行文字がなかったら最終行なので $pre_index 以降全てを返却。
162+ return substr($content, $pre_index) if ($post_index == -1);
163+
164+ # 見つかった改行文字に挟まれた文字列を返却。
165+ return substr($content, $pre_index, $post_index - $pre_index);
166+}
167+
Show on old repository browser