Recent Changes - Search:

Cookbook

PmWiki

pmwiki.org

Attachtable

Summary: Actions to rename, delete & restore deleted attachments, as well as an attachlist replacement to use those actions and show file MIME types.
Version: 2007-11-28-2
Prerequisites: PmWiki 2.2.0-beta series, untested on 2.1.27 and earlier
Status: beta
Maintainer: EemeliAro
Categories: Uploads

Questions answered by this recipe

  • How can I rename attachments?
  • How can I delete attachments?
  • If I've deleted an attachment, how can I restore it or view it?
  • How can I make (:attachlist:) look prettier and provide more information?

Description

By default, renaming or deleting attached files isn't possible from within PmWiki. This recipe adds that functionality, as well as an undelete action, and a modified list of attachments to provide easy links to using these actions. A few extra bells and whistles are also provided.

Screenshot using (:attachtable data=all:), see below for the CSS

To install this recipe

  • download attachtable.phpΔ to your cookbook directory
  • add the following line to your configuration file:
include_once("$FarmD/cookbook/attachtable.php");

Usage

The directive (:attachtable:) accepts the same parameters as (:attachlist:) does, as well as some others, and generates a table rather than a list of attached files. It also has additional action links to delete ( X ) and rename/restore ( R ) files. Hover over the links for their tooltip explanations. These links are only visible if you have the required level of authorization (or have set otherwise, see below).

If you wish to use this recipe instead of the default attachment listing in the upload pages, edit the page Site.UploadQuickReference on your site and replace (:attachlist:) with (:attachtable:).

For full functionality, you'll need to have $EnableUploadVersions set on (not set by default). To do so, add the following to your configuration file before including attachtable.php:

$EnableUploadVersions=1;

By default, Attachtable actions require 'upload' authorization, except for deleting files from disk, which requires 'postattr' authorization. I picked 'postattr' because it's pretty much the highest level of authorization in a standard PmWiki. Authorization levels are customizable for all actions.

Deleting attachments - linked as X
If $EnableUploadVersions is set, deleting a file will first rename it to have a different extension (filename.ext,timestamp). Deleting such a "deleted" file will remove it from disk; this is confirmed using JavaScript, as it can't be undone.
Renaming & restoring attachments - linked as R
For the interactive prompt, you'll need to have JavaScript enabled (and not have $EnableAttachtableRename set to 0). If you have different size limits for different extensions, these will also be checked.

Viewing deleted files directly is also possible, with the proper MIME type and even if $EnableDirectDownload is set off.

Configuration

The following variables may be set in your config.php file to configure the way Attachtable works.

$AttachtableDataFields
default: array( 'size', 'modtime' )
The default data fields to display when not specified by a parameter to (:attachtable:). Valid entries are:
  • 'size' - File size in bytes
  • 'mimetype' - The MIME type of the file contents, if supported by your PHP engine
  • 'modtime' - Time when file contents were last modified. Due to the way attachments are handled in PmWiki, this is synonymous with the time when this version of this file was uploaded.
The order of these fields matters, as it defines the order in which they're displayed.
$HandleAuth array entries
See the source code for the different $HandleAuth definitions and set them to override the default authorization levels, eg. with $HandleAuth['delattach'] = $HandleAuth['postattr'];
These also define the visibility of the action links in the attachtable.
$AttachtableFileCheck
Custom file check function, undefined by default, see below for more information.

(:attachtable:)

(:attachtable:) shows a tabular list of attachments of the current group or page, depending on whether attachments are organised per group or per page. It accepts the same optional parameters as (:attachlist:) as well as some additional ones:

