";
+ if($config->{'max_file_size'} && $size > $config->{'max_file_size'})
+ {
+ return error($config->{'errors'}->{'file_too_large'},upper_path($virtual),{SIZE => $config->{'max_file_size'}})
+ }
+ else
+ {
+ my $content = file_read($physical);
+ $$content =~ s/\015\012|\012|\015/\n/g;
- $output .= htmlfoot;
+ $tpl->read_file($config->{'templates'}->{'viewfile'});
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+ $tpl->fillin("CONTENT",encode_entities($$content));
+
+ $tpl->parse_if_block("editable",-r $physical && -w $physical && -T $physical && not ($config->{'max_file_size'} && $size > $config->{'max_file_size'}) && $uselist->unused($virtual));
+ }
}
}
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
return \$output;
}
@@ -218,9 +251,9 @@ sub exec_beginedit($$)
my $virtual = $data->{'virtual'};
my $uselist = $data->{'uselist'};
- return error("You cannot edit directories.",upper_path($virtual)) if(-d $physical);
- return error_in_use($virtual) if($uselist->in_use($virtual));
- return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
+ return error($config->{'errors'}->{'editdir'},upper_path($virtual)) if(-d $physical);
+ return error($config->{'errors'}->{'in_use'},upper_path($virtual),{FILE => $virtual}) if($uselist->in_use($virtual));
+ return error($config->{'errors'}->{'noedit'},upper_path($virtual)) unless(-r $physical && -w $physical);
# Check on binary files
@@ -228,58 +261,57 @@ sub exec_beginedit($$)
{
# Binary file
- return error("This editor is not able to view/edit binary files.",upper_path($virtual));
+ return error($config->{'errors'}->{'binary'},upper_path($virtual));
}
else
{
- # Text file
-
- $uselist->add_file($virtual);
- $uselist->save;
-
- my $dir = upper_path($virtual);
- my $content = encode_entities(${file_read($physical)});
+ if($config->{'max_file_size'} && (stat($physical))[7] > $config->{'max_file_size'})
+ {
+ return error($config->{'errors'}->{'file_too_large'},upper_path($virtual),{SIZE => $config->{'max_file_size'}})
+ }
+ else
+ {
+ # Text file
- my $equal_url = equal_url($config->{'httproot'},$virtual);
+ $uselist->add_file($virtual);
+ $uselist->save;
- $virtual = encode_entities($virtual);
+ my $content = file_read($physical);
+ $$content =~ s/\015\012|\012|\015/\n/g;
- my $output = htmlhead("Edit file $virtual");
- $output .= $equal_url;
- $output .= <Caution! This file is locked for other users while you are editing it. To unlock it, click Save and exit or Exit WITHOUT saving. Please don't click the Reload button in your browser! This will confuse the editor.
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'editfile'});
-
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+ $tpl->fillin("CONTENT",encode_entities($$content));
-
-END
+# exec_canceledit()
+#
+# Abort file editing
+#
+# Params: 1. Reference to user input hash
+# 2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
- $output .= htmlfoot;
+sub exec_canceledit($$)
+{
+ my ($data,$config) = @_;
+ my $virtual = $data->{'virtual'};
- return \$output;
- }
+ file_unlock($data->{'uselist'},$virtual);
+ return devedit_reload({command => 'show', file => upper_path($virtual)});
}
# exec_endedit()
@@ -297,9 +329,7 @@ sub exec_endedit($$)
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
my $content = $data->{'cgi'}->param('filecontent');
-
- return error("You cannot edit directories.") if(-d $physical);
- return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
+ my $uselist = $data->{'uselist'};
# Normalize newlines
@@ -318,17 +348,29 @@ sub exec_endedit($$)
$physical = $data->{'new_physical'};
$virtual = $data->{'new_virtual'};
+
+ # Check if someone else is editing the new file
+
+ return error($config->{'errors'}->{'in_use'},upper_path($virtual),{FILE => $virtual}) if($uselist->in_use($virtual));
}
+ return error($config->{'errors'}->{'editdir'},upper_path($virtual)) if(-d $physical);
+ return error($config->{'errors'}->{'noedit'}, upper_path($virtual)) unless(-r $physical && -w $physical);
+
if(file_save($physical,\$content))
{
# Saving of the file was successful - so unlock it!
- return exec_unlock($data,$config);
+ file_unlock($uselist,$data->{'virtual'});
+ # ^^^^^^^^^^^^^^^^^^
+ # Maybe the user saved the file using another filename...
+ # But we have to unlock the original file!
+
+ return devedit_reload({command => 'show', file => upper_path($virtual)});
}
else
{
- return error("Saving of file '".encode_entities($virtual)."' failed'.",upper_path($virtual));
+ return error($config->{'errors'}->{'edit_failed'},upper_path($virtual),{FILE => $virtual});
}
}
@@ -349,10 +391,26 @@ sub exec_mkfile($$)
my $dir = upper_path($new_virtual);
$new_virtual = encode_entities($new_virtual);
- return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
+ if($new_physical)
+ {
+ return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
+
+ file_create($new_physical) or return error($config->{'errors'}->{'mkfile_failed'},$dir,{FILE => $new_virtual});
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'mkfile'});
+
+ $tpl->fillin("DIR","/");
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
- file_create($new_physical) or return error("Could not create file '$new_virtual'.",$dir);
- return devedit_reload({command => 'show', file => $dir});
+ return \$output;
+ }
}
# exec_mkdir()
@@ -372,107 +430,86 @@ sub exec_mkdir($$)
my $dir = upper_path($new_virtual);
$new_virtual = encode_entities($new_virtual);
- return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
+ return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
+
+ if($new_physical)
+ {
+ mkdir($new_physical,0777) or return error($config->{'errors'}->{'mkdir_failed'},$dir,{DIR => $new_virtual});
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'mkdir'});
- mkdir($new_physical) or return error("Could not create directory '$new_virtual'.",$dir);
- return devedit_reload({command => 'show', file => $dir});
+ $tpl->fillin("DIR","/");
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
}
-# exec_workwithfile()
+# exec_upload()
#
-# Display a form for renaming/copying/deleting/unlocking a file
+# Upload a file
#
# Params: 1. Reference to user input hash
# 2. Reference to config hash
#
# Return: Output of the command (Scalar Reference)
-sub exec_workwithfile($$)
+sub exec_upload($$)
{
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
- my $unused = $data->{'uselist'}->unused($virtual);
-
- my $dir = encode_entities(upper_path($virtual));
-
- my $output = htmlhead("Work with file ".encode_entities($virtual));
- $output .= equal_url($config->{'httproot'},$virtual);
+ my $cgi = $data->{'cgi'};
- $virtual = encode_entities($virtual);
-
- $output .= dir_link($virtual);
- $output .= "
Note: On UNIX systems, filenames are case-sensitive!
\n\n";
-
- $output .= "
Someone else is currently editing this file. So not all features are available.
\n\n" unless($unused);
-
- $output .= "\n\n";
-
- # Copying of the file is always allowed - but we need read access
-
- if(-r $physical)
+ if(my $uploaded_file = $cgi->param('uploaded_file'))
{
- $output .= <Copy
+ # Process file upload
-
+ my $filename = file_name($uploaded_file);
+ my $file_phys = $physical."/".$filename;
+ my $file_virt = $virtual."".$filename;
-
+ return error($config->{'errors'}->{'file_exists'},$virtual,{FILE => $file_virt}) if(-e $file_phys && not $cgi->param('overwrite'));
-END
- }
+ my $ascii = $cgi->param('ascii');
+ my $handle = $cgi->upload('uploaded_file');
- if($unused)
- {
- # File is not locked
- # Allow renaming and deleting the file
+ local *FILE;
- $output .= <Move/rename
+ open(FILE,">$file_phys") or return error($config->{'errors'}->{'mkfile_failed'},$virtual,{FILE => $file_virt});
+ binmode(FILE) unless($ascii);
-
+ # Read transferred file and write it to disk
-
+ read($handle, my $data, -s $handle);
+ $data =~ s/\015\012|\012|\015/\n/g if($ascii); # Replace line separators if transferring in ASCII mode
+ print FILE $data;
-
Delete
+ close(FILE);
-
-END
+ return devedit_reload({command => "show", file => $virtual});
}
else
{
- # File is locked
- # Just display a button for unlocking it
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'upload'});
- $output .= <Unlock file
+ $tpl->fillin("DIR",$virtual);
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
-
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 only in this case) you can unlock the file using this button:
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
-
-END
+ return \$output;
}
-
- $output .= "\n";
- $output .= htmlfoot;
-
- return \$output;
}
# exec_copy()
@@ -490,20 +527,63 @@ sub exec_copy($$)
my $physical = $data->{'physical'};
my $virtual = encode_entities($data->{'virtual'});
my $new_physical = $data->{'new_physical'};
- my $new_virtual = $data->{'new_virtual'};
- my $dir = upper_path($new_virtual);
- $new_virtual = encode_entities($new_virtual);
- return error("This editor is not able to copy directories.") if(-d $physical);
- return error("You have not enough permissions to copy this file.") unless(-r $physical);
+ return error($config->{'errors'}->{'nocopy'}) unless(-r $physical);
- if(-e $new_physical)
+ if($new_physical)
{
- 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));
+ my $new_virtual = $data->{'new_virtual'};
+ my $dir = upper_path($new_virtual);
+ $new_virtual = encode_entities($new_virtual);
+
+ if(-e $new_physical)
+ {
+ return error($config->{'errors'}->{'exist_edited'},$dir,{FILE => $new_virtual}) if($data->{'uselist'}->in_use($data->{'new_virtual'}));
+
+ if(-d $new_physical)
+ {
+ return error($config->{'errors'}->{'dircopy'});
+ }
+ elsif(not $data->{'cgi'}->param('confirmed'))
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_replace'});
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("NEW_FILE",$new_virtual);
+ $tpl->fillin("NEW_FILENAME",file_name($new_virtual));
+ $tpl->fillin("NEW_DIR",$dir);
+ $tpl->fillin("DIR",upper_path($virtual));
+
+ $tpl->fillin("COMMAND","copy");
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+
+ copy($physical,$new_physical) or return error($config->{'errors'}->{'copy_failed'},upper_path($virtual),{FILE => $virtual, NEW_FILE => $new_virtual});
+ return devedit_reload({command => 'show', file => $dir});
}
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'copyfile'});
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
- copy($physical,$new_physical) or return error("Could not copy '$virtual' to '$new_virtual'",upper_path($virtual));
- return devedit_reload({command => 'show', file => $dir});
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
}
# exec_rename()
@@ -521,24 +601,69 @@ sub exec_rename($$)
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
my $new_physical = $data->{'new_physical'};
- my $new_virtual = $data->{'new_virtual'};
- my $dir = upper_path($new_virtual);
- $new_virtual = encode_entities($new_virtual);
- return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
+ return error($config->{'errors'}->{'rename_root'},"/") if($virtual eq "/");
+ return error($config->{'errors'}->{'in_use'},upper_path($virtual),{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
- if(-e $new_physical)
+ if($new_physical)
{
- 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));
+ my $new_virtual = $data->{'new_virtual'};
+ my $dir = upper_path($new_virtual);
+ $new_virtual = encode_entities($new_virtual);
+
+ if(-e $new_physical)
+ {
+ return error($config->{'errors'}->{'exist_edited'},$dir,{FILE => $new_virtual}) if($data->{'uselist'}->in_use($data->{'new_virtual'}));
+
+ if(-d $new_physical)
+ {
+ return error($config->{'errors'}->{'dircopy'});
+ }
+ elsif(not $data->{'cgi'}->param('confirmed'))
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_replace'});
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("NEW_FILE",$new_virtual);
+ $tpl->fillin("NEW_FILENAME",file_name($new_virtual));
+ $tpl->fillin("NEW_DIR",$dir);
+ $tpl->fillin("DIR",upper_path($virtual));
+
+ $tpl->fillin("COMMAND","rename");
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+
+ rename($physical,$new_physical) or return error($config->{'errors'}->{'rename_failed'},upper_path($virtual),{FILE => $virtual, NEW_FILE => $new_virtual});
+ return devedit_reload({command => 'show', file => $dir});
}
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'renamefile'});
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
- rename($physical,$new_physical) or return error("Could not move/rename '".encode_entities($virtual)."' to '$new_virtual'.",upper_path($virtual));
- return devedit_reload({command => 'show', file => $dir});
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
}
# exec_remove()
#
-# Remove a file and return to directory view
+# Remove a file or a directory and return to directory view
#
# Params: 1. Reference to user input hash
# 2. Reference to config hash
@@ -551,11 +676,137 @@ sub exec_remove($$)
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
- return error("Deleting directories is currently unsupported.",upper_path($virtual)) if(-d $physical);
- return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
+ return error($config->{'errors'}->{'remove_root'},"/") if($virtual eq "/");
- unlink($physical) or return error("Could not delete file '".encode_entities($virtual)."'.",upper_path($virtual));
- return devedit_reload({command => 'show', file => upper_path($virtual)});
+ if(-d $physical)
+ {
+ # Remove a directory
+
+ if($data->{'cgi'}->param('confirmed'))
+ {
+ rmtree($physical);
+ return devedit_reload({command => 'show', file => upper_path($virtual)});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_rmdir'});
+
+ $tpl->fillin("DIR",$virtual);
+ $tpl->fillin("UPPER_DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+ else
+ {
+ # Remove a file
+
+ return error($config->{'errors'}->{'in_use'},upper_path($virtual),{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
+
+ if($data->{'cgi'}->param('confirmed'))
+ {
+ unlink($physical) or return error($config->{'errors'}->{'delete_failed'},upper_path($virtual),{FILE => $virtual});
+ return devedit_reload({command => 'show', file => upper_path($virtual)});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_rmfile'});
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+}
+
+# exec_chprop()
+#
+# Change the mode and the group of a file or a directory
+#
+# Params: 1. Reference to user input hash
+# 2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
+
+sub exec_chprop($$)
+{
+ my ($data,$config) = @_;
+ my $physical = $data->{'physical'};
+ my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
+ my $cgi = $data->{'cgi'};
+ my $mode = $cgi->param('mode');
+ my $group = $cgi->param('group');
+
+ if($users)
+ {
+ if(-o $physical)
+ {
+ if($mode || $group)
+ {
+ if($mode)
+ {
+ my $oct_mode = $mode;
+ $oct_mode = "0".$oct_mode if(length($oct_mode) == 3);
+ $oct_mode = oct($oct_mode);
+
+ chmod($oct_mode,$physical);
+ }
+
+ chgrp($group,$physical) if($group);
+
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my @stat = stat($physical);
+
+ my $mode = $stat[2];
+ my $mode_oct = substr(sprintf("%04o",$mode),-4);
+ my $gid = $stat[5];
+ my $group = getgrgid($gid);
+
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'chprop'});
+
+ $tpl->fillin("MODE_OCTAL",$mode_oct);
+ $tpl->fillin("MODE_STRING",mode_string($mode));
+ $tpl->fillin("GID",$gid);
+ $tpl->fillin("GROUP",$group);
+
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",$dir);
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+ else
+ {
+ return error($config->{'errors'}->{'not_owner'},$dir,{FILE => $virtual});
+ }
+ }
+ else
+ {
+ return error($config->{'errors'}->{'no_users'},$dir,{FILE => $virtual});
+ }
}
# exec_unlock()
@@ -572,12 +823,101 @@ sub exec_unlock($$)
{
my ($data,$config) = @_;
my $virtual = $data->{'virtual'};
- my $uselist = $data->{'uselist'};
- $uselist->remove_file($virtual);
- $uselist->save;
+ if($data->{'cgi'}->param('confirmed'))
+ {
+ file_unlock($data->{'uselist'},$virtual);
+ return devedit_reload({command => 'show', file => upper_path($virtual)});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_unlock'});
- return devedit_reload({command => 'show', file => upper_path($virtual)});
+ $tpl->fillin("FILE",$virtual);
+ $tpl->fillin("DIR",upper_path($virtual));
+ $tpl->fillin("URL",equal_url($config->{'httproot'},$virtual));
+ $tpl->fillin("SCRIPT",$script);
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+}
+
+# exec_about()
+#
+# Display some information about Dev-Editor
+#
+# Params: 1. Reference to user input hash
+# 2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
+
+sub exec_about($$)
+{
+ my ($data,$config) = @_;
+
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'about'});
+
+ $tpl->fillin("SCRIPT",$script);
+
+ # Dev-Editor's version number
+
+ $tpl->fillin("VERSION",$data->{'version'});
+
+ # Some path information
+
+ $tpl->fillin("SCRIPT_PHYS",$ENV{'SCRIPT_FILENAME'});
+ $tpl->fillin("CONFIG_PATH",$data->{'configfile'});
+ $tpl->fillin("FILE_ROOT",$config->{'fileroot'});
+ $tpl->fillin("HTTP_ROOT",$config->{'httproot'});
+
+ # Perl
+
+ $tpl->fillin("PERL_PROG",$^X);
+ $tpl->fillin("PERL_VER",sprintf("%vd",$^V));
+
+ # Information about the server
+
+ $tpl->fillin("HTTPD",$ENV{'SERVER_SOFTWARE'});
+ $tpl->fillin("OS",$^O);
+ $tpl->fillin("TIME",strftime($config->{'timeformat'},localtime));
+
+ # Process information
+
+ $tpl->fillin("PID",$$);
+
+ # Check if the functions getpwuid() and getgrgid() are available
+
+ if($users)
+ {
+ # Dev-Editor is running on a system which allows users and groups
+ # So we display the user and the group of our process
+
+ $tpl->parse_if_block("users",1);
+
+ # ID's of user and group
+
+ $tpl->fillin("UID",$<);
+ $tpl->fillin("GID",$();
+
+ # Names of user and group
+
+ $tpl->fillin("USER",getpwuid($<));
+ $tpl->fillin("GROUP",getgrgid($());
+ }
+ else
+ {
+ $tpl->parse_if_block("users",0);
+ }
+
+ my $output = header(-type => "text/html");
+ $output .= $tpl->get_template;
+
+ return \$output;
}
# it's true, baby ;-)