basic attachment plugin, unfinished

Currently includes UI, and a few tests of the attachment, as well as the
framework to extend pagespecs to test attachments. Does not actually save
the file yet.
master
Joey Hess 2008-06-30 22:58:33 -04:00
parent 6643db0cd2
commit 0a37c45f32
2 changed files with 177 additions and 0 deletions

View File

@ -0,0 +1,134 @@
#!/usr/bin/perl
package IkiWiki::Plugin::attachment;
use warnings;
use strict;
use IkiWiki 2.00;
use CGI;
$CGI::DISABLE_UPLOADS=0;
# TODO move to admin prefs
$config{valid_attachments}="(*.mp3 and maxsize(15mb)) or (* and maxsize(.50kb))";
sub import { #{{{
hook(type => "formbuilder_setup", id => "attachment", call => \&formbuilder_setup);
hook(type => "formbuilder", id => "attachment", call => \&formbuilder);
} # }}}
sub formbuilder_setup { #{{{
my %params=@_;
my $form=$params{form};
return if $form->field("do") ne "edit";
$form->field(name => 'attachment', type => 'file');
} #}}}
sub formbuilder (@) { #{{{
my %params=@_;
my $form=$params{form};
return if $form->field("do") ne "edit";
if ($form->submitted eq "Upload") {
my $q=$params{cgi};
my $filename=IkiWiki::basename($q->param('attachment'));
if (! defined $filename || ! length $filename) {
# no file, so do nothing
return;
}
# This is an (apparently undocumented) way to get the name
# of the temp file that CGI writes the upload to.
my $tempfile=$q->tmpFileName($filename);
# To untaint the filename, escape any hazardous characters,
# and make sure it isn't pruned.
$filename=IkiWiki::possibly_foolish_untaint(IkiWiki::titlepage($filename));
if (IkiWiki::file_pruned($filename, $config{srcdir})) {
error(gettext("bad attachment filename"));
}
# Check that the attachment matches the configured
# pagespec.
my $result=pagespec_match($filename, $config{valid_attachments},
tempfile => $tempfile);
if (! $result) {
error(gettext("attachment rejected")." ($result)");
}
my $fh=$q->upload('attachment');
if (! defined $fh || ! ref $fh) {
error("failed to get filehandle");
}
binmode($fh);
while (<$fh>) {
print STDERR $_."\n";
}
}
} # }}}
package IkiWiki::PageSpec;
sub parsesize { #{{{
my $size=shift;
no warnings;
my $base=$size+0; # force to number
use warnings;
my $exponent=1;
if ($size=~/kb?$/i) {
$exponent=10;
}
elsif ($size=~/mb?$/i) {
$exponent=20;
}
elsif ($size=~/gb?$/i) {
$exponent=30;
}
elsif ($size=~/tb?$/i) {
$exponent=40;
}
return $base * 2**$exponent;
} #}}}
sub match_maxsize ($$;@) { #{{{
shift;
my $maxsize=eval{parsesize(shift)};
if ($@) {
return IkiWiki::FailReason->new("unable to parse maxsize (or number too large)");
}
my %params=@_;
if (! exists $params{tempfile}) {
return IkiWiki::FailReason->new("no tempfile specified");
}
if (-s $params{tempfile} > $maxsize) {
return IkiWiki::FailReason->new("attachment too large");
}
else {
return IkiWiki::SuccessReason->new("attachment size ok");
}
} #}}}
sub match_minsize ($$;@) { #{{{
shift;
my $minsize=eval{parsesize(shift)};
if ($@) {
return IkiWiki::FailReason->new("unable to parse minsize (or number too large)");
}
my %params=@_;
if (! exists $params{tempfile}) {
return IkiWiki::FailReason->new("no tempfile specified");
}
if (-s $params{tempfile} < $minsize) {
return IkiWiki::FailReason->new("attachment too small");
}
else {
return IkiWiki::SuccessReason->new("attachment size ok");
}
} #}}}
1

View File

@ -0,0 +1,43 @@
[[template id=plugin name=conditional core=1 author="[[Joey]]"]]
[[tag type/useful]]
This plugin allows files to be uploaded to the wiki over the web.
For each page `foo`, files in the subdirectory `foo/` are treated as
attachments of that page. Attachments can be uploaded and managed as
part of the interface for editing a page.
Warning: Do not enable this plugin on publically editable wikis, unless you
take care to lock down the types and sizes of files that can be uploaded.
Bear in mind that if you let anyone upload a particular kind of file
("*.mp3" files, say), then someone can abuse your wiki in at least three ways:
1. By uploading many mp3 files, wasting your disk space.
2. By uploading mp3 files that attempt to exploit security holes
in web browsers or other players.
3. By uploading files that claim to be mp3 files, but are really some
other kind of file. Some web browsers may display a `foo.mp3` that
contains html as a web page; including running any malicious javascript
embedded in that page.
To provide a way to combat these abuses, the wiki admin can specify a
[[ikiwiki/PageSpec]] on their preferences page, to control what types of
attachments can be uploaded. The regular [[ikiwiki/PageSpec]] syntax is
expanded with additional tests.
For example, to limit arbitrary files to 50 kilobtes, but allow
larger mp3 files to be uploaded, a test like this could be used:
(*.mp3 and maxsize(15mb)) or (* and maxsize(50kb))
The following additional tests are available:
* maxsize(size)
Tests whether the attachment is no larger than the specified size.
The size defaults to being in bytes, but "kb", "mb", "gb" etc can be
used to specify the units.
* minsize(size)
Tests whether the attachment is no smaller than the specified size.