(:attachtable NAME:)
Shows the attachments of the group or page NAME.
(:attachtable *:)
Shows the uploads directory and permits browsing of all uploaded files by directory if $EnableDirectDownload is not set to 0.
(:attachtable ext=xxx:)
Specifies an extension for filtering by type of file. To list multiple extensions, use ext='xt1 xt2' or ext=xt1,xt2. Attachtable's ext option will also list deleted files of the specified type, unlike (:attachlist:).
(:attachtable data=default|all|none|size|mimetype|modtime:)
Select which data fields to show in the table.
  • Leaving this out or setting data=default will let $AttachtableDataFields determine the fields.
  • data=all will show all fields (in the order size,mimetype,modtime).
  • data=none only shows the file names.
  • Any combination of the other three will show those fields in the order specified, eg. data=mimetype,size will show the file names, then the MIME type and third the file sizes.
(:attachtable actions=default|all|none:)
Show or hide the actions associated with the attachments.
  • Leaving this out or setting actions=default will only show the actions that the user currently has permissions for.
  • Setting actions=all won't circumvent the permissions required for the actions, it'll just show the links.
  • actions=none will hide all the actions.
(:attachtable -titlerow:)
Hides the title row, which has explanations for the data columns.
(:attachtable -deleted:)
Hides deleted files.

Actions

If you'd rather use the actions directly, the format is as follows. For both, filename can already be marked as deleted.

?action=delattach&upname=filename
filename is deleted from disk or renamed to filename,timestamp, depending on $EnableUploadVersions and whether it's already marked as deleted
?action=renameattach&upname=filename&newname=newfilename
filename is renamed to newfilename
?action=downloaddeleted&upname=filename,timestamp
filename,timestamp, a deleted or overwritten file, is displayed with the correct MIME type

CSS

The above screenshot makes use of the following CSS to format the table:

.attachtable td { padding-right: 20px; }
.attachtable a { text-decoration: none; }
.attachtable a:hover { text-decoration: underline; }
.attachtable .del, .attachtable .del a { color: #cccccc; }
.attachtable .titlerow
	{
		color: #cccccc;
		font-style: italic;
		font-size: 0.8em;
	}

If you'd rather style it yourself, the table element has class='attachtable', the top row has class='titlerow' and deleted rows have class='del'. The action links have class='createlink'.

Notes

By default, Attachtable may relax your security settings slightly, as 'upload' access will now also grant read access to overwritten files, which access is not granted in a default PmWiki if $EnableDirectDownload is set to 0. If this is a concern, change the $HandleAuth definition for 'delattach' to whatever you need. 'postattr' access will also grant permission to delete attached files from disk when using Attachtable.

Attachtable's file restoration depends on PmWiki's versioning of overwritten files, where the file is renamed to "$filename,$Now" where $Now is a unix timestamp: an integer number of seconds since 1970. If you've changed some part of how PmWiki handles this, Attachtable may not work. Also important is the MakeUploadName function in upload.php, which by default strips commas from uploaded files and hence prevents naming uploads in a way that matches the pattern of a deleted file.

The rename/restore prompt and the deletion confirmation are done using JavaScript, but the actions themselves don't require it. Without JavaScript, the restore link will try to restore the file to its original name. Internet Explorer may prompt you for permission to open the prompt (though I can't understand why); there's very little I can do about this.

File verification when renaming files doesn't use the $UploadVerifyFunction function, but an internal function UploadVerifyRename that's based on the default UploadVerifyBasic function defined in upload.php.

Provided that $EnableDirectDownload is not set to 0, directories may show up in (:attachtable:) output, if using the * parameter or if directories exist in the uploads/NAME directory. Attachtable actions won't work on directories.

The file MIME types are found using a relatively robust process: first we try to use either mime_content_type or finfo_file; if these don't produce a decent result we try the shell command 'file -bi filename' and if that doesn't work we look up the extension in the $UploadExts array. I'm unable to test this on a non-Linux machine so I don't know if or how it'll fail in, say, a Windows server environment.

If you'd like to specify your own file check function, for example to implement a regular expression parser for filenames or to do more arcane things, you can specify a function and assign its name to the variable $AttachtableFileCheck. If such a function exists, it'll be called first to let it initialise any variables that it needs, then to check each file. You can use the following framework for defining the function:

