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

patrick-canterino.de