]> git.p6c8.net - devedit.git/blob - modules/Command.pm
- Allow to filter directory listing using DOS-style wildcards (maybe it still
[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 <patrick@patshaping.de>
9 # Last modified: 2004-12-26
10 #
11
12 use strict;
13
14 use vars qw(@EXPORT);
15
16 use File::Access;
17 use File::Copy;
18 use File::Path;
19
20 use POSIX qw(strftime);
21 use Tool;
22
23 use CGI qw(header
24 escape);
25
26 use HTML::Entities;
27 use Output;
28 use Template;
29
30 my $script = encode_entities($ENV{'SCRIPT_NAME'});
31 my $users = eval("getpwuid(0)") && eval("getgrgid(0)");
32
33 my %dispatch = ('show' => \&exec_show,
34 'beginedit' => \&exec_beginedit,
35 'canceledit' => \&exec_canceledit,
36 'endedit' => \&exec_endedit,
37 'mkdir' => \&exec_mkdir,
38 'mkfile' => \&exec_mkfile,
39 'upload' => \&exec_upload,
40 'copy' => \&exec_copy,
41 'rename' => \&exec_rename,
42 'remove' => \&exec_remove,
43 'chprop' => \&exec_chprop,
44 'unlock' => \&exec_unlock,
45 'about' => \&exec_about
46 );
47
48 ### Export ###
49
50 use base qw(Exporter);
51
52 @EXPORT = qw(exec_command);
53
54 # exec_command()
55 #
56 # Execute the specified command
57 #
58 # Params: 1. Command to execute
59 # 2. Reference to user input hash
60 # 3. Reference to config hash
61 #
62 # Return: Output of the command (Scalar Reference)
63
64 sub exec_command($$$)
65 {
66 my ($command,$data,$config) = @_;
67
68 foreach(keys(%dispatch))
69 {
70 if(lc($_) eq lc($command))
71 {
72 my $output = &{$dispatch{$_}}($data,$config);
73 return $output;
74 }
75 }
76
77 return error($config->{'errors'}->{'cmd_unknown'},'/',{COMMAND => encode_entities($command)});
78 }
79
80 # exec_show()
81 #
82 # View a directory or a file
83 #
84 # Params: 1. Reference to user input hash
85 # 2. Reference to config hash
86 #
87 # Return: Output of the command (Scalar Reference)
88
89 sub exec_show($$)
90 {
91 my ($data,$config) = @_;
92 my $physical = $data->{'physical'};
93 my $virtual = $data->{'virtual'};
94 my $upper_path = encode_entities(upper_path($virtual));
95 my $uselist = $data->{'uselist'};
96
97 my $tpl = new Template;
98
99 if(-d $physical)
100 {
101 # Create directory listing
102
103 return error($config->{'errors'}->{'no_dir_access'},$upper_path) unless(-r $physical && -x $physical);
104
105 my $direntries = dir_read($physical);
106 return error($config->{'dir_read_fail'},$upper_path,{DIR => encode_entities($virtual)}) unless($direntries);
107
108 my $files = $direntries->{'files'};
109 my $dirs = $direntries->{'dirs'};
110
111 my $dir_writeable = -w $physical;
112
113 my $dirlist = "";
114
115 my $filter1 = $data->{'cgi'}->param('filter') || '*'; # The real wildcard
116 my $filter2 = ($filter1 && $filter1 ne '*') ? $filter1 : ''; # Wildcard for output
117
118 # Create the link to the upper directory
119 # (only if we are not in the root directory)
120
121 unless($virtual eq "/")
122 {
123 my @stat = stat($physical."/..");
124
125 my $udtpl = new Template;
126 $udtpl->read_file($config->{'templates'}->{'dirlist_up'});
127
128 $udtpl->fillin("UPPER_DIR",$upper_path);
129 $udtpl->fillin("DATE",encode_entities(strftime($config->{'timeformat'},localtime($stat[9]))));
130
131 $dirlist .= $udtpl->get_template;
132 }
133
134 # Directories
135
136 foreach my $dir(@$dirs)
137 {
138 next unless(dos_wildcard_match($filter1,$dir));
139
140 my $phys_path = $physical."/".$dir;
141 my $virt_path = encode_entities($virtual.$dir."/");
142
143 my @stat = stat($phys_path);
144
145 my $dtpl = new Template;
146 $dtpl->read_file($config->{'templates'}->{'dirlist_dir'});
147
148 $dtpl->fillin("DIR",$virt_path);
149 $dtpl->fillin("DIR_NAME",encode_entities($dir));
150 $dtpl->fillin("DATE",encode_entities(strftime($config->{'timeformat'},localtime($stat[9]))));
151 $dtpl->fillin("URL",equal_url(encode_entities($config->{'httproot'}),$virt_path));
152
153 $dtpl->parse_if_block("readable",-r $phys_path && -x $phys_path);
154 $dtpl->parse_if_block("users",$users && -o $phys_path);
155
156 $dirlist .= $dtpl->get_template;
157 }
158
159 # Files
160
161 foreach my $file(@$files)
162 {
163 next unless(dos_wildcard_match($filter1,$file));
164
165 my $phys_path = $physical."/".$file;
166 my $virt_path = encode_entities($virtual.$file);
167
168 my @stat = stat($phys_path);
169 my $in_use = $uselist->in_use($virtual.$file);
170 my $too_large = $config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'};
171
172 my $ftpl = new Template;
173 $ftpl->read_file($config->{'templates'}->{'dirlist_file'});
174
175 $ftpl->fillin("FILE",$virt_path);
176 $ftpl->fillin("FILE_NAME",encode_entities($file));
177 $ftpl->fillin("SIZE",$stat[7]);
178 $ftpl->fillin("DATE",encode_entities(strftime($config->{'timeformat'},localtime($stat[9]))));
179 $ftpl->fillin("URL",equal_url(encode_entities($config->{'httproot'}),$virt_path));
180
181 $ftpl->parse_if_block("not_readable",not -r $phys_path);
182 $ftpl->parse_if_block("binary",-B $phys_path);
183 $ftpl->parse_if_block("readonly",not -w $phys_path);
184
185 $ftpl->parse_if_block("viewable",-r $phys_path && -T $phys_path && not $too_large);
186 $ftpl->parse_if_block("editable",(-r $phys_path && -w $phys_path && -T $phys_path && not $too_large) && not $in_use);
187
188 $ftpl->parse_if_block("in_use",$in_use);
189 $ftpl->parse_if_block("unused",not $in_use);
190
191 $ftpl->parse_if_block("too_large",$config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'});
192
193 $ftpl->parse_if_block("users",$users && -o $phys_path);
194
195 $dirlist .= $ftpl->get_template;
196 }
197
198 $tpl->read_file($config->{'templates'}->{'dirlist'});
199
200 $tpl->fillin("DIRLIST",$dirlist);
201 $tpl->fillin("DIR",encode_entities($virtual));
202 $tpl->fillin("SCRIPT",$script);
203 $tpl->fillin("URL",encode_entities(equal_url($config->{'httproot'},$virtual)));
204
205 $tpl->fillin("FILTER",encode_entities($filter2));
206 $tpl->fillin("FILTER_URL",escape($filter2));
207
208 $tpl->parse_if_block("dir_writeable",$dir_writeable);
209 $tpl->parse_if_block("filter",$filter2);
210 }
211 else
212 {
213 # View a file
214
215 return error($config->{'errors'}->{'no_view'},$upper_path) unless(-r $physical);
216
217 # Check on binary files
218 # We have to do it in this way, or empty files
219 # will be recognized as binary files
220
221 unless(-T $physical)
222 {
223 # Binary file
224
225 return error($config->{'errors'}->{'binary'},$upper_path);
226 }
227 else
228 {
229 # Text file
230
231 if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'})
232 {
233 return error($config->{'errors'}->{'file_too_large'},$upper_path,{SIZE => $config->{'max_file_size'}})
234 }
235 else
236 {
237 my $content = file_read($physical);
238 $$content =~ s/\015\012|\012|\015/\n/g;
239
240 $tpl->read_file($config->{'templates'}->{'viewfile'});
241
242 $tpl->fillin("FILE",encode_entities($virtual));
243 $tpl->fillin("DIR",$upper_path);
244 $tpl->fillin("URL",encode_entities(equal_url($config->{'httproot'},$virtual)));
245 $tpl->fillin("SCRIPT",$script);
246
247 $tpl->parse_if_block("editable",-w $physical && $uselist->unused($virtual));
248
249 $tpl->fillin("CONTENT",encode_entities($$content));
250 }
251 }
252 }
253
254 my $output = header(-type => "text/html");
255 $output .= $tpl->get_template;
256
257 return \$output;
258 }
259
260 # exec_beginedit
261 #
262 # Lock a file and display a form to edit it
263 #
264 # Params: 1. Reference to user input hash
265 # 2. Reference to config hash
266 #
267 # Return: Output of the command (Scalar Reference)
268
269 sub exec_beginedit($$)
270 {
271 my ($data,$config) = @_;
272 my $physical = $data->{'physical'};
273 my $virtual = $data->{'virtual'};
274 my $dir = upper_path($virtual);
275 my $uselist = $data->{'uselist'};
276
277 return error($config->{'errors'}->{'editdir'},$dir) if(-d $physical);
278 return error($config->{'errors'}->{'in_use'}, $dir,{FILE => $virtual}) if($uselist->in_use($virtual));
279 return error($config->{'errors'}->{'no_edit'},$dir) unless(-r $physical && -w $physical);
280
281 # Check on binary files
282
283 unless(-T $physical)
284 {
285 # Binary file
286
287 return error($config->{'errors'}->{'binary'},$dir);
288 }
289 else
290 {
291 if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'})
292 {
293 return error($config->{'errors'}->{'file_too_large'},$dir,{SIZE => $config->{'max_file_size'}})
294 }
295 else
296 {
297 # Text file
298
299 $uselist->add_file($virtual);
300 $uselist->save;
301
302 my $content = file_read($physical);
303 $$content =~ s/\015\012|\012|\015/\n/g;
304
305 my $tpl = new Template;
306 $tpl->read_file($config->{'templates'}->{'editfile'});
307
308 $tpl->fillin("FILE",$virtual);
309 $tpl->fillin("DIR",$dir);
310 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
311 $tpl->fillin("SCRIPT",$script);
312 $tpl->fillin("CONTENT",encode_entities($$content));
313
314 my $output = header(-type => "text/html");
315 $output .= $tpl->get_template;
316
317 return \$output;
318 }
319 }
320 }
321
322 # exec_canceledit()
323 #
324 # Abort file editing
325 #
326 # Params: 1. Reference to user input hash
327 # 2. Reference to config hash
328 #
329 # Return: Output of the command (Scalar Reference)
330
331 sub exec_canceledit($$)
332 {
333 my ($data,$config) = @_;
334 my $virtual = $data->{'virtual'};
335
336 file_unlock($data->{'uselist'},$virtual);
337 return devedit_reload({command => 'show', file => upper_path($virtual)});
338 }
339
340 # exec_endedit()
341 #
342 # Save a file, unlock it and return to directory view
343 #
344 # Params: 1. Reference to user input hash
345 # 2. Reference to config hash
346 #
347 # Return: Output of the command (Scalar Reference)
348
349 sub exec_endedit($$)
350 {
351 my ($data,$config) = @_;
352 my $physical = $data->{'physical'};
353 my $virtual = $data->{'virtual'};
354 my $dir = upper_path($virtual);
355 my $content = $data->{'cgi'}->param('filecontent');
356 my $uselist = $data->{'uselist'};
357
358 # We already unlock the file at the beginning of the subroutine,
359 # because if we have to abort this routine, the file keeps locked.
360 # No other user of Dev-Editor will access the file during this
361 # routine because of the concept of File::UseList.
362
363 file_unlock($uselist,$virtual);
364
365 # Normalize newlines
366
367 $content =~ s/\015\012|\012|\015/\n/g;
368
369 if($data->{'cgi'}->param('encode_iso'))
370 {
371 # Encode all ISO-8859-1 special chars
372
373 $content = encode_entities($content,"\200-\377");
374 }
375
376 if($data->{'cgi'}->param('saveas') && $data->{'new_physical'} ne '' && $data->{'new_virtual'} ne '')
377 {
378 # Create the new filename
379
380 $physical = $data->{'new_physical'};
381 $virtual = $data->{'new_virtual'};
382
383 # Check if someone else is editing the new file
384
385 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($uselist->in_use($virtual));
386 }
387
388 return error($config->{'errors'}->{'editdir'},$dir) if(-d $physical);
389 return error($config->{'errors'}->{'no_edit'},$dir) if(-e $physical && !(-r $physical && -w $physical));
390 return error($config->{'errors'}->{'text_to_binary'},$dir) unless(-T $physical);
391
392 if(file_save($physical,\$content))
393 {
394 # Saving of the file was successful!
395
396 return devedit_reload({command => 'show', file => $dir});
397 }
398 else
399 {
400 return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual});
401 }
402 }
403
404 # exec_mkfile()
405 #
406 # Create a file and return to directory view
407 #
408 # Params: 1. Reference to user input hash
409 # 2. Reference to config hash
410 #
411 # Return: Output of the command (Scalar Reference)
412
413 sub exec_mkfile($$)
414 {
415 my ($data,$config) = @_;
416 my $new_physical = $data->{'new_physical'};
417 my $new_virtual = $data->{'new_virtual'};
418 my $dir = upper_path($new_virtual);
419 $new_virtual = encode_entities($new_virtual);
420
421 if($new_physical)
422 {
423 return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
424
425 file_create($new_physical) or return error($config->{'errors'}->{'mkfile_failed'},$dir,{FILE => $new_virtual});
426 return devedit_reload({command => 'show', file => $dir});
427 }
428 else
429 {
430 my $tpl = new Template;
431 $tpl->read_file($config->{'templates'}->{'mkfile'});
432
433 $tpl->fillin("DIR","/");
434 $tpl->fillin("SCRIPT",$script);
435
436 my $output = header(-type => "text/html");
437 $output .= $tpl->get_template;
438
439 return \$output;
440 }
441 }
442
443 # exec_mkdir()
444 #
445 # Create a directory and return to directory view
446 #
447 # Params: 1. Reference to user input hash
448 # 2. Reference to config hash
449 #
450 # Return: Output of the command (Scalar Reference)
451
452 sub exec_mkdir($$)
453 {
454 my ($data,$config) = @_;
455 my $new_physical = $data->{'new_physical'};
456 my $new_virtual = $data->{'new_virtual'};
457 my $dir = upper_path($new_virtual);
458 $new_virtual = encode_entities($new_virtual);
459
460 return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
461
462 if($new_physical)
463 {
464 mkdir($new_physical,0777) or return error($config->{'errors'}->{'mkdir_failed'},$dir,{DIR => $new_virtual});
465 return devedit_reload({command => 'show', file => $dir});
466 }
467 else
468 {
469 my $tpl = new Template;
470 $tpl->read_file($config->{'templates'}->{'mkdir'});
471
472 $tpl->fillin("DIR","/");
473 $tpl->fillin("SCRIPT",$script);
474
475 my $output = header(-type => "text/html");
476 $output .= $tpl->get_template;
477
478 return \$output;
479 }
480 }
481
482 # exec_upload()
483 #
484 # Upload a file
485 #
486 # Params: 1. Reference to user input hash
487 # 2. Reference to config hash
488 #
489 # Return: Output of the command (Scalar Reference)
490
491 sub exec_upload($$)
492 {
493 my ($data,$config) = @_;
494 my $physical = $data->{'physical'};
495 my $virtual = $data->{'virtual'};
496 my $cgi = $data->{'cgi'};
497
498 return error($config->{'errors'}->{'no_directory'},upper_path($virtual),{FILE => $virtual}) unless(-d $physical);
499 return error($config->{'errors'}->{'dir_no_create'},$virtual,{DIR => $virtual}) unless(-w $physical);
500
501 if(my $uploaded_file = $cgi->param('uploaded_file'))
502 {
503 # Process file upload
504
505 my $filename = file_name($uploaded_file);
506 my $file_phys = $physical."/".$filename;
507 my $file_virt = $virtual.$filename;
508
509 return error($config->{'errors'}->{'in_use'},$virtual,{FILE => $file_virt}) if($data->{'uselist'}->in_use($file_virt));
510
511 if(-e $file_phys)
512 {
513 return error($config->{'errors'}->{'dir_replace'},$virtual) if(-d $file_phys);
514 return error($config->{'errors'}->{'exist_no_write'},$virtual,{FILE => $file_virt}) unless(-w $file_phys);
515 return error($config->{'errors'}->{'file_exists'},$virtual,{FILE => $file_virt}) unless($cgi->param('overwrite'));
516 }
517
518 my $ascii = $cgi->param('ascii');
519 my $handle = $cgi->upload('uploaded_file');
520
521 # Read transferred file and write it to disk
522
523 read($handle, my $data, -s $handle);
524 $data =~ s/\015\012|\012|\015/\n/g if($ascii); # Replace line separators if transferring in ASCII mode
525 file_save($file_phys,\$data,not $ascii) or return error($config->{'errors'}->{'mkfile_failed'},$virtual,{FILE => $file_virt});
526
527 return devedit_reload({command => "show", file => $virtual});
528 }
529 else
530 {
531 my $tpl = new Template;
532 $tpl->read_file($config->{'templates'}->{'upload'});
533
534 $tpl->fillin("DIR",$virtual);
535 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
536 $tpl->fillin("SCRIPT",$script);
537
538 my $output = header(-type => "text/html");
539 $output .= $tpl->get_template;
540
541 return \$output;
542 }
543 }
544
545 # exec_copy()
546 #
547 # Copy a file and return to directory view
548 #
549 # Params: 1. Reference to user input hash
550 # 2. Reference to config hash
551 #
552 # Return: Output of the command (Scalar Reference)
553
554 sub exec_copy($$)
555 {
556 my ($data,$config) = @_;
557 my $physical = $data->{'physical'};
558 my $virtual = encode_entities($data->{'virtual'});
559 my $dir = upper_path($virtual);
560 my $new_physical = $data->{'new_physical'};
561
562 return error($config->{'errors'}->{'dircopy'},$dir) if(-d $physical);
563 return error($config->{'errors'}->{'no_copy'},$dir) unless(-r $physical);
564
565 if($new_physical)
566 {
567 my $new_virtual = $data->{'new_virtual'};
568 my $new_dir = upper_path($new_virtual);
569 $new_virtual = encode_entities($new_virtual);
570
571 if(-e $new_physical)
572 {
573 return error($config->{'errors'}->{'exist_edited'},$new_dir,{FILE => $new_virtual}) if($data->{'uselist'}->in_use($data->{'new_virtual'}));
574 return error($config->{'errors'}->{'dir_replace'},$new_dir) if(-d $new_physical);
575 return error($config->{'errors'}->{'exist_no_write'},$new_dir,{FILE => $new_virtual}) unless(-w $new_physical);
576
577 if(not $data->{'cgi'}->param('confirmed'))
578 {
579 my $tpl = new Template;
580 $tpl->read_file($config->{'templates'}->{'confirm_replace'});
581
582 $tpl->fillin("FILE",$virtual);
583 $tpl->fillin("NEW_FILE",$new_virtual);
584 $tpl->fillin("NEW_FILENAME",file_name($new_virtual));
585 $tpl->fillin("NEW_DIR",$new_dir);
586 $tpl->fillin("DIR",$dir);
587
588 $tpl->fillin("COMMAND","copy");
589 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
590 $tpl->fillin("SCRIPT",$script);
591
592 my $output = header(-type => "text/html");
593 $output .= $tpl->get_template;
594
595 return \$output;
596 }
597 }
598
599 copy($physical,$new_physical) or return error($config->{'errors'}->{'copy_failed'},$dir,{FILE => $virtual, NEW_FILE => $new_virtual});
600 return devedit_reload({command => 'show', file => $new_dir});
601 }
602 else
603 {
604 my $tpl = new Template;
605 $tpl->read_file($config->{'templates'}->{'copyfile'});
606
607 $tpl->fillin("FILE",$virtual);
608 $tpl->fillin("DIR",$dir);
609 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
610 $tpl->fillin("SCRIPT",$script);
611
612 my $output = header(-type => "text/html");
613 $output .= $tpl->get_template;
614
615 return \$output;
616 }
617 }
618
619 # exec_rename()
620 #
621 # Rename/move a file and return to directory view
622 #
623 # Params: 1. Reference to user input hash
624 # 2. Reference to config hash
625 #
626 # Return: Output of the command (Scalar Reference)
627
628 sub exec_rename($$)
629 {
630 my ($data,$config) = @_;
631 my $physical = $data->{'physical'};
632 my $virtual = $data->{'virtual'};
633 my $dir = upper_path($virtual);
634 my $new_physical = $data->{'new_physical'};
635
636 return error($config->{'errors'}->{'rename_root'},"/") if($virtual eq "/");
637 return error($config->{'errors'}->{'no_rename'},$dir) unless(-w upper_path($physical));
638 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
639
640 if($new_physical)
641 {
642 my $new_virtual = $data->{'new_virtual'};
643 my $new_dir = upper_path($new_virtual);
644 $new_virtual = encode_entities($new_virtual);
645
646 if(-e $new_physical)
647 {
648 return error($config->{'errors'}->{'exist_edited'},$new_dir,{FILE => $new_virtual}) if($data->{'uselist'}->in_use($data->{'new_virtual'}));
649 return error($config->{'errors'}->{'dir_replace'},$new_dir) if(-d $new_physical);
650 return error($config->{'errors'}->{'exist_no_write'},$new_dir,{FILE => $new_virtual}) unless(-w $new_physical);
651
652 if(not $data->{'cgi'}->param('confirmed'))
653 {
654 my $tpl = new Template;
655 $tpl->read_file($config->{'templates'}->{'confirm_replace'});
656
657 $tpl->fillin("FILE",$virtual);
658 $tpl->fillin("NEW_FILE",$new_virtual);
659 $tpl->fillin("NEW_FILENAME",file_name($new_virtual));
660 $tpl->fillin("NEW_DIR",$new_dir);
661 $tpl->fillin("DIR",$dir);
662
663 $tpl->fillin("COMMAND","rename");
664 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
665 $tpl->fillin("SCRIPT",$script);
666
667 my $output = header(-type => "text/html");
668 $output .= $tpl->get_template;
669
670 return \$output;
671 }
672 }
673
674 rename($physical,$new_physical) or return error($config->{'errors'}->{'rename_failed'},$dir,{FILE => $virtual, NEW_FILE => $new_virtual});
675 return devedit_reload({command => 'show', file => $new_dir});
676 }
677 else
678 {
679 my $tpl = new Template;
680 $tpl->read_file($config->{'templates'}->{'renamefile'});
681
682 $tpl->fillin("FILE",$virtual);
683 $tpl->fillin("DIR",$dir);
684 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
685 $tpl->fillin("SCRIPT",$script);
686
687 my $output = header(-type => "text/html");
688 $output .= $tpl->get_template;
689
690 return \$output;
691 }
692 }
693
694 # exec_remove()
695 #
696 # Remove a file or a directory and return to directory view
697 #
698 # Params: 1. Reference to user input hash
699 # 2. Reference to config hash
700 #
701 # Return: Output of the command (Scalar Reference)
702
703 sub exec_remove($$)
704 {
705 my ($data,$config) = @_;
706 my $physical = $data->{'physical'};
707 my $virtual = $data->{'virtual'};
708 my $dir = upper_path($virtual);
709
710 return error($config->{'errors'}->{'remove_root'},"/") if($virtual eq "/");
711 return error($config->{'errors'}->{'no_delete'},$dir) unless(-w upper_path($physical));
712
713 if(-d $physical)
714 {
715 # Remove a directory
716
717 if($data->{'cgi'}->param('confirmed'))
718 {
719 rmtree($physical);
720 return devedit_reload({command => 'show', file => $dir});
721 }
722 else
723 {
724 my $tpl = new Template;
725 $tpl->read_file($config->{'templates'}->{'confirm_rmdir'});
726
727 $tpl->fillin("DIR",$virtual);
728 $tpl->fillin("UPPER_DIR",$dir);
729 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
730 $tpl->fillin("SCRIPT",$script);
731
732 my $output = header(-type => "text/html");
733 $output .= $tpl->get_template;
734
735 return \$output;
736 }
737 }
738 else
739 {
740 # Remove a file
741
742 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
743
744 if($data->{'cgi'}->param('confirmed'))
745 {
746 unlink($physical) or return error($config->{'errors'}->{'delete_failed'},$dir,{FILE => $virtual});
747 return devedit_reload({command => 'show', file => $dir});
748 }
749 else
750 {
751 my $tpl = new Template;
752 $tpl->read_file($config->{'templates'}->{'confirm_rmfile'});
753
754 $tpl->fillin("FILE",$virtual);
755 $tpl->fillin("DIR",$dir);
756 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
757 $tpl->fillin("SCRIPT",$script);
758
759 my $output = header(-type => "text/html");
760 $output .= $tpl->get_template;
761
762 return \$output;
763 }
764 }
765 }
766
767 # exec_chprop()
768 #
769 # Change the mode and the group of a file or a directory
770 #
771 # Params: 1. Reference to user input hash
772 # 2. Reference to config hash
773 #
774 # Return: Output of the command (Scalar Reference)
775
776 sub exec_chprop($$)
777 {
778 my ($data,$config) = @_;
779 my $physical = $data->{'physical'};
780 my $virtual = $data->{'virtual'};
781 my $dir = upper_path($virtual);
782
783 return error($config->{'errors'}->{'no_users'},$dir,{FILE => $virtual}) unless($users);
784 return error($config->{'errors'}->{'chprop_root'},"/") if($virtual eq "/");
785 return error($config->{'errors'}->{'not_owner'},$dir,{FILE => $virtual}) unless(-o $physical);
786 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
787
788 my $cgi = $data->{'cgi'};
789 my $mode = $cgi->param('mode');
790 my $group = $cgi->param('group');
791
792 if($mode || $group)
793 {
794 if($mode)
795 {
796 # Change the mode
797
798 chmod(oct($mode),$physical);
799 }
800
801 if($group)
802 {
803 # Change the group using the `chgrp` system command
804
805 return error($config->{'errors'}->{'invalid_group'},$dir,{GROUP => encode_entities($group)}) unless($group =~ /^[a-z0-9_]+[a-z0-9_-]*$/i);
806 system("chgrp",$group,$physical);
807 }
808
809 return devedit_reload({command => 'show', file => $dir});
810 }
811 else
812 {
813 # Display the form
814
815 my @stat = stat($physical);
816 my $mode = $stat[2];
817 my $gid = $stat[5];
818
819 my $tpl = new Template;
820 $tpl->read_file($config->{'templates'}->{'chprop'});
821
822 # Insert file properties into the template
823
824 $tpl->fillin("MODE_OCTAL",substr(sprintf("%04o",$mode),-4));
825 $tpl->fillin("MODE_STRING",mode_string($mode));
826 $tpl->fillin("GID",$gid);
827
828 if(my $group = getgrgid($gid))
829 {
830 $tpl->fillin("GROUP",encode_entities($group));
831 $tpl->parse_if_block("group_detected",1);
832 }
833 else
834 {
835 $tpl->parse_if_block("group_detected",0);
836 }
837
838 # Insert other information
839
840 $tpl->fillin("FILE",$virtual);
841 $tpl->fillin("DIR",$dir);
842 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
843 $tpl->fillin("SCRIPT",$script);
844
845 my $output = header(-type => "text/html");
846 $output .= $tpl->get_template;
847
848 return \$output;
849 }
850 }
851
852 # exec_unlock()
853 #
854 # Remove a file from the list of used files and
855 # return to directory view
856 #
857 # Params: 1. Reference to user input hash
858 # 2. Reference to config hash
859 #
860 # Return: Output of the command (Scalar Reference)
861
862 sub exec_unlock($$)
863 {
864 my ($data,$config) = @_;
865 my $virtual = $data->{'virtual'};
866 my $uselist = $data->{'uselist'};
867 my $dir = upper_path($virtual);
868
869 return devedit_reload({command => 'show', file => $dir}) if($uselist->unused($virtual));
870
871 if($data->{'cgi'}->param('confirmed'))
872 {
873 file_unlock($uselist,$virtual);
874 return devedit_reload({command => 'show', file => $dir});
875 }
876 else
877 {
878 my $tpl = new Template;
879 $tpl->read_file($config->{'templates'}->{'confirm_unlock'});
880
881 $tpl->fillin("FILE",$virtual);
882 $tpl->fillin("DIR",$dir);
883 $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
884 $tpl->fillin("SCRIPT",$script);
885
886 my $output = header(-type => "text/html");
887 $output .= $tpl->get_template;
888
889 return \$output;
890 }
891 }
892
893 # exec_about()
894 #
895 # Display some information about Dev-Editor
896 #
897 # Params: 1. Reference to user input hash
898 # 2. Reference to config hash
899 #
900 # Return: Output of the command (Scalar Reference)
901
902 sub exec_about($$)
903 {
904 my ($data,$config) = @_;
905
906 my $tpl = new Template;
907 $tpl->read_file($config->{'templates'}->{'about'});
908
909 $tpl->fillin("SCRIPT",$script);
910
911 # Dev-Editor's version number
912
913 $tpl->fillin("VERSION",$data->{'version'});
914
915 # Some path information
916
917 $tpl->fillin("SCRIPT_PHYS",encode_entities($ENV{'SCRIPT_FILENAME'}));
918 $tpl->fillin("CONFIG_PATH",encode_entities($data->{'configfile'}));
919 $tpl->fillin("FILE_ROOT", encode_entities($config->{'fileroot'}));
920 $tpl->fillin("HTTP_ROOT", encode_entities($config->{'httproot'}));
921
922 # Perl
923
924 $tpl->fillin("PERL_PROG",encode_entities($^X));
925 $tpl->fillin("PERL_VER", sprintf("%vd",$^V));
926
927 # Information about the server
928
929 $tpl->fillin("HTTPD",encode_entities($ENV{'SERVER_SOFTWARE'}));
930 $tpl->fillin("OS", encode_entities($^O));
931 $tpl->fillin("TIME", encode_entities(strftime($config->{'timeformat'},localtime)));
932
933 # Process information
934
935 $tpl->fillin("PID",$$);
936
937 # Check if the functions getpwuid() and getgrgid() are available
938
939 if($users)
940 {
941 # Dev-Editor is running on a system which allows users and groups
942 # So we display the user and the group of our process
943
944 my $uid = POSIX::getuid;
945 my $gid = POSIX::getgid;
946
947 $tpl->parse_if_block("users",1);
948
949 # ID's of user and group
950
951 $tpl->fillin("UID",$uid);
952 $tpl->fillin("GID",$gid);
953
954 # Names of user and group
955
956 if(my $user = getpwuid($uid))
957 {
958 $tpl->fillin("USER",encode_entities($user));
959 $tpl->parse_if_block("user_detected",1);
960 }
961 else
962 {
963 $tpl->parse_if_block("user_detected",0);
964 }
965
966 if(my $group = getgrgid($gid))
967 {
968 $tpl->fillin("GROUP",encode_entities($group));
969 $tpl->parse_if_block("group_detected",1);
970 }
971 else
972 {
973 $tpl->parse_if_block("group_detected",0);
974 }
975
976 # Process umask
977
978 $tpl->fillin("UMASK",sprintf("%04o",umask));
979 }
980 else
981 {
982 $tpl->parse_if_block("users",0);
983 }
984
985 my $output = header(-type => "text/html");
986 $output .= $tpl->get_template;
987
988 return \$output;
989 }
990
991 # it's true, baby ;-)
992
993 1;
994
995 #
996 ### End ###

patrick-canterino.de