$AttachtableFileCheck = 'MyFileCheck';
function MyFileCheck( $pagename, $file, $dir=FALSE, $opt=FALSE ) {
    // the use of the 'skip' parameter is completely optional
    ## $file is the file name
    ## defined only when initialising, $dir is the files' directory
    ## defined only when initialising, $opt is the ParseArgs output array
    static $skip = FALSE;
    if ($opt) {
        if ( @$opt['skip'] && ( $skip = $opt['skip'] ) ) { # note assignment
            // $skip here has the non-null string value that was passed to it 
            // using (:attachtable skip=...:)
        }
        // more initialisation code
    }

    if ( $skip && $file ) {
        // check that file is ok
    }

    return TRUE;
        // return indicates whether the file should (TRUE) 
        // or should not (FALSE) be listed
}

Features under consideration

  • non-JavaScript file rename prompt
  • remap links on wiki pages when renaming a file
  • attachtable sorting
  • internationalization
  • PITS 00273 Refcount for attachments
  • PITS 00331 display number of attachments for a page
  • PITS 00659 enhanced Attach button

Release Notes

  • 2007-11-28-2
    • external file check for Petko's skip
    • bugfix: -titlerow parameter now actually works
  • 2007-11-28
    • MIME types
    • rearrange columns
    • view deleted files
    • properly read authorization levels for action link display
    • no $EnableUploadOverwrite dependency
  • 2007-11-27
    • verify on rename
    • globals to disable parts
    • optional direct links to deleted files
    • handle directories better
  • 2007-11-26
    • file rename action
    • internal reworking
    • simplify: more parameters & no globals
  • 2007-11-25 - answering Petko's suggestions
    • by default, only show permitted actions
    • delete from disk
    • superscripted restore link
    • minor cleanup & bugfixes
  • 2007-11-24 - first release

See Also

Contributors

Comments

Hi. Thanks for this usefull recipe, I really needed this! I have two request for the deleted files. (1) Could you please change the link on the filename with a normal download link (or maybe better no link at all), and add two superscript commands like for the visible files: "r" to restore the file, and "x" to physically delete the deleted file from the directory. (2) The "x", "Δ" and "r" links, as well as the deleted file names should be displayed only to users with 'upload' rights. Thanks! --Petko November 24, 2007, at 09:58 AM

Done and updated as version 2007-11-25. Normal download links for removed attachments don't really work since the internal function MakeUploadName by default takes away the comma in the filename, so I just made the restore link a superscript R. If you need easier access to different file versions, you're talking about a different thing than Attachtable -- though it could be nice... --EemeliAro November 24, 2007, at 04:46 PM
Fantastic, thanks for the lightning fast reply! Wow. I also like very much the higher level of authorization for really deleting files. Excellent! (P.S. On sites with the default $EnableDirectDownload=1; it is possible to download a deleted file for review even if the server sends it as binary. But never mind, I am not sure if it will be really used. Thanks again.) --Petko November 24, 2007, at 05:16 PM
True, but I'm not convinced providing the link is a good thing; I'd say it's more likely to confuse. As an alternative, I've changed the restore action to prompt for an optionally different filename. --EemeliAro November 25, 2007, at 04:58 PM
... and now you can get direct links as well, if you want them, using $EnableAttachtableLinkDeleted. --EemeliAro November 27, 2007, at 06:08 AM
Thank you my friend. I tested the new version with the renames and it is excellent. --Petko November 27, 2007, at 09:18 AM
Don't seem to be able to stop fiddling with this. Direct links to deleted files now work, independent of $EnableDirectDownload and with the proper MIME types, so should display correctly in the browser. --EemeliAro November 27, 2007, at 06:01 PM
Excellent! This is the best solution. Thanks again! --Petko November 29, 2007, at 01:01 PM

I'm open to suggestions for how to improve this. More specifically, I'd be interested to hear about the following: --EemeliAro November 25, 2007, at 04:58 PM

  • What other information columns should there be?
  • Is there a need for more fine-tuned control of the action links?
  • Should the JavaScript prompts and confirmations be replaced by HTML pages?
