2008-07-01 04:58:33 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
package IkiWiki::Plugin::attachment;
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
2008-12-23 22:34:19 +01:00
|
|
|
use IkiWiki 3.00;
|
2008-07-01 06:42:42 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub import {
|
2011-06-16 01:08:40 +02:00
|
|
|
add_underlay("attachment");
|
2011-06-16 01:16:08 +02:00
|
|
|
add_underlay("javascript");
|
|
|
|
add_underlay("jquery");
|
2008-07-26 00:05:55 +02:00
|
|
|
hook(type => "getsetup", id => "attachment", call => \&getsetup);
|
2008-07-01 19:43:32 +02:00
|
|
|
hook(type => "checkconfig", id => "attachment", call => \&checkconfig);
|
2008-07-01 04:58:33 +02:00
|
|
|
hook(type => "formbuilder_setup", id => "attachment", call => \&formbuilder_setup);
|
2011-06-14 20:44:20 +02:00
|
|
|
hook(type => "formbuilder", id => "attachment", call => \&formbuilder, last => 1);
|
2008-08-26 01:52:34 +02:00
|
|
|
IkiWiki::loadplugin("filecheck");
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-01 04:58:33 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub getsetup () {
|
2008-07-26 00:05:55 +02:00
|
|
|
return
|
2008-08-03 22:40:12 +02:00
|
|
|
plugin => {
|
|
|
|
safe => 1,
|
|
|
|
rebuild => 0,
|
2010-02-12 10:22:15 +01:00
|
|
|
section => "web",
|
2008-08-03 22:40:12 +02:00
|
|
|
},
|
2008-08-01 21:45:57 +02:00
|
|
|
allowed_attachments => {
|
2008-08-02 22:40:46 +02:00
|
|
|
type => "pagespec",
|
2008-08-03 22:40:12 +02:00
|
|
|
example => "virusfree() and mimetype(image/*) and maxsize(50kb)",
|
2008-08-01 21:45:57 +02:00
|
|
|
description => "enhanced PageSpec specifying what attachments are allowed",
|
2008-08-03 20:36:17 +02:00
|
|
|
link => "ikiwiki/PageSpec/attachment",
|
2008-08-01 21:45:57 +02:00
|
|
|
safe => 1,
|
|
|
|
rebuild => 0,
|
|
|
|
},
|
2008-08-04 01:35:35 +02:00
|
|
|
virus_checker => {
|
|
|
|
type => "string",
|
|
|
|
example => "clamdscan -",
|
|
|
|
description => "virus checker program (reads STDIN, returns nonzero if virus found)",
|
|
|
|
safe => 0, # executed
|
|
|
|
rebuild => 0,
|
|
|
|
},
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-26 00:05:55 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub check_canattach ($$;$) {
|
2008-07-22 04:41:31 +02:00
|
|
|
my $session=shift;
|
|
|
|
my $dest=shift; # where it's going to be put, under the srcdir
|
|
|
|
my $file=shift; # the path to the attachment currently
|
|
|
|
|
2008-07-22 23:12:20 +02:00
|
|
|
# Don't allow an attachment to be uploaded with the same name as an
|
|
|
|
# existing page.
|
2008-08-12 21:34:47 +02:00
|
|
|
if (exists $IkiWiki::pagesources{$dest} &&
|
|
|
|
$IkiWiki::pagesources{$dest} ne $dest) {
|
2008-07-22 23:12:20 +02:00
|
|
|
error(sprintf(gettext("there is already a page named %s"), $dest));
|
|
|
|
}
|
|
|
|
|
2008-07-22 04:41:31 +02:00
|
|
|
# Use a special pagespec to test that the attachment is valid.
|
|
|
|
my $allowed=1;
|
2008-08-01 21:45:57 +02:00
|
|
|
if (defined $config{allowed_attachments} &&
|
|
|
|
length $config{allowed_attachments}) {
|
|
|
|
$allowed=pagespec_match($dest,
|
|
|
|
$config{allowed_attachments},
|
|
|
|
file => $file,
|
|
|
|
user => $session->param("name"),
|
2010-06-23 22:32:20 +02:00
|
|
|
ip => $session->remote_addr(),
|
2008-08-01 21:45:57 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2008-07-22 04:41:31 +02:00
|
|
|
if (! $allowed) {
|
2008-07-22 21:06:59 +02:00
|
|
|
error(gettext("prohibited by allowed_attachments")." ($allowed)");
|
2008-07-22 04:41:31 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 1;
|
|
|
|
}
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-22 04:41:31 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub checkconfig () {
|
2008-07-01 19:43:32 +02:00
|
|
|
$config{cgi_disable_uploads}=0;
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-01 19:43:32 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub formbuilder_setup (@) {
|
2008-07-01 04:58:33 +02:00
|
|
|
my %params=@_;
|
|
|
|
my $form=$params{form};
|
2008-07-02 21:42:32 +02:00
|
|
|
my $q=$params{cgi};
|
2008-07-01 04:58:33 +02:00
|
|
|
|
2008-10-02 18:48:06 +02:00
|
|
|
if (defined $form->field("do") && ($form->field("do") eq "edit" ||
|
|
|
|
$form->field("do") eq "create")) {
|
2008-07-08 23:18:02 +02:00
|
|
|
# Add attachment field, set type to multipart.
|
|
|
|
$form->enctype(&CGI::MULTIPART);
|
2008-07-01 20:02:30 +02:00
|
|
|
$form->field(name => 'attachment', type => 'file');
|
2008-07-01 23:19:38 +02:00
|
|
|
# These buttons are not put in the usual place, so
|
2008-07-02 02:35:54 +02:00
|
|
|
# are not added to the normal formbuilder button list.
|
2008-07-01 23:19:38 +02:00
|
|
|
$form->tmpl_param("field-upload" => '<input name="_submit" type="submit" value="Upload Attachment" />');
|
|
|
|
$form->tmpl_param("field-link" => '<input name="_submit" type="submit" value="Insert Links" />');
|
2008-07-02 21:42:32 +02:00
|
|
|
|
2011-06-16 01:08:40 +02:00
|
|
|
# Add all the javascript used by the attachments interface.
|
2008-07-02 21:42:32 +02:00
|
|
|
require IkiWiki::Plugin::toggle;
|
2011-06-16 01:08:40 +02:00
|
|
|
my $js=IkiWiki::Plugin::toggle::include_javascript($params{page});
|
2011-06-16 01:48:49 +02:00
|
|
|
$js.='<link rel="stylesheet" href="'.urlto("ikiwiki/jquery-ui.min.css", $params{page}).'" id="theme">'."\n";
|
2011-06-16 01:08:40 +02:00
|
|
|
my @jsfiles=qw{jquery.min jquery-ui.min
|
|
|
|
jquery.tmpl.min jquery.iframe-transport
|
|
|
|
jquery.fileupload jquery.fileupload-ui
|
|
|
|
};
|
|
|
|
foreach my $file (@jsfiles) {
|
|
|
|
$js.='<script src="'.urlto("ikiwiki/$file.js", $params{page}).
|
|
|
|
'" type="text/javascript" charset="utf-8"></script>'."\n";
|
|
|
|
}
|
|
|
|
$form->tmpl_param("javascript" => $js);
|
|
|
|
|
2008-07-02 21:42:32 +02:00
|
|
|
# Start with the attachments interface toggled invisible,
|
|
|
|
# but if it was used, keep it open.
|
|
|
|
if ($form->submitted ne "Upload Attachment" &&
|
2008-07-08 15:40:46 +02:00
|
|
|
(! defined $q->param("attachment_select") ||
|
|
|
|
! length $q->param("attachment_select"))) {
|
2008-07-02 21:42:32 +02:00
|
|
|
$form->tmpl_param("attachments-class" => "toggleable");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$form->tmpl_param("attachments-class" => "toggleable-open");
|
|
|
|
}
|
2011-06-14 20:08:13 +02:00
|
|
|
|
2011-07-12 00:34:17 +02:00
|
|
|
# Save attachments in holding area before previewing and
|
|
|
|
# saving.
|
|
|
|
if ($form->submitted eq "Preview" ||
|
|
|
|
$form->submitted eq "Save Page") {
|
2011-06-14 20:08:13 +02:00
|
|
|
attachments_save($form, $params{session});
|
|
|
|
}
|
2008-07-01 20:02:30 +02:00
|
|
|
}
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-01 04:58:33 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub formbuilder (@) {
|
2008-07-01 04:58:33 +02:00
|
|
|
my %params=@_;
|
|
|
|
my $form=$params{form};
|
2008-07-02 00:08:31 +02:00
|
|
|
my $q=$params{cgi};
|
2008-07-01 04:58:33 +02:00
|
|
|
|
2008-10-02 18:48:06 +02:00
|
|
|
return if ! defined $form->field("do") || ($form->field("do") ne "edit" && $form->field("do") ne "create") ;
|
2008-07-01 04:58:33 +02:00
|
|
|
|
2014-10-11 10:28:22 +02:00
|
|
|
my $filename=Encode::decode_utf8(scalar $q->param('attachment'));
|
2015-06-07 15:49:31 +02:00
|
|
|
my $handle=$q->upload('attachment');
|
|
|
|
|
2011-06-15 21:21:59 +02:00
|
|
|
if (defined $filename && length $filename) {
|
2015-06-07 15:49:31 +02:00
|
|
|
attachment_store($filename, $handle, $form, $q, $params{session});
|
2008-07-01 04:58:33 +02:00
|
|
|
}
|
2011-06-15 21:21:59 +02:00
|
|
|
|
2011-06-14 20:08:13 +02:00
|
|
|
if ($form->submitted eq "Save Page") {
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
attachments_save($form, $params{session});
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($form->submitted eq "Insert Links") {
|
2014-10-11 10:28:22 +02:00
|
|
|
my $page=quotemeta(Encode::decode_utf8(scalar $q->param("page")));
|
2008-07-02 00:08:31 +02:00
|
|
|
my $add="";
|
2014-10-15 23:32:02 +02:00
|
|
|
foreach my $f (@{$q->param_fetch("attachment_select")}) {
|
2009-12-14 23:16:40 +01:00
|
|
|
$f=Encode::decode_utf8($f);
|
2008-07-26 01:22:29 +02:00
|
|
|
$f=~s/^$page\///;
|
2010-06-13 05:00:30 +02:00
|
|
|
if (IkiWiki::isinlinableimage($f) &&
|
2012-03-18 19:34:21 +01:00
|
|
|
IkiWiki::Plugin::img->can("import")) {
|
2010-06-13 05:00:30 +02:00
|
|
|
$add.='[[!img '.$f.' align="right" size="" alt=""]]';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$add.="[[$f]]";
|
|
|
|
}
|
|
|
|
$add.="\n";
|
2008-07-02 00:08:31 +02:00
|
|
|
}
|
|
|
|
$form->field(name => 'editcontent',
|
|
|
|
value => $form->field('editcontent')."\n\n".$add,
|
2008-07-02 21:42:32 +02:00
|
|
|
force => 1) if length $add;
|
2008-07-02 00:08:31 +02:00
|
|
|
}
|
2008-07-02 01:05:15 +02:00
|
|
|
|
|
|
|
# Generate the attachment list only after having added any new
|
|
|
|
# attachments.
|
|
|
|
$form->tmpl_param("attachment_list" => [attachment_list($form->field('page'))]);
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-01 04:58:33 +02:00
|
|
|
|
2011-06-14 21:47:47 +02:00
|
|
|
sub attachment_holding_location {
|
2011-06-14 20:44:20 +02:00
|
|
|
my $page=attachment_location(shift);
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
|
2011-06-14 21:47:47 +02:00
|
|
|
my $dir=$config{wikistatedir}."/attachments/".
|
2011-06-14 19:41:07 +02:00
|
|
|
IkiWiki::possibly_foolish_untaint(linkpage($page));
|
2011-06-14 21:47:47 +02:00
|
|
|
$dir=~s/\/$//;
|
|
|
|
return $dir;
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
}
|
|
|
|
|
2011-06-14 21:30:19 +02:00
|
|
|
sub is_held_attachment {
|
2011-06-14 20:44:20 +02:00
|
|
|
my $attachment=shift;
|
|
|
|
|
2011-06-14 21:47:47 +02:00
|
|
|
my $f=attachment_holding_location($attachment);
|
2011-06-14 20:44:20 +02:00
|
|
|
if (-f $f) {
|
2011-06-14 21:30:19 +02:00
|
|
|
return $f
|
2011-06-14 20:44:20 +02:00
|
|
|
}
|
|
|
|
else {
|
2011-06-14 21:30:19 +02:00
|
|
|
return undef;
|
2011-06-14 20:44:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
# Stores the attachment in a holding area, not yet in the wiki proper.
|
|
|
|
sub attachment_store {
|
2011-06-14 19:06:59 +02:00
|
|
|
my $filename=shift;
|
2015-06-07 15:49:31 +02:00
|
|
|
my $handle=shift;
|
2011-06-14 19:06:59 +02:00
|
|
|
my $form=shift;
|
|
|
|
my $q=shift;
|
|
|
|
my $session=shift;
|
2015-06-07 15:49:31 +02:00
|
|
|
|
|
|
|
my $tempfile;
|
|
|
|
if (defined $handle) {
|
|
|
|
# This is what works in CGI.pm 4.09+: $q->tmpFileName($q->upload('attachment'))
|
|
|
|
$tempfile=$q->tmpFileName($handle);
|
|
|
|
}
|
|
|
|
if (! defined $tempfile || ! length $tempfile) {
|
|
|
|
# This is what is *documented* in CGI.pm 4.09: $q->tmpFileName($q->param('attachment'))
|
|
|
|
$tempfile=$q->tmpFileName($filename);
|
|
|
|
}
|
2011-06-14 19:06:59 +02:00
|
|
|
if (! defined $tempfile || ! length $tempfile) {
|
|
|
|
# perl 5.8 needs an alternative, awful method
|
|
|
|
if ($q =~ /HASH/ && exists $q->{'.tmpfiles'}) {
|
|
|
|
foreach my $key (keys(%{$q->{'.tmpfiles'}})) {
|
|
|
|
$tempfile=$q->tmpFileName(\$key);
|
|
|
|
last if defined $tempfile && length $tempfile;
|
|
|
|
}
|
|
|
|
}
|
2015-06-07 15:49:31 +02:00
|
|
|
}
|
|
|
|
if (! defined $tempfile || ! length $tempfile) {
|
|
|
|
error("CGI::tmpFileName failed to return the uploaded file name");
|
2011-06-14 19:06:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$filename=IkiWiki::basename($filename);
|
|
|
|
$filename=~s/.*\\+(.+)/$1/; # hello, windows
|
2011-06-14 19:38:37 +02:00
|
|
|
$filename=IkiWiki::possibly_foolish_untaint(linkpage($filename));
|
2011-06-16 19:01:23 +02:00
|
|
|
my $dest=attachment_holding_location($form->field('page'));
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
|
|
|
|
# Check that the user is allowed to edit the attachment.
|
2011-06-14 19:38:37 +02:00
|
|
|
my $final_filename=
|
|
|
|
linkpage(IkiWiki::possibly_foolish_untaint(
|
|
|
|
attachment_location($form->field('page')))).
|
|
|
|
$filename;
|
2011-06-16 19:01:23 +02:00
|
|
|
eval {
|
|
|
|
if (IkiWiki::file_pruned($final_filename)) {
|
|
|
|
error(gettext("bad attachment filename"));
|
|
|
|
}
|
|
|
|
IkiWiki::check_canedit($final_filename, $q, $session);
|
|
|
|
# And that the attachment itself is acceptable.
|
|
|
|
check_canattach($session, $final_filename, $tempfile);
|
|
|
|
};
|
|
|
|
if ($@) {
|
protect $@ whenever a block using $@ is non-trivial
As noted in the Try::Tiny man page, eval/$@ can be quite awkward in
corner cases, because $@ has the same properties and problems as C's
errno. While writing a regression test for definetemplate
in which it couldn't find an appropriate template, I received
<span class="error">Error: failed to process template
<span class="createlink">deftmpl</span> </span>
instead of the intended
<span class="error">Error: failed to process template
<span class="createlink">deftmpl</span> template deftmpl not
found</span>
which turned out to be because the "catch"-analogous block called
gettext before it used $@, and gettext can call define_gettext,
which uses eval.
This commit alters all current "catch"-like blocks that use $@, except
those that just do trivial things with $@ (string interpolation, string
concatenation) and call a function (die, error, print, etc.)
2014-02-21 18:06:36 +01:00
|
|
|
# save error in case called functions clobber $@
|
|
|
|
my $error = $@;
|
|
|
|
json_response($q, $form, $dest."/".$filename, $error);
|
|
|
|
error $error;
|
2011-06-14 19:06:59 +02:00
|
|
|
}
|
|
|
|
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
# Move the attachment into holding directory.
|
2011-06-14 19:06:59 +02:00
|
|
|
# Try to use a fast rename; fall back to copying.
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
IkiWiki::prep_writefile($filename, $dest);
|
|
|
|
unlink($dest."/".$filename);
|
|
|
|
if (rename($tempfile, $dest."/".$filename)) {
|
2011-06-14 19:06:59 +02:00
|
|
|
# The temp file has tight permissions; loosen up.
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
chmod(0666 & ~umask, $dest."/".$filename);
|
2011-06-14 19:06:59 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
my $fh=$q->upload('attachment');
|
|
|
|
if (! defined $fh || ! ref $fh) {
|
|
|
|
# needed by old CGI versions
|
|
|
|
$fh=$q->param('attachment');
|
|
|
|
if (! defined $fh || ! ref $fh) {
|
|
|
|
# even that doesn't always work,
|
|
|
|
# fall back to opening the tempfile
|
|
|
|
$fh=undef;
|
|
|
|
open($fh, "<", $tempfile) || error("failed to open \"$tempfile\": $!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
binmode($fh);
|
2011-06-14 20:44:20 +02:00
|
|
|
require IkiWiki::Render;
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
writefile($filename, $dest, undef, 1, sub {
|
2011-06-14 19:06:59 +02:00
|
|
|
IkiWiki::fast_file_copy($tempfile, $filename, $fh, @_);
|
|
|
|
});
|
|
|
|
}
|
2011-06-16 02:02:14 +02:00
|
|
|
|
improve detection of ajax request
Firefox sent an accept header for application/xml, not application/json,
and also weakened the priority to 0.8. So that stuff is not to be trusted;
instead I found a better way: When an ajax upload is *not* being made,
the Upload Attachment button will be used, so enable ajax if an upload
is being made without that button having been used.
Also, testing with firefox revealed it refused to process a response that
was type application/json, and checking the demo page for the jquery file
upload plugin, it actually returns the json with type text/html. Ugh.
Followed suite.
Now tested with: chromium, chromium (w/o js), firefox, firefox (w/o js),
and w3m.
2011-06-17 21:17:20 +02:00
|
|
|
json_response($q, $form, $dest."/".$filename, stored_msg());
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# Save all stored attachments for a page.
|
|
|
|
sub attachments_save {
|
|
|
|
my $form=shift;
|
|
|
|
my $session=shift;
|
|
|
|
|
|
|
|
# Move attachments out of holding directory.
|
|
|
|
my @attachments;
|
2011-06-14 21:47:47 +02:00
|
|
|
my $dir=attachment_holding_location($form->field('page'));
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
foreach my $filename (glob("$dir/*")) {
|
2012-01-15 21:39:13 +01:00
|
|
|
$filename=Encode::decode_utf8($filename);
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
next unless -f $filename;
|
2013-07-11 00:23:09 +02:00
|
|
|
my $destdir=linkpage(IkiWiki::possibly_foolish_untaint(
|
|
|
|
attachment_location($form->field('page'))));
|
|
|
|
my $absdestdir=$config{srcdir}."/".$destdir;
|
2011-07-12 03:35:46 +02:00
|
|
|
my $destfile=IkiWiki::basename($filename);
|
2013-07-11 00:23:09 +02:00
|
|
|
my $dest=$absdestdir.$destfile;
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
unlink($dest);
|
2013-07-11 00:23:09 +02:00
|
|
|
IkiWiki::prep_writefile($destfile, $absdestdir);
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
rename($filename, $dest);
|
2013-07-11 00:23:09 +02:00
|
|
|
push @attachments, $destdir.$destfile;
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
}
|
|
|
|
return unless @attachments;
|
2011-06-14 20:44:20 +02:00
|
|
|
require IkiWiki::Render;
|
2012-04-07 18:52:29 +02:00
|
|
|
IkiWiki::prune($dir, $config{wikistatedir}."/attachments");
|
2011-06-14 19:06:59 +02:00
|
|
|
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
# Check the attachments in and trigger a wiki refresh.
|
2011-06-14 19:06:59 +02:00
|
|
|
if ($config{rcs}) {
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
IkiWiki::rcs_add($_) foreach @attachments;
|
2011-06-14 19:06:59 +02:00
|
|
|
IkiWiki::disable_commit_hook();
|
store attachments in holding area; commit to wiki on page save
This makes uploading a lot of attachments somewhat faster, because
the user does not need to wait for a long website refresh after each
upload. Still probably somewhat slow, since ikiwiki has to run for each
upload.
More importantly, this opens the door for integration of things like
the jquery file upload interface, which allow drag-n-drop and multiple
file uploads to be queued and then ran.
It uses rcs_commit_staged, which leaves out tla and mercurual which lack
that, but since rename, remove, autoindex, etc also use that, I think it's
fine for attachments to also depend on it.
The attachment list is currently broken; it does not look in the holding
area yet, and its links to the attached files won't work since they're not
yet in the wiki. previewing is also currently broken.
Work sponsored by TOVA.
2011-06-14 19:30:09 +02:00
|
|
|
IkiWiki::rcs_commit_staged(
|
2011-06-14 19:06:59 +02:00
|
|
|
message => gettext("attachment upload"),
|
|
|
|
session => $session,
|
|
|
|
);
|
|
|
|
IkiWiki::enable_commit_hook();
|
|
|
|
IkiWiki::rcs_update();
|
|
|
|
}
|
|
|
|
IkiWiki::refresh();
|
|
|
|
IkiWiki::saveindex();
|
|
|
|
}
|
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub attachment_location ($) {
|
2008-07-02 01:05:15 +02:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
# Put the attachment in a subdir of the page it's attached
|
2011-07-08 02:32:14 +02:00
|
|
|
# to, unless that page is the "index" page.
|
|
|
|
return "" if $page eq 'index';
|
2008-07-02 01:05:15 +02:00
|
|
|
$page.="/" if length $page;
|
|
|
|
|
|
|
|
return $page;
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-02 01:05:15 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub attachment_list ($) {
|
2008-07-02 01:05:15 +02:00
|
|
|
my $page=shift;
|
|
|
|
my $loc=attachment_location($page);
|
|
|
|
|
2011-06-14 21:07:34 +02:00
|
|
|
my $std=sub {
|
|
|
|
my $file=shift;
|
|
|
|
my $mtime=shift;
|
2011-06-15 21:21:59 +02:00
|
|
|
my $date=shift;
|
2011-06-14 21:07:34 +02:00
|
|
|
my $size=shift;
|
|
|
|
|
2011-06-15 21:21:59 +02:00
|
|
|
name => $file,
|
2011-06-14 21:07:34 +02:00
|
|
|
size => IkiWiki::Plugin::filecheck::humansize($size),
|
2011-06-15 21:21:59 +02:00
|
|
|
mtime => $date,
|
2011-06-14 21:07:34 +02:00
|
|
|
mtime_raw => $mtime,
|
|
|
|
};
|
|
|
|
|
2011-06-14 19:49:41 +02:00
|
|
|
# attachments already in the wiki
|
|
|
|
my %attachments;
|
2008-07-02 01:05:15 +02:00
|
|
|
foreach my $f (values %pagesources) {
|
2008-09-27 19:34:46 +02:00
|
|
|
if (! defined pagetype($f) &&
|
2010-06-12 20:29:56 +02:00
|
|
|
$f=~m/^\Q$loc\E[^\/]+$/) {
|
2011-06-14 19:49:41 +02:00
|
|
|
$attachments{$f}={
|
2011-06-15 21:21:59 +02:00
|
|
|
$std->($f, $IkiWiki::pagemtime{$f}, displaytime($IkiWiki::pagemtime{$f}), (stat($f))[7]),
|
2008-07-02 01:05:15 +02:00
|
|
|
link => htmllink($page, $page, $f, noimageinline => 1),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2011-06-14 19:49:41 +02:00
|
|
|
|
|
|
|
# attachments in holding directory
|
2011-06-14 21:47:47 +02:00
|
|
|
my $dir=attachment_holding_location($page);
|
2011-06-14 19:59:11 +02:00
|
|
|
my $heldmsg=gettext("this attachment is not yet saved");
|
2011-06-14 19:49:41 +02:00
|
|
|
foreach my $file (glob("$dir/*")) {
|
2012-01-15 21:39:13 +01:00
|
|
|
$file=Encode::decode_utf8($file);
|
2011-06-14 21:19:23 +02:00
|
|
|
next unless -f $file;
|
|
|
|
my $base=IkiWiki::basename($file);
|
|
|
|
my $f=$loc.$base;
|
2011-06-14 19:49:41 +02:00
|
|
|
$attachments{$f}={
|
2011-06-16 01:48:49 +02:00
|
|
|
$std->($f, (stat($file))[9]*2, stored_msg(), (stat(_))[7]),
|
2011-06-15 21:21:59 +02:00
|
|
|
link => $base,
|
2011-06-14 19:49:41 +02:00
|
|
|
}
|
|
|
|
}
|
2008-07-02 01:05:15 +02:00
|
|
|
|
2011-06-15 21:21:59 +02:00
|
|
|
# Sort newer attachments to the end of the list.
|
|
|
|
return sort { $a->{mtime_raw} <=> $b->{mtime_raw} || $a->{link} cmp $b->{link} }
|
2011-06-14 19:49:41 +02:00
|
|
|
values %attachments;
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-07-02 01:05:15 +02:00
|
|
|
|
2011-06-15 21:21:59 +02:00
|
|
|
sub stored_msg {
|
|
|
|
gettext("just uploaded");
|
|
|
|
}
|
|
|
|
|
improve detection of ajax request
Firefox sent an accept header for application/xml, not application/json,
and also weakened the priority to 0.8. So that stuff is not to be trusted;
instead I found a better way: When an ajax upload is *not* being made,
the Upload Attachment button will be used, so enable ajax if an upload
is being made without that button having been used.
Also, testing with firefox revealed it refused to process a response that
was type application/json, and checking the demo page for the jquery file
upload plugin, it actually returns the json with type text/html. Ugh.
Followed suite.
Now tested with: chromium, chromium (w/o js), firefox, firefox (w/o js),
and w3m.
2011-06-17 21:17:20 +02:00
|
|
|
sub json_response ($$$$) {
|
2011-06-16 19:01:23 +02:00
|
|
|
my $q=shift;
|
improve detection of ajax request
Firefox sent an accept header for application/xml, not application/json,
and also weakened the priority to 0.8. So that stuff is not to be trusted;
instead I found a better way: When an ajax upload is *not* being made,
the Upload Attachment button will be used, so enable ajax if an upload
is being made without that button having been used.
Also, testing with firefox revealed it refused to process a response that
was type application/json, and checking the demo page for the jquery file
upload plugin, it actually returns the json with type text/html. Ugh.
Followed suite.
Now tested with: chromium, chromium (w/o js), firefox, firefox (w/o js),
and w3m.
2011-06-17 21:17:20 +02:00
|
|
|
my $form=shift;
|
2011-06-16 19:01:23 +02:00
|
|
|
my $filename=shift;
|
|
|
|
my $stored_msg=shift;
|
|
|
|
|
improve detection of ajax request
Firefox sent an accept header for application/xml, not application/json,
and also weakened the priority to 0.8. So that stuff is not to be trusted;
instead I found a better way: When an ajax upload is *not* being made,
the Upload Attachment button will be used, so enable ajax if an upload
is being made without that button having been used.
Also, testing with firefox revealed it refused to process a response that
was type application/json, and checking the demo page for the jquery file
upload plugin, it actually returns the json with type text/html. Ugh.
Followed suite.
Now tested with: chromium, chromium (w/o js), firefox, firefox (w/o js),
and w3m.
2011-06-17 21:17:20 +02:00
|
|
|
if (! defined $form->submitted ||
|
|
|
|
$form->submitted ne "Upload Attachment") {
|
2011-06-16 19:01:23 +02:00
|
|
|
eval q{use JSON};
|
|
|
|
error $@ if $@;
|
improve detection of ajax request
Firefox sent an accept header for application/xml, not application/json,
and also weakened the priority to 0.8. So that stuff is not to be trusted;
instead I found a better way: When an ajax upload is *not* being made,
the Upload Attachment button will be used, so enable ajax if an upload
is being made without that button having been used.
Also, testing with firefox revealed it refused to process a response that
was type application/json, and checking the demo page for the jquery file
upload plugin, it actually returns the json with type text/html. Ugh.
Followed suite.
Now tested with: chromium, chromium (w/o js), firefox, firefox (w/o js),
and w3m.
2011-06-17 21:17:20 +02:00
|
|
|
print "Content-type: text/html\n\n";
|
2011-06-16 19:01:23 +02:00
|
|
|
my $size=-s $filename;
|
|
|
|
print to_json([
|
|
|
|
{
|
|
|
|
name => IkiWiki::basename($filename),
|
|
|
|
size => $size,
|
|
|
|
humansize => IkiWiki::Plugin::filecheck::humansize($size),
|
|
|
|
stored_msg => $stored_msg,
|
|
|
|
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-01 04:58:33 +02:00
|
|
|
1
|