OSDN Git Service

668c4b739ca9324fb1a3b2676d77773dce803b4d
[fswiki/fswiki.git] / plugin / core / Diff.pm
1 ###############################################################################
2
3 # º¹Ê¬¤òɽ¼¨¤¹¤ë¥×¥é¥°¥¤¥ó
4
5 ###############################################################################
6 package plugin::core::Diff;
7 use Algorithm::Diff qw(traverse_sequences);
8 use strict;
9
10 #==============================================================================
11 # ¥³¥ó¥¹¥È¥é¥¯¥¿
12 #==============================================================================
13 sub new {
14         my $class = shift;
15         my $self = {};
16         
17         return bless $self,$class;
18 }
19
20 #==============================================================================
21 # ¥¢¥¯¥·¥ç¥ó¤Î¼Â¹Ô
22 #==============================================================================
23 sub do_action {
24         my $self = shift;
25         my $wiki = shift;
26         my $cgi = $wiki->get_CGI;
27         
28         my $pagename = $cgi->param("page");
29         if($pagename eq ""){
30                 $pagename = $wiki->config("frontpage");
31         }
32         unless($wiki->can_show($pagename)){
33                 return $wiki->error("»²¾È¸¢¸Â¤¬¤¢¤ê¤Þ¤»¤ó¡£");
34         }
35         if($cgi->param('rollback') ne ''){
36                 return $self->rollback($wiki, $pagename, $cgi->param('rollback'));
37         } elsif($wiki->{storage}->backup_type eq 'all'){
38                 if($cgi->param('generation') eq '' && $cgi->param('diff') eq ''){
39                         return $self->show_history($wiki, $pagename);
40                 } else {
41                         if($cgi->param('generation') ne ''){
42                                 return $self->show_diff($wiki, $pagename, '', $cgi->param('generation'));
43                         }
44                         return $self->show_diff($wiki, $pagename, $cgi->param('from'), $cgi->param('to'));
45                 }
46         } else {
47                 return $self->show_diff($wiki, $pagename, '', 0);
48         }
49 }
50
51 #==============================================================================
52 # ÍúÎò¤«¤é¥Ú¡¼¥¸¤òÉü¸µ
53 #==============================================================================
54 sub rollback {
55         my $self = shift;
56         my $wiki = shift;
57         my $page = shift;
58         my $gen  = shift;
59         unless($wiki->can_modify_page($page)){
60                 return $wiki->error("¹¹¿·¸¢¸Â¤¬¤¢¤ê¤Þ¤»¤ó¡£");
61         }
62         my $source = $wiki->get_backup($page,$gen);
63         $wiki->save_page($page, $source);
64         return $wiki->redirect($page);
65 }
66
67 #==============================================================================
68 # ÍúÎò¤Î°ìÍ÷¤òɽ¼¨
69 # ¥¹¥È¥ì¡¼¥¸¤Îbackup_type=all¤Î¤È¤­
70 #==============================================================================
71 sub show_history {
72         my $self = shift;
73         my $wiki = shift;
74         my $page = shift;
75         
76         $wiki->set_title("$page¤ÎÊѹ¹ÍúÎò");
77         my $buf   = "<form><ul>\n";
78         my $count = 0;
79         my @list  = $wiki->{storage}->get_backup_list($page);
80         
81         if($#list == -1){
82                 return "ÍúÎò¤Ï¤¢¤ê¤Þ¤»¤ó¡£";
83         }
84         
85         # editlog¥×¥é¥°¥¤¥ó¤Î¥í¥°¤«¤éÊÔ½¸¼Ô¤Î¥æ¡¼¥¶Ì¾¤ò¼èÆÀ
86         my $editlog = {};
87         if($wiki->config('log_dir') ne "" && -e $wiki->config('log_dir')."/useredit.log"){
88                 open(DATA,$wiki->config('log_dir')."/useredit.log") or die $!;
89                 while(<DATA>){
90                         my($date, $time, $unixtime, $action, $subject, $id) = split(" ",$_);
91                         if($subject eq $page){
92                                 if($id eq ''){
93                                         $editlog->{$unixtime} = 'anonymous';
94                                 } else {
95                                         $editlog->{$unixtime} = $id;
96                                 }
97                         }
98                 }
99                 close(DATA);
100         }
101         
102         foreach my $time (@list){
103                 $buf .= "<li>";
104                 if($count == 0){
105                         $buf .= "<input type=\"radio\" name=\"from\" value=\"\" checked>".
106                                 "<input type=\"radio\" name=\"to\" value=\"\" checked>";
107                 } else {
108                         $buf .= "<input type=\"radio\" name=\"from\" value=\"".($#list-$count+1)."\">".
109                                 "<input type=\"radio\" name=\"to\" value=\"".($#list-$count+1)."\">";
110                 }
111                 $buf .= "<a href=\"".$wiki->create_url({ action=>"DIFF",page=>$page,generation=>($#list-$count) })."\">".&Util::format_date($time).
112                         "</a> <a href=\"".$wiki->create_url({ action=>"SOURCE",page=>$page,generation=>($#list-$count) })."\">¥½¡¼¥¹</a>";
113                         
114                 if(defined($editlog->{$time})){
115                         $buf .= " by ".$editlog->{$time};
116                 }
117                 
118                 $buf .=  "</li>\n";
119                 $count++;
120         }
121         return $buf."</ul>".
122         "<input type=\"hidden\" name=\"page\" value=\"".Util::escapeHTML($page)."\">".
123         "<input type=\"hidden\" name=\"action\" value=\"DIFF\">".
124         "<input type=\"submit\" name=\"diff\" value=\"ÁªÂò¤·¤¿¥ê¥Ó¥¸¥ç¥ó´Ö¤Îº¹Ê¬¤òɽ¼¨\"></form>\n";
125 }
126
127 #==============================================================================
128 # º¹Ê¬¤òɽ¼¨
129 #==============================================================================
130 sub show_diff {
131         my $self = shift;
132         my $wiki = shift;
133         my $page = shift;
134         my $from = shift;
135         my $to   = shift;
136         
137         $wiki->set_title("$page¤ÎÊѹ¹ÅÀ");
138         my ($diff, $rollback) = $self->get_diff_html($wiki,$page, $from, $to);
139         
140         $diff =~ s/\n/<br>/g;
141         
142         my $buf = qq|
143                 <ul>
144                   <li>Äɲ䵤줿Éôʬ¤Ï<ins class="diff">¤³¤Î¤è¤¦¤Ë</ins>ɽ¼¨¤µ¤ì¤Þ¤¹¡£</li>
145                   <li>ºï½ü¤µ¤ì¤¿Éôʬ¤Ï<del class="diff">¤³¤Î¤è¤¦¤Ë</del>ɽ¼¨¤µ¤ì¤Þ¤¹¡£</li>
146                 </ul>
147                 <div class="diff">$diff</div>
148         |;
149         
150         if($wiki->can_modify_page($page) && $rollback && $wiki->get_CGI->param('diff') eq ''){
151                 $buf .= qq|
152                         <form action="@{[$wiki->create_url()]}" method="POST">
153                                 <input type="submit" value="¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤ËÌ᤹"/>
154                                 <input type="hidden" name="action" value="DIFF"/>
155                                 <input type="hidden" name="page" value="@{[Util::escapeHTML($page)]}"/>
156                                 <input type="hidden" name="rollback" value="@{[Util::escapeHTML($from)]}"/>
157                         </form>
158                 |;
159         }
160         
161         return $buf;
162 }
163
164 #==============================================================================
165 # º¹Ê¬Ê¸»úÎó¤ò¼èÆÀ
166 #==============================================================================
167 sub get_diff_text {
168         my $self = shift;
169         my $wiki = shift;
170         my $page = shift;
171         my $gen  = shift;
172         
173         my $source1 = $wiki->get_page($page);
174         my $source2 = $wiki->get_backup($page, $gen);
175         my $format  = $wiki->get_edit_format();
176         
177         $source1 = $wiki->convert_from_fswiki($source1, $format);
178         $source2 = $wiki->convert_from_fswiki($source2, $format);
179         
180         my $diff_text = "";
181         my @msg1 = split(/\n/,$source1);
182         my @msg2 = split(/\n/,$source2);
183         my $msgrefA = \@msg2;
184         my $msgrefB = \@msg1;
185         
186         traverse_sequences($msgrefA, $msgrefB,
187                 {
188                         MATCH => sub {},
189                         DISCARD_A => sub {
190                                 my ($a, $b) = @_;
191                                 $diff_text .= "-".$msgrefA->[$a]."\n";
192                         },
193                         DISCARD_B => sub {
194                                 my ($a, $b) = @_;
195                                 $diff_text .= "+".$msgrefB->[$b]."\n";
196                         }
197                 });
198         
199         return $diff_text;
200 }
201
202 #==============================================================================
203 # º¹Ê¬Ê¸»úÎó¤òɽ¼¨ÍÑHTML¤È¤·¤Æ¼èÆÀ
204 #==============================================================================
205 sub get_diff_html {
206         my $self = shift;
207         my $wiki = shift;
208         my $page = shift;
209         my $from = shift;
210         my $to   = shift;
211         
212         my $source1 = '';
213         if($from ne ''){
214                 $source1 = $wiki->get_backup($page, $from);
215         } else {
216                 $source1 = $wiki->get_page($page);
217         }
218         my $source2 = '';
219         if($to ne ''){
220                 $source2 = $wiki->get_backup($page, $to);
221         } else {
222                 $source2 = $wiki->get_page($page);
223         }
224         my $format  = $wiki->get_edit_format();
225         
226         $source1 = $wiki->convert_from_fswiki($source1, $format);
227         $source2 = $wiki->convert_from_fswiki($source2, $format);
228         
229         return (&_get_diff_html($source1, $source2), $source2 ne "");
230 }
231
232 #==============================================================================
233 # º¹Ê¬HTML¤òÀ¸À®¤¹¤ë´Ø¿ô
234 #==============================================================================
235 sub _get_diff_html {
236         my $source1 = shift;
237         my $source2 = shift;
238         
239         my @msg1 = _str_jfold($source1, 1);
240         my @msg2 = _str_jfold($source2, 1);
241         
242         my $msgrefA = \@msg2;
243         my $msgrefB = \@msg1;
244         
245         my $diff_text = "";
246         
247         traverse_sequences($msgrefA, $msgrefB,
248                 {
249                         MATCH => sub {
250                                 my ($a, $b) = @_;
251                                 $diff_text .= Util::escapeHTML($msgrefA->[$a]);
252                         },
253                         DISCARD_A => sub {
254                                 my ($a, $b) = @_;
255                                 $diff_text .= "<del class=\"diff\">".Util::escapeHTML($msgrefA->[$a])."</del><wbr>";
256                         },
257                         DISCARD_B => sub {
258                                 my ($a, $b) = @_;
259                                 $diff_text .= "<ins class=\"diff\">".Util::escapeHTML($msgrefB->[$b])."</ins><wbr>";
260                         }
261                 });
262         
263         return $diff_text;
264 }
265
266 #==============================================================================
267 # Ê¸»úÎó¤ò»ØÄêʸ»ú¿ô¤òʬ³ä
268 #==============================================================================
269 sub _str_jfold {\r
270   my $str    = shift;       #»ØÄêʸ»úÎó\r
271   my $byte   = shift;       #»ØÄê¥Ð¥¤¥È\r
272   my $j      = new Jcode($str);\r
273   my @result = ();\r
274 \r
275   foreach my $buff ( $j->jfold($byte) ){\r
276     push(@result, $buff);\r
277   }\r
278 \r
279   return(@result);\r
280 }
281
282 #==============================================================================
283 # ¥Ú¡¼¥¸É½¼¨»þ¤Î¥Õ¥Ã¥¯¥á¥½¥Ã¥É
284 # ¡Öº¹Ê¬¡×¥á¥Ë¥å¡¼¤òÍ­¸ú¤Ë¤·¤Þ¤¹
285 #==============================================================================
286 sub hook {
287         my $self = shift;
288         my $wiki = shift;
289         my $cgi  = $wiki->get_CGI;
290         my $page = $cgi->param("page");
291         if($wiki->{storage}->backup_type eq 'all'){
292                 $wiki->add_menu("ÍúÎò",$wiki->create_url({ action=>"DIFF",page=>$page }));
293         } else {
294                 $wiki->add_menu("º¹Ê¬",$wiki->create_url({ action=>"DIFF",page=>$page }));
295         }
296 }
297
298 1;