I think the current features are great. We could hardly have another column of information, as PmWiki doesn't store any (like: who uploaded the file). I'd like to have a way to hide some files from the list, and this possibly to be configured in config.php and overridden in the wiki page. For example: $AttachtableSkipPattern = "/^th\\d+---/"; and (:attachtable skip="/^th\\d+---/":) will allow us to not display thumbnails created by ThumbList.[1] And skip=none to display all files. About the JavaScript: I believe it's fine. Most webmasters have decent browsers, and a JS prompt is very easy, fast and straightforward. Additionally, it is preventing search robots from messing with the attachments (for example, on completely open wikis). Thanks. --Petko November 27, 2007, at 09:54 AM
Hmmmm. File uploader information isn't necessarily impossible. PmWiki indeed doesn't store the info, but that just means it's a matter of modifying HandlePostUpload until it does. Also page histories could tell who and when first referred to an attachment, which is relatively synonymous to a file creation date. --EemeliAro November 27, 2007, at 06:01 PM
I like the skip idea, will see about implementing it. The JavaScript doesn't do anything about stopping spiders, as the links still have valid targets. If your wiki is so open that you let anyone have upload permission and you implement Attachtable, you really ought to require some authentication for the Attachtable actions. --EemeliAro November 27, 2007, at 06:01 PM
How about adding such a hook:
# added after "if ( @$matchext &&..."
if(function_exists(@$AttachtableFileCheck)
   && !$AttachtableFileCheck($file, $opt) ) continue;
   $filelist[$file] = $file; # current line 266
This will allow me to write the checking function. --Petko November 27, 2007, at 08:09 PM
Done, see above and source code as it's slightly different from what you suggested. --EemeliAro November 28, 2007, at 05:31 AM
Thanks, it works for me (the "static" variable may interfere if there are two attachtables in a page). --Petko November 29, 2007, at 01:01 PM
It shouldn't, as each is processed in turn, and each gets initialised before looping through the files. Hence provided your $AttachtableFileCheck doesn't assume the static variable is FALSE if the property you're looking for isn't in the (:attachtable:) directive. --EemeliAro November 29, 2007, at 02:17 PM

I have now this idea of implementing a parameter like list= in pagelists, and an array similar to $SearchPatterns which admins can define. May be much better and flexible than skip=. This could be a lot of work, I don't know yet, so unless you like it a lot and are impatient, I'll write it in a couple of days. :-) --Petko November 29, 2007, at 01:01 PM

Something like the pagelist list= is probably the right answer for this, but I haven't the time to implement it just now -- it'll probably be more than a week until I've next got time to look at the code that deeply again. So go ahead and implement it, if you want, and publish it here. Hopefully I'll have enough time tomorrow to polish up a new version, which can provide summary info and optionally ties together with your RecentUploadsLog. --EemeliAro November 29, 2007, at 02:17 PM
Ok, very good. Thanks. --Petko November 29, 2007, at 03:01 PM
Here it is - Demo. I talked with Patrick who suggested to do it this way (MakeName, list=default...) and that some day he will add such a function to PmWiki. It is brilliant now, really! (Removed the hooks that we added for the $AttachtableFileCheck, as the new way is more powerfull and fast.) Thanks! --Petko November 29, 2007, at 07:52 PM

I've modified Attachtable to use UserAuth to support specific page and group auth access i.e. <action>_group/page. You can download it here: attachtable_userauth.phpΔ //Aidin

Nice recipe, but I have one Question: I've added this recipe to our project wiki (http://crrcsim.sourceforge.net/wiki), but deleting files doesn't work. I don't seem to have delattach permissions (action link not displayed, only upload and rename) even when I'm logged in as admin. The wiki does not use any advanced auth mechanisms (AuthUser, UserAuth, ...), just definitions for the $DefaultPasswords admin, upload and attr. How do I gain "postattr" permissions? The PmWiki docs say nothing about it. --Jan R

Hi. Somehow I have had similar problems, so here is my local configuration:
$HandleAuth['deldelattach'] = 'admin';
$HandleAuth['delattach'] = 'upload';
$HandleAuth['renameattach'] = 'upload';
include_once("$FarmD/cookbook/attachtable.php");

