]> git.p6c8.net - devedit.git/blob - modules/Command.pm
In directory listing, when a file cannot be viewed or edited, a tool tip on the ...
[devedit.git] / modules / Command.pm
1 package Command;
2
3 #
4 # Dev-Editor - Module Command
5 #
6 # Execute Dev-Editor's commands
7 #
8 # Author: Patrick Canterino <patshaping@gmx.net>
9 # Last modified: 2003-11-10
10 #
11
12 use strict;
13
14 use vars qw(@EXPORT
15 $script);
16
17 use File::Access;
18 use File::Copy;
19
20 use HTML::Entities;
21 use Output;
22 use POSIX qw(strftime);
23 use Tool;
24
25 $script = $ENV{'SCRIPT_NAME'};
26
27 ### Export ###
28
29 use base qw(Exporter);
30
31 @EXPORT = qw(exec_show
32 exec_beginedit
33 exec_endedit
34 exec_mkfile
35 exec_mkdir
36 exec_workwithfile
37 exec_copy
38 exec_rename
39 exec_remove
40 exec_unlock);
41
42 # exec_show()
43 #
44 # View a directory or a file
45 #
46 # Params: 1. Reference to user input hash
47 # 2. Reference to config hash
48 #
49 # Return: Output of the command (Scalar Reference)
50
51 sub exec_show($$$)
52 {
53 my ($data,$config) = @_;
54 my $physical = $data->{'physical'};
55 my $virtual = $data->{'virtual'};
56 my $output;
57
58 if(-d $physical)
59 {
60 # Create directory listing
61
62 my $direntries = dir_read($physical);
63 return error("Reading of directory $virtual failed.",upper_path($virtual)) unless($direntries);
64
65 my $files = $direntries->{'files'};
66 my $dirs = $direntries->{'dirs'};
67
68 $output .= htmlhead("Directory listing of $virtual");
69 $output .= equal_url($config->{'httproot'},$virtual);
70 $output .= "<hr>\n\n<pre>\n";
71
72 # Create the link to the upper directory
73 # (only if we are not in the root directory)
74
75 unless($virtual eq "/")
76 {
77 my $upper = $physical."/..";
78 my @stat = stat($upper);
79
80 $output .= " [SUBDIR] ";
81 $output .= strftime("%d.%m.%Y %H:%M",localtime($stat[9]));
82 $output .= " " x 10;
83 $output .= "<a href=\"$script?command=show&file=".encode_entities(upper_path($virtual))."\">../</a>\n";
84 }
85
86 # Get the length of the longest file/directory name
87
88 my $max_name_len = 0;
89
90 foreach(@$dirs,@$files)
91 {
92 my $length = length($_);
93 $max_name_len = $length if($length > $max_name_len);
94 }
95
96 # Directories
97
98 foreach my $dir(@$dirs)
99 {
100 my @stat = stat($physical."/".$dir);
101
102 $output .= " ";
103 $output .= "[SUBDIR] ";
104 $output .= strftime($config->{'timeformat'},localtime($stat[9]));
105 $output .= " " x 10;
106 $output .= "<a href=\"$script?command=show&file=".encode_entities($virtual.$dir)."/\">".encode_entities($dir)."/</a>\n";
107 }
108
109 # Files
110
111 foreach my $file(@$files)
112 {
113 my $phys_path = $physical."/".$file;
114 my $virt_path = encode_entities($virtual.$file);
115
116 my @stat = stat($phys_path);
117 my $in_use = $data->{'uselist'}->in_use($virtual.$file);
118
119 $output .= " " x (10 - length($stat[7]));
120 $output .= $stat[7];
121 $output .= " ";
122 $output .= strftime($config->{'timeformat'},localtime($stat[9]));
123 $output .= " " x 10;
124 $output .= encode_entities($file);
125 $output .= " " x ($max_name_len - length($file))."\t (";
126
127 # Link "View"
128
129 if(-r $phys_path && -T $phys_path)
130 {
131 $output .= "<a href=\"$script?command=show&file=$virt_path\">View</a>";
132 }
133 else
134 {
135 $output .= '<span style="color:#C0C0C0" title="';
136
137 $output .= (not -r $phys_path) ? "Not readable" :
138 (-B $phys_path) ? "Binary file" : "";
139
140 $output .= '">View</span>';
141 }
142
143 $output .= " | ";
144
145 # Link "Edit"
146
147 if(-w $phys_path && -r $phys_path && -T $phys_path && not $in_use)
148 {
149 $output .= "<a href=\"$script?command=beginedit&file=$virt_path\">Edit</a>";
150 }
151 else
152 {
153 $output .= '<span style="color:#C0C0C0" title="';
154
155 $output .= (not -r $phys_path) ? "Not readable" :
156 (not -w $phys_path) ? "Read only" :
157 (-B $phys_path) ? "Binary file" :
158 ($in_use) ? "In use" : "";
159
160 $output .= '">Edit</span>';
161 }
162
163 # Link "Do other stuff"
164
165 $output .= " | <a href=\"$script?command=workwithfile&file=$virt_path\">Do other stuff</a>)\n";
166 }
167
168 $output .= "</pre>\n\n<hr>\n\n";
169
170 # Bottom of directory listing
171 # (Fields for creating files and directories)
172
173 $output .= <<END;
174 <table border="0">
175 <tr>
176 <form action="$script">
177 <input type="hidden" name="command" value="mkdir">
178 <input type="hidden" name="curdir" value="$virtual">
179 <td>Create new directory:</td>
180 <td>$virtual <input type="text" name="newfile"> <input type="submit" value="Create!"></td>
181 </form>
182 </tr>
183 <tr>
184 <td>Create new file:</td>
185 <form action="$script">
186 <input type="hidden" name="command" value="mkfile">
187 <input type="hidden" name="curdir" value="$virtual">
188 <td>$virtual <input type="text" name="newfile"> <input type="submit" value="Create!"></td>
189 </form>
190 </tr>
191 </table>
192
193 <hr>
194 END
195 $output .= htmlfoot;
196 }
197 else
198 {
199 # View a file
200
201 return error("You have not enough permissions to view this file.",upper_path($virtual)) unless(-r $physical);
202
203 # Check on binary files
204 # We have to do it in this way, or empty files
205 # will be recognized as binary files
206
207 unless(-T $physical)
208 {
209 # Binary file
210
211 return error("This editor is not able to view/edit binary files.",upper_path($virtual));
212 }
213 else
214 {
215 # Text file
216
217 $output = htmlhead("Contents of file ".encode_entities($virtual));
218 $output .= equal_url($config->{'httproot'},$virtual);
219 $output .= dir_link($virtual);
220
221 $output .= '<div style="background-color:#FFFFE0;border:1px solid black;margin-top:10px;width:100%">'."\n";
222 $output .= '<pre style="color:#0000C0;">'."\n";
223 $output .= encode_entities(${file_read($physical)});
224 $output .= "\n</pre>\n</div>";
225
226 $output .= htmlfoot;
227 }
228 }
229
230 return \$output;
231 }
232
233 # exec_beginedit
234 #
235 # Lock a file and display a form to edit it
236 #
237 # Params: 1. Reference to user input hash
238 # 2. Reference to config hash
239 #
240 # Return: Output of the command (Scalar Reference)
241
242 sub exec_beginedit($$)
243 {
244 my ($data,$config) = @_;
245 my $physical = $data->{'physical'};
246 my $virtual = $data->{'virtual'};
247 my $uselist = $data->{'uselist'};
248
249 return error("You cannot edit directories.",upper_path($virtual)) if(-d $physical);
250 return error_in_use($virtual) if($uselist->in_use($virtual));
251 return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
252
253 # Check on binary files
254
255 unless(-T $physical)
256 {
257 # Binary file
258
259 return error("This editor is not able to view/edit binary files.",upper_path($virtual));
260 }
261 else
262 {
263 # Text file
264
265 $uselist->add_file($virtual);
266 $uselist->save;
267
268 my $dir = upper_path($virtual);
269 my $content = encode_entities(${file_read($physical)});
270
271 my $equal_url = equal_url($config->{'httproot'},$virtual);
272
273 $virtual = encode_entities($virtual);
274
275 my $output = htmlhead("Edit file $virtual");
276 $output .= $equal_url;
277 $output .= <<END;
278 <p><b style="color:#FF0000">Caution!</b> This file is locked for other users while you are editing it. To unlock it, click <i>Save and exit</i> or <i>Exit WITHOUT saving</i>. Please <b>don't</b> click the <i>Reload</i> button in your browser! This will confuse the editor.</p>
279
280 <form action="$script" method="get">
281 <input type="hidden" name="command" value="canceledit">
282 <input type="hidden" name="file" value="$virtual">
283 <p><input type="submit" value="Exit WITHOUT saving"></p>
284 </form>
285
286 <form action="$script" method="post">
287 <input type="hidden" name="command" value="endedit">
288 <input type="hidden" name="file" value="$virtual">
289
290 <table width="100%" border="1">
291 <tr>
292 <td width="50%" align="center">
293 <input type="hidden" name="file" value="$virtual">
294 <input type="checkbox" name="saveas" value="1"> Save as new file: $dir <input type=text name="newfile" value=""></td>
295 <td width="50%" align="center"><input type="checkbox" name="encode_iso" value="1"> Encode ISO-8859-1 special chars</td>
296 </tr>
297 <tr>
298 <td align="center"><input type="reset" value="Reset form"></td>
299 <td align="center"><input type="submit" value="Save and exit"></td>
300 </tr>
301 </table>
302
303 <textarea name="filecontent" rows="25" cols="120">$content</textarea>
304 </form>
305 END
306
307 $output .= htmlfoot;
308
309 return \$output;
310 }
311 }
312
313 # exec_endedit()
314 #
315 # Save a file, unlock it and return to directory view
316 #
317 # Params: 1. Reference to user input hash
318 # 2. Reference to config hash
319 #
320 # Return: Output of the command (Scalar Reference)
321
322 sub exec_endedit($$)
323 {
324 my ($data,$config) = @_;
325 my $physical = $data->{'physical'};
326 my $virtual = $data->{'virtual'};
327 my $content = $data->{'cgi'}->param('filecontent');
328
329 return error("You cannot edit directories.") if(-d $physical);
330 return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
331
332 # Normalize newlines
333
334 $content =~ s/\015\012|\012|\015/\n/g;
335
336 if($data->{'cgi'}->param('encode_iso'))
337 {
338 # Encode all ISO-8859-1 special chars
339
340 $content = encode_entities($content,"\200-\377");
341 }
342
343 if($data->{'cgi'}->param('saveas'))
344 {
345 # Create the new filename
346
347 $physical = $data->{'new_physical'};
348 $virtual = $data->{'new_virtual'};
349 }
350
351 if(file_save($physical,\$content))
352 {
353 # Saving of the file was successful - so unlock it!
354
355 return exec_unlock($data,$config);
356 }
357 else
358 {
359 return error("Saving of file '".encode_entities($virtual)."' failed'.",upper_path($virtual));
360 }
361 }
362
363 # exec_mkfile()
364 #
365 # Create a file and return to directory view
366 #
367 # Params: 1. Reference to user input hash
368 # 2. Reference to config hash
369 #
370 # Return: Output of the command (Scalar Reference)
371
372 sub exec_mkfile($$)
373 {
374 my ($data,$config) = @_;
375 my $new_physical = $data->{'new_physical'};
376 my $new_virtual = $data->{'new_virtual'};
377 my $dir = upper_path($new_virtual);
378 $new_virtual = encode_entities($new_virtual);
379
380 return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
381
382 file_create($new_physical) or return error("Could not create file '$new_virtual'.",$dir);
383 return devedit_reload({command => 'show', file => $dir});
384 }
385
386 # exec_mkdir()
387 #
388 # Create a directory and return to directory view
389 #
390 # Params: 1. Reference to user input hash
391 # 2. Reference to config hash
392 #
393 # Return: Output of the command (Scalar Reference)
394
395 sub exec_mkdir($$)
396 {
397 my ($data,$config) = @_;
398 my $new_physical = $data->{'new_physical'};
399 my $new_virtual = $data->{'new_virtual'};
400 my $dir = upper_path($new_virtual);
401 $new_virtual = encode_entities($new_virtual);
402
403 return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
404
405 mkdir($new_physical) or return error("Could not create directory '$new_virtual'.",$dir);
406 return devedit_reload({command => 'show', file => $dir});
407 }
408
409 # exec_workwithfile()
410 #
411 # Display a form for renaming/copying/deleting/unlocking a file
412 #
413 # Params: 1. Reference to user input hash
414 # 2. Reference to config hash
415 #
416 # Return: Output of the command (Scalar Reference)
417
418 sub exec_workwithfile($$)
419 {
420 my ($data,$config) = @_;
421 my $physical = $data->{'physical'};
422 my $virtual = $data->{'virtual'};
423 my $unused = $data->{'uselist'}->unused($virtual);
424
425 my $dir = encode_entities(upper_path($virtual));
426
427 my $output = htmlhead("Work with file ".encode_entities($virtual));
428 $output .= equal_url($config->{'httproot'},$virtual);
429
430 $virtual = encode_entities($virtual);
431
432 $output .= dir_link($virtual);
433 $output .= "<p><b>Note:</b> On UNIX systems, filenames are <b>case-sensitive</b>!</p>\n\n";
434
435 $output .= "<p>Someone else is currently editing this file. So not all features are available.</p>\n\n" unless($unused);
436
437 $output .= "<hr>\n\n";
438
439 # Copying of the file is always allowed - but we need read access
440
441 if(-r $physical)
442 {
443 $output .= <<END;
444 <h2>Copy</h2>
445
446 <form action="$script">
447 <input type="hidden" name="command" value="copy">
448 <input type="hidden" name="file" value="$virtual">
449 <p>Copy file '$virtual' to: $dir <input type="text" name="newfile" size="50"> <input type="submit" value="Copy!"></p>
450 </form>
451
452 <hr>
453
454 END
455 }
456
457 if($unused)
458 {
459 # File is not locked
460 # Allow renaming and deleting the file
461
462 $output .= <<END;
463 <h2>Move/rename</h2>
464
465 <form action="$script">
466 <input type="hidden" name="command" value="rename">
467 <input type="hidden" name="file" value="$virtual">
468 <p>Move/Rename file '$virtual' to: $dir <input type="text" name="newfile" size="50"> <input type="submit" value="Move/Rename!"></p>
469 </form>
470
471 <hr>
472
473 <h2>Delete</h2>
474
475 <form action="$script" method="get">
476 <input type="hidden" name="file" value="$virtual">
477 <input type="hidden" name="command" value="remove">
478 <p><input type="submit" value="Delete file '$virtual'!"></p>
479 </form>
480 END
481 }
482 else
483 {
484 # File is locked
485 # Just display a button for unlocking it
486
487 $output .= <<END;
488 <h2>Unlock file</h2>
489
490 <p>Someone else is currently editing this file. At least, the file is marked so. Maybe, someone who was editing the file has forgotten to unlock it. In this case (and <b>only</b> in this case) you can unlock the file using this button:</p>
491
492 <form action="$script" method="get">
493 <input type="hidden" name="file" value="$virtual">
494 <input type="hidden" name="command" value="unlock">
495 <p><input type="submit" value="Unlock file '$virtual'"></p>
496 </form>
497 END
498 }
499
500 $output .= "\n<hr>";
501 $output .= htmlfoot;
502
503 return \$output;
504 }
505
506 # exec_copy()
507 #
508 # Copy a file and return to directory view
509 #
510 # Params: 1. Reference to user input hash
511 # 2. Reference to config hash
512 #
513 # Return: Output of the command (Scalar Reference)
514
515 sub exec_copy($$)
516 {
517 my ($data,$config) = @_;
518 my $physical = $data->{'physical'};
519 my $virtual = encode_entities($data->{'virtual'});
520 my $new_physical = $data->{'new_physical'};
521 my $new_virtual = $data->{'new_virtual'};
522 my $dir = upper_path($new_virtual);
523 $new_virtual = encode_entities($new_virtual);
524
525 return error("This editor is not able to copy directories.") if(-d $physical);
526 return error("You have not enough permissions to copy this file.") unless(-r $physical);
527
528 if(-e $new_physical)
529 {
530 return error("A file or directory called '$new_virtual' already exists and this editor is currently not able to ask to overwrite the existing file or directory.",upper_path($virtual));
531 }
532
533 copy($physical,$new_physical) or return error("Could not copy '$virtual' to '$new_virtual'",upper_path($virtual));
534 return devedit_reload({command => 'show', file => $dir});
535 }
536
537 # exec_rename()
538 #
539 # Rename/move a file and return to directory view
540 #
541 # Params: 1. Reference to user input hash
542 # 2. Reference to config hash
543 #
544 # Return: Output of the command (Scalar Reference)
545
546 sub exec_rename($$)
547 {
548 my ($data,$config) = @_;
549 my $physical = $data->{'physical'};
550 my $virtual = $data->{'virtual'};
551 my $new_physical = $data->{'new_physical'};
552 my $new_virtual = $data->{'new_virtual'};
553 my $dir = upper_path($new_virtual);
554 $new_virtual = encode_entities($new_virtual);
555
556 return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
557
558 if(-e $new_physical)
559 {
560 return error("A file or directory called '$new_virtual' already exists and this editor is currently not able to ask to overwrite the existing file or directory.",upper_path($virtual));
561 }
562
563 rename($physical,$new_physical) or return error("Could not move/rename '".encode_entities($virtual)."' to '$new_virtual'.",upper_path($virtual));
564 return devedit_reload({command => 'show', file => $dir});
565 }
566
567 # exec_remove()
568 #
569 # Remove a file and return to directory view
570 #
571 # Params: 1. Reference to user input hash
572 # 2. Reference to config hash
573 #
574 # Return: Output of the command (Scalar Reference)
575
576 sub exec_remove($$)
577 {
578 my ($data,$config) = @_;
579 my $physical = $data->{'physical'};
580 my $virtual = $data->{'virtual'};
581
582 return error("Deleting directories is currently unsupported.",upper_path($virtual)) if(-d $physical);
583 return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
584
585 unlink($physical) or return error("Could not delete file '".encode_entities($virtual)."'.",upper_path($virtual));
586 return devedit_reload({command => 'show', file => upper_path($virtual)});
587 }
588
589 # exec_unlock()
590 #
591 # Remove a file from the list of used files and
592 # return to directory view
593 #
594 # Params: 1. Reference to user input hash
595 # 2. Reference to config hash
596 #
597 # Return: Output of the command (Scalar Reference)
598
599 sub exec_unlock($$)
600 {
601 my ($data,$config) = @_;
602 my $virtual = $data->{'virtual'};
603 my $uselist = $data->{'uselist'};
604
605 $uselist->remove_file($virtual);
606 $uselist->save;
607
608 return devedit_reload({command => 'show', file => upper_path($virtual)});
609 }
610
611 # it's true, baby ;-)
612
613 1;
614
615 #
616 ### End ###

patrick-canterino.de