]> git.p6c8.net - devedit.git/blob - modules/Command.pm
Added directory links in some error messages
[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-10-30
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 .= ($in_use) ? " (IN USE) " : (not -T $phys_path) ? " (BINARY) " : " " x 10;
124 $output .= encode_entities($file);
125 $output .= " " x ($max_name_len - length($file))."\t (";
126
127 $output .= (-r $phys_path && -T $phys_path)
128 ? "<a href=\"$script?command=show&file=$virt_path\">View</a>"
129 : '<span style="color:#C0C0C0">View</span>';
130
131 $output .= " | ";
132
133 $output .= (-w $phys_path && -r $phys_path && -T $phys_path && not $in_use)
134 ? "<a href=\"$script?command=beginedit&file=$virt_path\">Edit</a>"
135 : '<span style="color:#C0C0C0">Edit</span>';
136
137 $output .= " | <a href=\"$script?command=workwithfile&file=$virt_path\">Do other stuff</a>)\n";
138 }
139
140 $output .= "</pre>\n\n<hr>\n\n";
141
142 # Bottom of directory listing
143 # (Fields for creating files and directories)
144
145 $output .= <<END;
146 <table border="0">
147 <tr>
148 <form action="$script">
149 <input type="hidden" name="command" value="mkdir">
150 <input type="hidden" name="curdir" value="$virtual">
151 <td>Create new directory:</td>
152 <td>$virtual <input type="text" name="newfile"> <input type="submit" value="Create!"></td>
153 </form>
154 </tr>
155 <tr>
156 <td>Create new file:</td>
157 <form action="$script">
158 <input type="hidden" name="command" value="mkfile">
159 <input type="hidden" name="curdir" value="$virtual">
160 <td>$virtual <input type="text" name="newfile"> <input type="submit" value="Create!"></td>
161 </form>
162 </tr>
163 </table>
164
165 <hr>
166 END
167 $output .= htmlfoot;
168 }
169 else
170 {
171 # View a file
172
173 return error("You have not enough permissions to view this file.",upper_path($virtual)) unless(-r $physical);
174
175 # Check on binary files
176 # We have to do it in this way, or empty files
177 # will be recognized as binary files
178
179 unless(-T $physical)
180 {
181 # Binary file
182
183 return error("This editor is not able to view/edit binary files.",upper_path($virtual));
184 }
185 else
186 {
187 # Text file
188
189 $output = htmlhead("Contents of file ".encode_entities($virtual));
190 $output .= equal_url($config->{'httproot'},$virtual);
191 $output .= dir_link($virtual);
192
193 $output .= '<div style="background-color:#FFFFE0;border:1px solid black;margin-top:10px;width:100%">'."\n";
194 $output .= '<pre style="color:#0000C0;">'."\n";
195 $output .= encode_entities(${file_read($physical)});
196 $output .= "\n</pre>\n</div>";
197
198 $output .= htmlfoot;
199 }
200 }
201
202 return \$output;
203 }
204
205 # exec_beginedit
206 #
207 # Lock a file and display a form to edit it
208 #
209 # Params: 1. Reference to user input hash
210 # 2. Reference to config hash
211 #
212 # Return: Output of the command (Scalar Reference)
213
214 sub exec_beginedit($$)
215 {
216 my ($data,$config) = @_;
217 my $physical = $data->{'physical'};
218 my $virtual = $data->{'virtual'};
219 my $uselist = $data->{'uselist'};
220
221 return error("You cannot edit directories.",upper_path($virtual)) if(-d $physical);
222 return error_in_use($virtual) if($uselist->in_use($virtual));
223 return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
224
225 # Check on binary files
226
227 unless(-T $physical)
228 {
229 # Binary file
230
231 return error("This editor is not able to view/edit binary files.",upper_path($virtual));
232 }
233 else
234 {
235 # Text file
236
237 $uselist->add_file($virtual);
238 $uselist->save;
239
240 my $dir = upper_path($virtual);
241 my $content = encode_entities(${file_read($physical)});
242
243 my $equal_url = equal_url($config->{'httproot'},$virtual);
244
245 $virtual = encode_entities($virtual);
246
247 my $output = htmlhead("Edit file $virtual");
248 $output .= $equal_url;
249 $output .= <<END;
250 <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>
251
252 <form action="$script" method="get">
253 <input type="hidden" name="command" value="canceledit">
254 <input type="hidden" name="file" value="$virtual">
255 <p><input type="submit" value="Exit WITHOUT saving"></p>
256 </form>
257
258 <form action="$script" method="post">
259 <input type="hidden" name="command" value="endedit">
260 <input type="hidden" name="file" value="$virtual">
261
262 <table width="100%" border="1">
263 <tr>
264 <td width="50%" align="center">
265 <input type="hidden" name="file" value="$virtual">
266 <input type="checkbox" name="saveas" value="1"> Save as new file: $dir <input type=text name="newfile" value=""></td>
267 <td width="50%" align="center"><input type="checkbox" name="encode_iso" value="1"> Encode ISO-8859-1 special chars</td>
268 </tr>
269 <tr>
270 <td align="center"><input type="reset" value="Reset form"></td>
271 <td align="center"><input type="submit" value="Save and exit"></td>
272 </tr>
273 </table>
274
275 <textarea name="filecontent" rows="25" cols="120">$content</textarea>
276 </form>
277 END
278
279 $output .= htmlfoot;
280
281 return \$output;
282 }
283 }
284
285 # exec_endedit()
286 #
287 # Save a file, unlock it and return to directory view
288 #
289 # Params: 1. Reference to user input hash
290 # 2. Reference to config hash
291 #
292 # Return: Output of the command (Scalar Reference)
293
294 sub exec_endedit($$)
295 {
296 my ($data,$config) = @_;
297 my $physical = $data->{'physical'};
298 my $virtual = $data->{'virtual'};
299 my $content = $data->{'cgi'}->param('filecontent');
300
301 return error("You cannot edit directories.") if(-d $physical);
302 return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
303
304 # Normalize newlines
305
306 $content =~ s/\015\012|\012|\015/\n/g;
307
308 if($data->{'cgi'}->param('encode_iso'))
309 {
310 # Encode all ISO-8859-1 special chars
311
312 $content = encode_entities($content,"\200-\377");
313 }
314
315 if($data->{'cgi'}->param('saveas'))
316 {
317 # Create the new filename
318
319 $physical = $data->{'new_physical'};
320 $virtual = $data->{'new_virtual'};
321 }
322
323 if(file_save($physical,\$content))
324 {
325 # Saving of the file was successful - so unlock it!
326
327 return exec_unlock($data,$config);
328 }
329 else
330 {
331 return error("Saving of file '".encode_entities($virtual)."' failed'.",upper_path($virtual));
332 }
333 }
334
335 # exec_mkfile()
336 #
337 # Create a file and return to directory view
338 #
339 # Params: 1. Reference to user input hash
340 # 2. Reference to config hash
341 #
342 # Return: Output of the command (Scalar Reference)
343
344 sub exec_mkfile($$)
345 {
346 my ($data,$config) = @_;
347 my $new_physical = $data->{'new_physical'};
348 my $new_virtual = $data->{'new_virtual'};
349 my $dir = upper_path($new_virtual);
350 $new_virtual = encode_entities($new_virtual);
351
352 return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
353
354 file_create($new_physical) or return error("Could not create file '$new_virtual'.",$dir);
355 return devedit_reload({command => 'show', file => $dir});
356 }
357
358 # exec_mkdir()
359 #
360 # Create a directory and return to directory view
361 #
362 # Params: 1. Reference to user input hash
363 # 2. Reference to config hash
364 #
365 # Return: Output of the command (Scalar Reference)
366
367 sub exec_mkdir($$)
368 {
369 my ($data,$config) = @_;
370 my $new_physical = $data->{'new_physical'};
371 my $new_virtual = $data->{'new_virtual'};
372 my $dir = upper_path($new_virtual);
373 $new_virtual = encode_entities($new_virtual);
374
375 return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
376
377 mkdir($new_physical) or return error("Could not create directory '$new_virtual'.",$dir);
378 return devedit_reload({command => 'show', file => $dir});
379 }
380
381 # exec_workwithfile()
382 #
383 # Display a form for renaming/copying/deleting/unlocking a file
384 #
385 # Params: 1. Reference to user input hash
386 # 2. Reference to config hash
387 #
388 # Return: Output of the command (Scalar Reference)
389
390 sub exec_workwithfile($$)
391 {
392 my ($data,$config) = @_;
393 my $physical = $data->{'physical'};
394 my $virtual = $data->{'virtual'};
395 my $unused = $data->{'uselist'}->unused($virtual);
396
397 my $dir = encode_entities(upper_path($virtual));
398
399 my $output = htmlhead("Work with file ".encode_entities($virtual));
400 $output .= equal_url($config->{'httproot'},$virtual);
401
402 $virtual = encode_entities($virtual);
403
404 $output .= dir_link($virtual);
405 $output .= "<p><b>Note:</b> On UNIX systems, filenames are <b>case-sensitive</b>!</p>\n\n";
406
407 $output .= "<p>Someone else is currently editing this file. So not all features are available.</p>\n\n" unless($unused);
408
409 $output .= "<hr>\n\n";
410
411 # Copying of the file is always allowed - but we need read access
412
413 if(-r $physical)
414 {
415 $output .= <<END;
416 <h2>Copy</h2>
417
418 <form action="$script">
419 <input type="hidden" name="command" value="copy">
420 <input type="hidden" name="file" value="$virtual">
421 <p>Copy file '$virtual' to: $dir <input type="text" name="newfile" size="50"> <input type="submit" value="Copy!"></p>
422 </form>
423
424 <hr>
425
426 END
427 }
428
429 if($unused)
430 {
431 # File is not locked
432 # Allow renaming and deleting the file
433
434 $output .= <<END;
435 <h2>Move/rename</h2>
436
437 <form action="$script">
438 <input type="hidden" name="command" value="rename">
439 <input type="hidden" name="file" value="$virtual">
440 <p>Move/Rename file '$virtual' to: $dir <input type="text" name="newfile" size="50"> <input type="submit" value="Move/Rename!"></p>
441 </form>
442
443 <hr>
444
445 <h2>Delete</h2>
446
447 <form action="$script" method="get">
448 <input type="hidden" name="file" value="$virtual">
449 <input type="hidden" name="command" value="remove">
450 <p><input type="submit" value="Delete file '$virtual'!"></p>
451 </form>
452 END
453 }
454 else
455 {
456 # File is locked
457 # Just display a button for unlocking it
458
459 $output .= <<END;
460 <h2>Unlock file</h2>
461
462 <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>
463
464 <form action="$script" method="get">
465 <input type="hidden" name="file" value="$virtual">
466 <input type="hidden" name="command" value="unlock">
467 <p><input type="submit" value="Unlock file '$virtual'"></p>
468 </form>
469 END
470 }
471
472 $output .= "\n<hr>";
473 $output .= htmlfoot;
474
475 return \$output;
476 }
477
478 # exec_copy()
479 #
480 # Copy a file and return to directory view
481 #
482 # Params: 1. Reference to user input hash
483 # 2. Reference to config hash
484 #
485 # Return: Output of the command (Scalar Reference)
486
487 sub exec_copy($$)
488 {
489 my ($data,$config) = @_;
490 my $physical = $data->{'physical'};
491 my $virtual = encode_entities($data->{'virtual'});
492 my $new_physical = $data->{'new_physical'};
493 my $new_virtual = $data->{'new_virtual'};
494 my $dir = upper_path($new_virtual);
495 $new_virtual = encode_entities($new_virtual);
496
497 return error("This editor is not able to copy directories.") if(-d $physical);
498 return error("You have not enough permissions to copy this file.") unless(-r $physical);
499
500 if(-e $new_physical)
501 {
502 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));
503 }
504
505 copy($physical,$new_physical) or return error("Could not copy '$virtual' to '$new_virtual'",upper_path($virtual));
506 return devedit_reload({command => 'show', file => $dir});
507 }
508
509 # exec_rename()
510 #
511 # Rename/move a file and return to directory view
512 #
513 # Params: 1. Reference to user input hash
514 # 2. Reference to config hash
515 #
516 # Return: Output of the command (Scalar Reference)
517
518 sub exec_rename($$)
519 {
520 my ($data,$config) = @_;
521 my $physical = $data->{'physical'};
522 my $virtual = $data->{'virtual'};
523 my $new_physical = $data->{'new_physical'};
524 my $new_virtual = $data->{'new_virtual'};
525 my $dir = upper_path($new_virtual);
526 $new_virtual = encode_entities($new_virtual);
527
528 return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
529
530 if(-e $new_physical)
531 {
532 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));
533 }
534
535 rename($physical,$new_physical) or return error("Could not move/rename '".encode_entities($virtual)."' to '$new_virtual'.",upper_path($virtual));
536 return devedit_reload({command => 'show', file => $dir});
537 }
538
539 # exec_remove()
540 #
541 # Remove a file and return to directory view
542 #
543 # Params: 1. Reference to user input hash
544 # 2. Reference to config hash
545 #
546 # Return: Output of the command (Scalar Reference)
547
548 sub exec_remove($$)
549 {
550 my ($data,$config) = @_;
551 my $physical = $data->{'physical'};
552 my $virtual = $data->{'virtual'};
553
554 return error("Deleting directories is currently unsupported.",upper_path($virtual)) if(-d $physical);
555 return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
556
557 unlink($physical) or return error("Could not delete file '".encode_entities($virtual)."'.",upper_path($virtual));
558 return devedit_reload({command => 'show', file => upper_path($virtual)});
559 }
560
561 # exec_unlock()
562 #
563 # Remove a file from the list of used files and
564 # return to directory view
565 #
566 # Params: 1. Reference to user input hash
567 # 2. Reference to config hash
568 #
569 # Return: Output of the command (Scalar Reference)
570
571 sub exec_unlock($$)
572 {
573 my ($data,$config) = @_;
574 my $virtual = $data->{'virtual'};
575 my $uselist = $data->{'uselist'};
576
577 $uselist->remove_file($virtual);
578 $uselist->save;
579
580 return devedit_reload({command => 'show', file => upper_path($virtual)});
581 }
582
583 # it's true, baby ;-)
584
585 1;
586
587 #
588 ### End ###

patrick-canterino.de