This allows me to delete the "deleted" files as admin. Hope that helps. --Petko June 11, 2008, at 01:04 AM

Thanks a lot, that solved all my problems! This is exactly what I wanted. --Jan R

How would one go about changing the display of filesize from bytes to KB, or even to MB? thanks!

overtones99? June 18, 2008, at 06:08 PM

In the current version this is not possible; I could code this next week if Eemeli didn't do it in the meantime. --Petko June 24, 2008, at 05:57 PM
Sort of answered this and the following question on a post to the mailing list, but haven't actually implemented the code. Petko: feel free to code this if you've got the time and interest & add yourself as a recipe maintainer; I wouldn't actually mind you modifying the "official" attachtable.php either, as long as you keep me up to date. --EemeliAro June 25, 2008, at 05:08 PM
Thanks Eemeli! the code you pointed me to works! simply switch:
	   //$s .= '<td>'.number_format($stat['size']).'</td>';   /// original this is where the byte size is created/calculated
	   $s .= '<td>'.bytesToNBytesFunc($stat['size']).'</td>';   /// *** call func to convert to KB
... and changed the code from the PHP site to make it "American" style (decimals instead of commas):
         /// from http://php.net/manual/en/function.number-format.php#72969
         function bytesToNBFunc($a) {
             $unim = array("B","KB","MB","GB","TB","PB");
             $c = 0;
             while ($a>=1024) {
                 $c++;
                 $a = $a/1024;
             }
             //return number_format($a,($c ? 2 : 0),",",".")." ".$unim[$c];
             return number_format($a,($c ? 1 : 0))." ".$unim[$c];  // using decimals instead of commas, 
                                                                        and only 1 decimal point...
         }
works great. thanks for the suggestion. overtones99? June 25, 2008, at 08:15 PM

Hi. How can I prevent attachtable from redirecting to the confirmation on Group.Page?action=upload..., and instead just go back to the page where I was uploading from (in this case, Group/Uploads)? Even better, I'd love to be able to have an options field like this:

 (:attachtable MyGroup.MyUploadPage
redirect=MyGroup.MyUploadPage#currentUploads:)

Is something like this possible? Thanks, overtones99? June 22, 2008, at 04:58 PM

In the current version this is not possible; there are a number of actions (uploading, deleting, renaming, replacing a file...) which issue a redirect to the uploads form and list -- after which of these actions you need to redirect elsewhere? --Petko June 24, 2008, at 05:57 PM
Note that you may find Attachtable extremely useful if you place it below the uploads form, in the page "Site.UploadsQuickReference" on your wiki, replacing the Attachlist markup. This way it will show on all your uploads pages, and it is maybe what you need. --Petko June 24, 2008, at 06:04 PM
Hi. I guess in my situation I've been using attachtable on a Group/Uploads page (each user has their own group and uploads page), which employs a couple modified versions of the uploadform recipe... problem i'm having is the confirmation page that you get... but i figured a way out of my predicament (minus the confirmation):
        // *** Prevent confirmation page - Placed in both deleteattach and renameattach functions ***//
	//Redirect($pagename,"{\$PageUrl}?action=upload&uprname=$upname&upresult=$result");

	if(stristr($pagename,"Uploads")) { // skip uploads page, and redirect right back to page's uploads	
                // good if upload list is at the bottom of the page
		Redirect( $pagename, "{\$PageUrl}#currentUploads" ); 
	} else { // DEFAULT ACTION
		Redirect( $pagename, "{\$PageUrl}?action=upload&uprname=$upname&$result" ); // original redirect
	}
my only suggestion was that it my be nice to have a 'redirect' option where redirect=1 or by default uses the default confirmation page... and 'redirect=$PageUrl#currentUploads' goes to where you want after uploading
overtones99? June 25, 2008, at 09:27 PM
Edit - History - Print - Recent Changes - Search
Page last modified on June 25, 2008, at 09:30 PM