]> git.p6c8.net - devedit.git/blob - modules/Command.pm
- For security reasons, I completely changed the handling of symbolic links:
[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-02-12
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 && not -l $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 the current directory is not 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'},($config->{'use_gmt'}) ? gmtime($stat[9]) : 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'},($config->{'use_gmt'}) ? gmtime($stat[9]) : 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 = lstat($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'},($config->{'use_gmt'}) ? gmtime($stat[9]) : localtime($stat[9]))));
179 $ftpl->fillin('URL',equal_url(encode_entities($config->{'httproot'}),$virt_path));
180
181 $ftpl->parse_if_block('link',-l $phys_path);
182 $ftpl->parse_if_block('no_link',not -l $phys_path);
183 $ftpl->parse_if_block('not_readable',not -r $phys_path);
184 $ftpl->parse_if_block('binary',-B $phys_path);
185 $ftpl->parse_if_block('readonly',not -w $phys_path);
186
187 $ftpl->parse_if_block('viewable',(-r $phys_path && -T $phys_path && not $too_large) || -l $phys_path);
188 $ftpl->parse_if_block('editable',((-r $phys_path && -w $phys_path && -T $phys_path && not $too_large) && not $in_use) && not -l $phys_path);
189
190 $ftpl->parse_if_block('in_use',$in_use);
191 $ftpl->parse_if_block('unused',not $in_use);
192
193 $ftpl->parse_if_block('too_large',$config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'});
194
195 $ftpl->parse_if_block('users',$users && -o $phys_path);
196
197 $dirlist .= $ftpl->get_template;
198 }
199
200 $tpl->read_file($config->{'templates'}->{'dirlist'});
201
202 $tpl->fillin('DIRLIST',$dirlist);
203 $tpl->fillin('DIR',encode_entities($virtual));
204 $tpl->fillin('SCRIPT',$script);
205 $tpl->fillin('URL',encode_entities(equal_url($config->{'httproot'},$virtual)));
206
207 $tpl->fillin('FILTER',encode_entities($filter2));
208 $tpl->fillin('FILTER_URL',escape($filter2));
209
210 $tpl->parse_if_block('dir_writeable',$dir_writeable);
211 $tpl->parse_if_block('filter',$filter2);
212 $tpl->parse_if_block('gmt',$config->{'use_gmt'});
213 }
214 elsif(-l $physical)
215 {
216 # Show the target of a symbolic link
217
218 my $link_target = readlink($physical);
219
220 $tpl->read_file($config->{'templates'}->{'viewlink'});
221
222 $tpl->fillin('FILE',encode_entities($virtual));
223 $tpl->fillin('DIR',$upper_path);
224 $tpl->fillin('URL',encode_entities(equal_url($config->{'httproot'},$virtual)));
225 $tpl->fillin('SCRIPT',$script);
226
227 $tpl->fillin('LINK_TARGET',encode_entities($link_target));
228 }
229 else
230 {
231 # View a file
232
233 return error($config->{'errors'}->{'no_view'},$upper_path) unless(-r $physical);
234
235 # Check on binary files
236 # We have to do it in this way or empty files will be recognized
237 # as binary files
238
239 return error($config->{'errors'}->{'binary'},$upper_path) unless(-T $physical);
240
241 # Is the file too large?
242
243 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'});
244
245 # View the file
246
247 my $content = file_read($physical);
248 $$content =~ s/\015\012|\012|\015/\n/g;
249
250 $tpl->read_file($config->{'templates'}->{'viewfile'});
251
252 $tpl->fillin('FILE',encode_entities($virtual));
253 $tpl->fillin('DIR',$upper_path);
254 $tpl->fillin('URL',encode_entities(equal_url($config->{'httproot'},$virtual)));
255 $tpl->fillin('SCRIPT',$script);
256
257 $tpl->parse_if_block('editable',-w $physical && $uselist->unused($virtual));
258
259 $tpl->fillin('CONTENT',encode_entities($$content));
260 }
261
262 my $output = header(-type => 'text/html');
263 $output .= $tpl->get_template;
264
265 return \$output;
266 }
267
268 # exec_beginedit
269 #
270 # Lock a file and display a form to edit it
271 #
272 # Params: 1. Reference to user input hash
273 # 2. Reference to config hash
274 #
275 # Return: Output of the command (Scalar Reference)
276
277 sub exec_beginedit($$)
278 {
279 my ($data,$config) = @_;
280 my $physical = $data->{'physical'};
281 my $virtual = $data->{'virtual'};
282 my $dir = upper_path($virtual);
283 my $uselist = $data->{'uselist'};
284
285 return error($config->{'errors'}->{'link_edit'},$dir) if(-l $physical);
286 return error($config->{'errors'}->{'dir_edit'}, $dir) if(-d $physical);
287 return error($config->{'errors'}->{'in_use'}, $dir,{FILE => $virtual}) if($uselist->in_use($virtual));
288 return error($config->{'errors'}->{'no_edit'}, $dir) unless(-r $physical && -w $physical);
289
290 # Check on binary files
291
292 return error($config->{'errors'}->{'binary'},$dir) unless(-T $physical);
293
294 # Is the file too large?
295
296 return error($config->{'errors'}->{'file_too_large'},$dir,{SIZE => $config->{'max_file_size'}}) if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'});
297
298 # Lock the file...
299
300 ($uselist->add_file($virtual) and
301 $uselist->save) or return error($config->{'errors'}->{'ul_add_failed'},$dir,{FILE => $virtual});
302
303 # ... and show the editing form
304
305 my $content = file_read($physical);
306 $$content =~ s/\015\012|\012|\015/\n/g;
307
308 my $tpl = new Template;
309 $tpl->read_file($config->{'templates'}->{'editfile'});
310
311 $tpl->fillin('FILE',$virtual);
312 $tpl->fillin('DIR',$dir);
313 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
314 $tpl->fillin('SCRIPT',$script);
315 $tpl->fillin('CONTENT',encode_entities($$content));
316
317 my $output = header(-type => 'text/html');
318 $output .= $tpl->get_template;
319
320 return \$output;
321 }
322
323 # exec_canceledit()
324 #
325 # Abort file editing
326 #
327 # Params: 1. Reference to user input hash
328 # 2. Reference to config hash
329 #
330 # Return: Output of the command (Scalar Reference)
331
332 sub exec_canceledit($$)
333 {
334 my ($data,$config) = @_;
335 my $virtual = $data->{'virtual'};
336 my $dir = upper_path($virtual);
337 my $uselist = $data->{'uselist'};
338
339 file_unlock($uselist,$virtual) or return error($config->{'errors'}->{'ul_rm_failed'},$dir,{FILE => $virtual, USELIST => $uselist->{'listfile'}});
340 return devedit_reload({command => 'show', file => $dir});
341 }
342
343 # exec_endedit()
344 #
345 # Save a file, unlock it and return to directory view
346 #
347 # Params: 1. Reference to user input hash
348 # 2. Reference to config hash
349 #
350 # Return: Output of the command (Scalar Reference)
351
352 sub exec_endedit($$)
353 {
354 my ($data,$config) = @_;
355 my $physical = $data->{'physical'};
356 my $virtual = $data->{'virtual'};
357 my $dir = upper_path($virtual);
358 my $content = $data->{'cgi'}->param('filecontent');
359 my $uselist = $data->{'uselist'};
360
361 # We already unlock the file at the beginning of the subroutine,
362 # because if we have to abort this routine, the file keeps locked.
363 # No other user of Dev-Editor will access the file during this
364 # routine because of the concept of File::UseList.
365
366 file_unlock($uselist,$virtual) or return error($config->{'errors'}->{'ul_rm_failed'},$dir,{FILE => $virtual, USELIST => $uselist->{'listfile'}});
367
368 # Normalize newlines
369
370 $content =~ s/\015\012|\012|\015/\n/g;
371
372 if($data->{'cgi'}->param('encode_iso'))
373 {
374 # Encode all ISO-8859-1 special chars
375
376 $content = encode_entities($content,"\200-\377");
377 }
378
379 if($data->{'cgi'}->param('saveas') && $data->{'new_physical'} ne '' && $data->{'new_virtual'} ne '')
380 {
381 # Create the new filename
382
383 $physical = $data->{'new_physical'};
384 $virtual = $data->{'new_virtual'};
385
386 # Check if someone else is editing the new file
387
388 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($uselist->in_use($virtual));
389 }
390
391 return error($config->{'errors'}->{'link_edit'},$dir) if(-l $physical);
392 return error($config->{'errors'}->{'dir_edit'},$dir) if(-d $physical);
393 return error($config->{'errors'}->{'no_edit'},$dir) if(-e $physical && !(-r $physical && -w $physical));
394 return error($config->{'errors'}->{'text_to_binary'},$dir) unless(-T $physical);
395
396 if(file_save($physical,\$content))
397 {
398 # The file was successfully saved!
399
400 return devedit_reload({command => 'show', file => $dir});
401 }
402 else
403 {
404 return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual});
405 }
406 }
407
408 # exec_mkfile()
409 #
410 # Create a file and return to directory view
411 #
412 # Params: 1. Reference to user input hash
413 # 2. Reference to config hash
414 #
415 # Return: Output of the command (Scalar Reference)
416
417 sub exec_mkfile($$)
418 {
419 my ($data,$config) = @_;
420 my $new_physical = $data->{'new_physical'};
421 my $new_virtual = $data->{'new_virtual'};
422 my $dir = upper_path($new_virtual);
423 $new_virtual = encode_entities($new_virtual);
424
425 if($new_physical)
426 {
427 return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
428
429 file_create($new_physical) or return error($config->{'errors'}->{'mkfile_failed'},$dir,{FILE => $new_virtual});
430 return devedit_reload({command => 'show', file => $dir});
431 }
432 else
433 {
434 my $tpl = new Template;
435 $tpl->read_file($config->{'templates'}->{'mkfile'});
436
437 $tpl->fillin('DIR','/');
438 $tpl->fillin('SCRIPT',$script);
439
440 my $output = header(-type => 'text/html');
441 $output .= $tpl->get_template;
442
443 return \$output;
444 }
445 }
446
447 # exec_mkdir()
448 #
449 # Create a directory and return to directory view
450 #
451 # Params: 1. Reference to user input hash
452 # 2. Reference to config hash
453 #
454 # Return: Output of the command (Scalar Reference)
455
456 sub exec_mkdir($$)
457 {
458 my ($data,$config) = @_;
459 my $new_physical = $data->{'new_physical'};
460 my $new_virtual = $data->{'new_virtual'};
461 my $dir = upper_path($new_virtual);
462 $new_virtual = encode_entities($new_virtual);
463
464 if($new_physical)
465 {
466 return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
467
468 mkdir($new_physical,0777) or return error($config->{'errors'}->{'mkdir_failed'},$dir,{DIR => $new_virtual});
469 return devedit_reload({command => 'show', file => $dir});
470 }
471 else
472 {
473 my $tpl = new Template;
474 $tpl->read_file($config->{'templates'}->{'mkdir'});
475
476 $tpl->fillin('DIR','/');
477 $tpl->fillin('SCRIPT',$script);
478
479 my $output = header(-type => 'text/html');
480 $output .= $tpl->get_template;
481
482 return \$output;
483 }
484 }
485
486 # exec_upload()
487 #
488 # Process a file upload
489 #
490 # Params: 1. Reference to user input hash
491 # 2. Reference to config hash
492 #
493 # Return: Output of the command (Scalar Reference)
494
495 sub exec_upload($$)
496 {
497 my ($data,$config) = @_;
498 my $physical = $data->{'physical'};
499 my $virtual = $data->{'virtual'};
500 my $cgi = $data->{'cgi'};
501
502 return error($config->{'errors'}->{'no_directory'},upper_path($virtual),{FILE => $virtual}) unless(-d $physical && not -l $physical);
503 return error($config->{'errors'}->{'dir_no_create'},$virtual,{DIR => $virtual}) unless(-w $physical);
504
505 if(my $uploaded_file = $cgi->param('uploaded_file'))
506 {
507 # Process file upload
508
509 my $filename = file_name($uploaded_file);
510 my $file_phys = $physical.'/'.$filename;
511 my $file_virt = $virtual.$filename;
512
513 return error($config->{'errors'}->{'in_use'},$virtual,{FILE => $file_virt}) if($data->{'uselist'}->in_use($file_virt));
514
515 if(-e $file_phys)
516 {
517 return error($config->{'errors'}->{'link_replace'},$virtual) if(-l $file_phys);
518 return error($config->{'errors'}->{'dir_replace'},$virtual) if(-d $file_phys);
519 return error($config->{'errors'}->{'exist_no_write'},$virtual,{FILE => $file_virt}) unless(-w $file_phys);
520 return error($config->{'errors'}->{'file_exists'},$virtual,{FILE => $file_virt}) unless($cgi->param('overwrite'));
521 }
522
523 my $ascii = $cgi->param('ascii');
524 my $handle = $cgi->upload('uploaded_file');
525
526 return error($config->{'errors'}->{'invalid_upload'},$virtual) unless($handle);
527
528 # Read transferred file and write it to disk
529
530 read($handle, my $data, -s $handle);
531 $data =~ s/\015\012|\012|\015/\n/g if($ascii); # Replace line separators if transferring in ASCII mode
532 file_save($file_phys,\$data,not $ascii) or return error($config->{'errors'}->{'mkfile_failed'},$virtual,{FILE => $file_virt});
533
534 return devedit_reload({command => 'show', file => $virtual});
535 }
536 else
537 {
538 my $tpl = new Template;
539 $tpl->read_file($config->{'templates'}->{'upload'});
540
541 $tpl->fillin('DIR',$virtual);
542 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
543 $tpl->fillin('SCRIPT',$script);
544
545 my $output = header(-type => 'text/html');
546 $output .= $tpl->get_template;
547
548 return \$output;
549 }
550 }
551
552 # exec_copy()
553 #
554 # Copy a file and return to directory view
555 #
556 # Params: 1. Reference to user input hash
557 # 2. Reference to config hash
558 #
559 # Return: Output of the command (Scalar Reference)
560
561 sub exec_copy($$)
562 {
563 my ($data,$config) = @_;
564 my $physical = $data->{'physical'};
565 my $virtual = encode_entities($data->{'virtual'});
566 my $dir = upper_path($virtual);
567 my $new_physical = $data->{'new_physical'};
568
569 return error($config->{'errors'}->{'link_copy'},$dir) if(-l $physical);
570 return error($config->{'errors'}->{'dir_copy'},$dir) if(-d $physical);
571 return error($config->{'errors'}->{'no_copy'},$dir) unless(-r $physical);
572
573 if($new_physical)
574 {
575 my $new_virtual = $data->{'new_virtual'};
576 my $new_dir = upper_path($new_virtual);
577 $new_virtual = encode_entities($new_virtual);
578
579 if(-e $new_physical)
580 {
581 return error($config->{'errors'}->{'exist_edited'},$new_dir,{FILE => $new_virtual}) if($data->{'uselist'}->in_use($data->{'new_virtual'}));
582 return error($config->{'errors'}->{'link_replace'},$new_dir) if(-l $new_physical);
583 return error($config->{'errors'}->{'dir_replace'},$new_dir) if(-d $new_physical);
584 return error($config->{'errors'}->{'exist_no_write'},$new_dir,{FILE => $new_virtual}) unless(-w $new_physical);
585
586 if(not $data->{'cgi'}->param('confirmed'))
587 {
588 my $tpl = new Template;
589 $tpl->read_file($config->{'templates'}->{'confirm_replace'});
590
591 $tpl->fillin('FILE',$virtual);
592 $tpl->fillin('NEW_FILE',$new_virtual);
593 $tpl->fillin('NEW_FILENAME',file_name($new_virtual));
594 $tpl->fillin('NEW_DIR',$new_dir);
595 $tpl->fillin('DIR',$dir);
596
597 $tpl->fillin('COMMAND','copy');
598 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
599 $tpl->fillin('SCRIPT',$script);
600
601 my $output = header(-type => 'text/html');
602 $output .= $tpl->get_template;
603
604 return \$output;
605 }
606 }
607
608 copy($physical,$new_physical) or return error($config->{'errors'}->{'copy_failed'},$dir,{FILE => $virtual, NEW_FILE => $new_virtual});
609 return devedit_reload({command => 'show', file => $new_dir});
610 }
611 else
612 {
613 my $tpl = new Template;
614 $tpl->read_file($config->{'templates'}->{'copyfile'});
615
616 $tpl->fillin('FILE',$virtual);
617 $tpl->fillin('DIR',$dir);
618 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
619 $tpl->fillin('SCRIPT',$script);
620
621 my $output = header(-type => 'text/html');
622 $output .= $tpl->get_template;
623
624 return \$output;
625 }
626 }
627
628 # exec_rename()
629 #
630 # Rename/move a file and return to directory view
631 #
632 # Params: 1. Reference to user input hash
633 # 2. Reference to config hash
634 #
635 # Return: Output of the command (Scalar Reference)
636
637 sub exec_rename($$)
638 {
639 my ($data,$config) = @_;
640 my $physical = $data->{'physical'};
641 my $virtual = $data->{'virtual'};
642 my $dir = upper_path($virtual);
643 my $new_physical = $data->{'new_physical'};
644
645 return error($config->{'errors'}->{'rename_root'},'/') if($virtual eq '/');
646 return error($config->{'errors'}->{'no_rename'},$dir) unless(-w upper_path($physical));
647 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
648
649 if($new_physical)
650 {
651 my $new_virtual = $data->{'new_virtual'};
652 my $new_dir = upper_path($new_virtual);
653 $new_virtual = encode_entities($new_virtual);
654
655 if(-e $new_physical)
656 {
657 return error($config->{'errors'}->{'exist_edited'},$new_dir,{FILE => $new_virtual}) if($data->{'uselist'}->in_use($data->{'new_virtual'}));
658 return error($config->{'errors'}->{'dir_replace'},$new_dir) if(-d $new_physical && not -l $new_physical);
659 return error($config->{'errors'}->{'exist_no_write'},$new_dir,{FILE => $new_virtual}) unless(-w $new_physical);
660
661 if(not $data->{'cgi'}->param('confirmed'))
662 {
663 my $tpl = new Template;
664 $tpl->read_file($config->{'templates'}->{'confirm_replace'});
665
666 $tpl->fillin('FILE',$virtual);
667 $tpl->fillin('NEW_FILE',$new_virtual);
668 $tpl->fillin('NEW_FILENAME',file_name($new_virtual));
669 $tpl->fillin('NEW_DIR',$new_dir);
670 $tpl->fillin('DIR',$dir);
671
672 $tpl->fillin('COMMAND','rename');
673 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
674 $tpl->fillin('SCRIPT',$script);
675
676 my $output = header(-type => 'text/html');
677 $output .= $tpl->get_template;
678
679 return \$output;
680 }
681 }
682
683 rename($physical,$new_physical) or return error($config->{'errors'}->{'rename_failed'},$dir,{FILE => $virtual, NEW_FILE => $new_virtual});
684 return devedit_reload({command => 'show', file => $new_dir});
685 }
686 else
687 {
688 my $tpl = new Template;
689 $tpl->read_file($config->{'templates'}->{'renamefile'});
690
691 $tpl->fillin('FILE',$virtual);
692 $tpl->fillin('DIR',$dir);
693 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
694 $tpl->fillin('SCRIPT',$script);
695
696 my $output = header(-type => 'text/html');
697 $output .= $tpl->get_template;
698
699 return \$output;
700 }
701 }
702
703 # exec_remove()
704 #
705 # Remove a file or a directory and return to directory view
706 #
707 # Params: 1. Reference to user input hash
708 # 2. Reference to config hash
709 #
710 # Return: Output of the command (Scalar Reference)
711
712 sub exec_remove($$)
713 {
714 my ($data,$config) = @_;
715 my $physical = $data->{'physical'};
716 my $virtual = $data->{'virtual'};
717 my $dir = upper_path($virtual);
718
719 return error($config->{'errors'}->{'remove_root'},'/') if($virtual eq '/');
720 return error($config->{'errors'}->{'no_delete'},$dir) unless(-w upper_path($physical));
721
722 if(-d $physical && not -l $physical)
723 {
724 # Remove a directory
725
726 if($data->{'cgi'}->param('confirmed'))
727 {
728 rmtree($physical);
729 return devedit_reload({command => 'show', file => $dir});
730 }
731 else
732 {
733 my $tpl = new Template;
734 $tpl->read_file($config->{'templates'}->{'confirm_rmdir'});
735
736 $tpl->fillin('DIR',$virtual);
737 $tpl->fillin('UPPER_DIR',$dir);
738 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
739 $tpl->fillin('SCRIPT',$script);
740
741 my $output = header(-type => 'text/html');
742 $output .= $tpl->get_template;
743
744 return \$output;
745 }
746 }
747 else
748 {
749 # Remove a file
750
751 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
752
753 if($data->{'cgi'}->param('confirmed'))
754 {
755 unlink($physical) or return error($config->{'errors'}->{'delete_failed'},$dir,{FILE => $virtual});
756 return devedit_reload({command => 'show', file => $dir});
757 }
758 else
759 {
760 my $tpl = new Template;
761 $tpl->read_file($config->{'templates'}->{'confirm_rmfile'});
762
763 $tpl->fillin('FILE',$virtual);
764 $tpl->fillin('DIR',$dir);
765 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
766 $tpl->fillin('SCRIPT',$script);
767
768 my $output = header(-type => 'text/html');
769 $output .= $tpl->get_template;
770
771 return \$output;
772 }
773 }
774 }
775
776 # exec_chprop()
777 #
778 # Change the mode and the group of a file or a directory
779 #
780 # Params: 1. Reference to user input hash
781 # 2. Reference to config hash
782 #
783 # Return: Output of the command (Scalar Reference)
784
785 sub exec_chprop($$)
786 {
787 my ($data,$config) = @_;
788 my $physical = $data->{'physical'};
789 my $virtual = $data->{'virtual'};
790 my $dir = upper_path($virtual);
791
792 return error($config->{'errors'}->{'no_users'},$dir,{FILE => $virtual}) unless($users);
793 return error($config->{'errors'}->{'chprop_root'},'/') if($virtual eq '/');
794 return error($config->{'errors'}->{'not_owner'},$dir,{FILE => $virtual}) unless(-o $physical);
795 return error($config->{'errors'}->{'chprop_link'},$dir) if(-l $physical);
796 return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
797
798 my $cgi = $data->{'cgi'};
799 my $mode = $cgi->param('mode');
800 my $group = $cgi->param('group');
801
802 if($mode || $group)
803 {
804 if($mode)
805 {
806 # Change the mode
807
808 chmod(oct($mode),$physical);
809 }
810
811 if($group)
812 {
813 # Change the group using the `chgrp` system command
814
815 return error($config->{'errors'}->{'invalid_group'},$dir,{GROUP => encode_entities($group)}) unless($group =~ /^[a-z0-9_]+[a-z0-9_-]*$/i);
816 system('chgrp',$group,$physical);
817 }
818
819 return devedit_reload({command => 'show', file => $dir});
820 }
821 else
822 {
823 # Display the form
824
825 my @stat = stat($physical);
826 my $mode = $stat[2];
827 my $gid = $stat[5];
828
829 my $tpl = new Template;
830 $tpl->read_file($config->{'templates'}->{'chprop'});
831
832 # Insert file properties into the template
833
834 $tpl->fillin('MODE_OCTAL',substr(sprintf('%04o',$mode),-4));
835 $tpl->fillin('MODE_STRING',mode_string($mode));
836 $tpl->fillin('GID',$gid);
837
838 if(my $group = getgrgid($gid))
839 {
840 $tpl->fillin('GROUP',encode_entities($group));
841 $tpl->parse_if_block('group_detected',1);
842 }
843 else
844 {
845 $tpl->parse_if_block('group_detected',0);
846 }
847
848 # Insert other information
849
850 $tpl->fillin('FILE',$virtual);
851 $tpl->fillin('DIR',$dir);
852 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
853 $tpl->fillin('SCRIPT',$script);
854
855 my $output = header(-type => 'text/html');
856 $output .= $tpl->get_template;
857
858 return \$output;
859 }
860 }
861
862 # exec_unlock()
863 #
864 # Remove a file from the list of used files and
865 # return to directory view
866 #
867 # Params: 1. Reference to user input hash
868 # 2. Reference to config hash
869 #
870 # Return: Output of the command (Scalar Reference)
871
872 sub exec_unlock($$)
873 {
874 my ($data,$config) = @_;
875 my $virtual = $data->{'virtual'};
876 my $uselist = $data->{'uselist'};
877 my $dir = upper_path($virtual);
878
879 return devedit_reload({command => 'show', file => $dir}) if($uselist->unused($virtual));
880
881 if($data->{'cgi'}->param('confirmed'))
882 {
883 file_unlock($uselist,$virtual) or return error($config->{'errors'}->{'ul_rm_failed'},$dir,{FILE => $virtual, USELIST => $uselist->{'listfile'}});
884 return devedit_reload({command => 'show', file => $dir});
885 }
886 else
887 {
888 my $tpl = new Template;
889 $tpl->read_file($config->{'templates'}->{'confirm_unlock'});
890
891 $tpl->fillin('FILE',$virtual);
892 $tpl->fillin('DIR',$dir);
893 $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
894 $tpl->fillin('SCRIPT',$script);
895
896 my $output = header(-type => 'text/html');
897 $output .= $tpl->get_template;
898
899 return \$output;
900 }
901 }
902
903 # exec_about()
904 #
905 # Display some information about Dev-Editor
906 #
907 # Params: 1. Reference to user input hash
908 # 2. Reference to config hash
909 #
910 # Return: Output of the command (Scalar Reference)
911
912 sub exec_about($$)
913 {
914 my ($data,$config) = @_;
915
916 my $tpl = new Template;
917 $tpl->read_file($config->{'templates'}->{'about'});
918
919 $tpl->fillin('SCRIPT',$script);
920
921 # Dev-Editor's version number
922
923 $tpl->fillin('VERSION',$data->{'version'});
924
925 # Some path information
926
927 $tpl->fillin('SCRIPT_PHYS',encode_entities($ENV{'SCRIPT_FILENAME'}));
928 $tpl->fillin('CONFIG_PATH',encode_entities($data->{'configfile'}));
929 $tpl->fillin('FILE_ROOT', encode_entities($config->{'fileroot'}));
930 $tpl->fillin('HTTP_ROOT', encode_entities($config->{'httproot'}));
931
932 # Perl
933
934 $tpl->fillin('PERL_PROG',encode_entities($^X));
935 $tpl->fillin('PERL_VER', sprintf('%vd',$^V));
936
937 # Information about the server
938
939 $tpl->fillin('HTTPD',encode_entities($ENV{'SERVER_SOFTWARE'}));
940 $tpl->fillin('OS', encode_entities($^O));
941 $tpl->fillin('TIME', encode_entities(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime : localtime)));
942
943 $tpl->parse_if_block('gmt',$config->{'use_gmt'});
944
945 # Process information
946
947 $tpl->fillin('PID',$$);
948
949 # The following information is only available on systems supporting
950 # users and groups
951
952 if($users)
953 {
954 # Dev-Editor is running on a system which allows users and groups
955 # So we display the user and the group of our process
956
957 my $uid = POSIX::getuid;
958 my $gid = POSIX::getgid;
959
960 $tpl->parse_if_block('users',1);
961
962 # ID's of user and group
963
964 $tpl->fillin('UID',$uid);
965 $tpl->fillin('GID',$gid);
966
967 # Names of user and group
968
969 if(my $user = getpwuid($uid))
970 {
971 $tpl->fillin('USER',encode_entities($user));
972 $tpl->parse_if_block('user_detected',1);
973 }
974 else
975 {
976 $tpl->parse_if_block('user_detected',0);
977 }
978
979 if(my $group = getgrgid($gid))
980 {
981 $tpl->fillin('GROUP',encode_entities($group));
982 $tpl->parse_if_block('group_detected',1);
983 }
984 else
985 {
986 $tpl->parse_if_block('group_detected',0);
987 }
988
989 # Process umask
990
991 $tpl->fillin('UMASK',sprintf('%04o',umask));
992 }
993 else
994 {
995 $tpl->parse_if_block('users',0);
996 }
997
998 my $output = header(-type => 'text/html');
999 $output .= $tpl->get_template;
1000
1001 return \$output;
1002 }
1003
1004 # it's true, baby ;-)
1005
1006 1;
1007
1008 #
1009 ### End ###

patrick-canterino.de