| 1 | == Extension Point : ''IAttachmentManipulator'' == |
| 2 | |
| 3 | ||'''Interface'''||''IAttachmentManipulator''||'''Since'''||0.10|| |
| 4 | ||'''Module'''||''trac.attachment''||'''Source'''||[source:trunk/trac/attachment.py#/IAttachmentManipulator attachment.py]|| |
| 5 | |
| 6 | The ''IAttachmentManipulator'' can manipulate and validate attachments before saving. |
| 7 | |
| 8 | == Purpose == |
| 9 | |
| 10 | Trac allows users to attach arbitrary files to e.g. tickets or wiki pages. Plugins can hook into the attachment module to tweak the attachment saving process. |
| 11 | |
| 12 | The main purpose for this interface is to allow plugins to add new attachment validation rules. Attachments violating these rules are rejected. |
| 13 | |
| 14 | == Usage == |
| 15 | |
| 16 | Implementing the interface follows the standard guidelines found in [wiki:TracDev/ComponentArchitecture] and of course [wiki:TracDev/PluginDevelopment]. |
| 17 | |
| 18 | The `validate_attachment` method is called when a user adds a new attachment or replaces an existing attachment. Returning a list of messages rejects the attachment, returning `[]` accepts it. |
| 19 | |
| 20 | Note that currently there is no easy way to validate the attachment's file ''contents''. (See #9281) The `req` parameter contains a file object in `req.args['attachment''].file` that can be read from. (Make sure to `seek` back to `0` or only the remaining file content after the current file position may be stored.) |
| 21 | {{{#!python |
| 22 | if 'attachment' in req.args: |
| 23 | upload = req.args['attachment'] |
| 24 | try: |
| 25 | data = upload.file.read(self.sample_size) |
| 26 | if not is_binary(data): |
| 27 | content = to_unicode(data) |
| 28 | finally: |
| 29 | upload.file.seek(0) |
| 30 | filename = upload.filename |
| 31 | }}} |
| 32 | |
| 33 | The `prepare_attachment` method should always be implemented as an empty dummy method for compatibility reasons: |
| 34 | {{{#!python |
| 35 | def prepare_attachment(self, req, attachment, fields): |
| 36 | pass |
| 37 | }}} |
| 38 | |
| 39 | == Examples == |
| 40 | |
| 41 | A common use case for attachments is to attach patches to tickets. An open source project might require all such patches to be explicitly licensed under the BSD license. |
| 42 | The following minimal example IAttachmentManipulator implementation could enforce such a policy: |
| 43 | {{{#!python |
| 44 | from trac.core import Component, implements |
| 45 | from trac.attachment import IAttachmentManipulator |
| 46 | from trac.mimeview.api import get_mimetype |
| 47 | |
| 48 | class PatchLicenseChecker(Component): |
| 49 | implements(IAttachmentManipulator) |
| 50 | |
| 51 | def prepare_attachment(self, req, attachment, fields): |
| 52 | pass |
| 53 | |
| 54 | def validate_attachment(self, req, attachment): |
| 55 | mimetype = get_mimetype(attachment.filename) |
| 56 | if mimetype == 'text/x-diff' and \ |
| 57 | not attachment.description.contains('BSD'): |
| 58 | return [('description', "Patches must be released under BSD license")] |
| 59 | return [] |
| 60 | }}} |
| 61 | |
| 62 | == Available Implementations == |
| 63 | |
| 64 | * SpamFilter: Reject attachments that contain spam |
| 65 | * th:AttachFilterPlugin: Reject attachments by MIME type (guessed from file extension) |
| 66 | |
| 67 | == Additional Information and References == |
| 68 | |
| 69 | * [http://www.edgewall.org/docs/trac-trunk/epydoc/trac.attachment.IAttachmentManipulator-class.html epydoc] |
| 70 | * [http://www.edgewall.org/docs/trac-trunk/html/api/trac_attachment.html#trac.attachment.IAttachmentManipulator API Reference] |
| 71 | * See trac.attachment.IAttachmentChangeListener |
| 72 | * See trac.ticket.api.ITicketManipulator, trac.wiki.api.IWikiPageManipulator |
| 73 | * Introduced in changeset:3399 |
| 74 | * [TracDev/DatabaseSchema/Attachments Attachments database schema] |
| 75 | * Related tickets: |
| 76 | * [query:status!=closed&component=attachment attachment component] |
| 77 | * #6014 Pre-/Post-processing for compression, virus-check, etc. |
| 78 | * #9281 Easily accessing attachment data |
| 79 | * #10125 Discusses unused `prepare_attachment` method |
| 80 | * comment:15:ticket:10125 and following discuss ideas for fundamental refactoring |
| 81 | * #10353 Multiple error messages (Fixed in 1.0) |
| 82 | * comment:7:ticket:10353 and comment:8:ticket:10353 discuss ideas for attachment module refactoring |