Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Finally this is productive now :-) -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
[Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
The proposal to merge lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website has been updated. Status: Needs review => Merged For more details, see: https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 -- Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Manx thanks :) I wait only for janus to approve the changes regarding python3. He will look at it next weekend. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Review: Approve I have tested map upload and attaching to forum. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Review: Resubmit -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Finally i got it (hopefully) Please check again on alpha... https://alpha.widelands.org/ -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Review: Needs Fixing Thanks :-) But the check for clamdscan doesn't work on the server... i know why, but i don't know the underlying cause. Will talk on IRC about that issue when i have some more time. Just found that map uploading is broken with the changes in this branch. So the code for map uploading needs adapting too... -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Stupid me. :-) I installed clamdscan. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
How do you intend to access clamav? The current mode is via socket: LocalSocket /var/run/clamav/clamd.ctl If you'd like, I can add a local TCP daemon on port 3310. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
@Toni: Can we have the package 'clamdscan' installed? For some reason it is a recommended package for clamd and we do not install recommended packages by default. Or is clamd configured to have on-access-scanning enabled? Didn't saw that it is configured like that. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
> I also wonder whether we should disallow map files - it might come in handy > if somebody wants some feedback before publishing to the maps section. I just don't want to have map files in the forum. I 'fear' most (new) users will upload a map in the forum instead in the 'right' place. A Feedback can also be done in the map comments, or by linking a map in the forum and ask there for a feedback. Once there is a fix for bug 357914 'Allow submitters of maps to upload new versions' get implement, it should be fine to not allow maps in forum. But of course we can remove that part of code and if we get in trouble we can add it again. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
1 tiny nit. I also wonder whether we should disallow map files - it might come in handy if somebody wants some feedback before publishing to the maps section. Diff comments: > > === modified file 'pybb/util.py' > --- pybb/util.py 2019-04-11 15:20:33 + > +++ pybb/util.py 2019-08-15 08:32:18 + > @@ -173,3 +180,144 @@ > text = text.replace('', '"') > text = text.replace('', '\'') > return text > + > + > +def validate_file(attachment): > + > +tmp_file_path = attachment.temporary_file_path() > + > +# Helper functions > +def _split_mime(mime_type): > +main, sub = mime_type.split('/', maxsplit=1) > +return {'maintype': main, 'subtype': sub} > + > +def _is_image(): > +# Use PIL to determine if it is a valid image file > +# works not for corrupted jpg > +try: > +with Image.open(tmp_file_path) as im: > +im.verify() > +except: > +return False > +return True > + > +def _is_zip(): > +try: > +zip_obj = zipfile.ZipFile(tmp_file_path) > +except zipfile.BadZipfile: > +return None > +return zip_obj > + > +def _zip_contains(zip_parts): > +# Check if each entry in zip_parts is inside the attachment > +zip_obj = _is_zip() > +if zip_obj: > +try: > +for obj in zip_parts: > +zip_obj.getinfo(obj) > +except KeyError: > +return False > +return True > + > + > +# Main part of file checks > +# File size > +if attachment.size > pybb_settings.ATTACHMENT_SIZE_LIMIT: > +raise ValidationError( > +'Attachment is too big. We allow max %(size)s Mb', Megabit or megabyte? > +params = { > +'size': pybb_settings.ATTACHMENT_SIZE_LIMIT/1024/1024, > +} > +) > + > +# Checks by file extension > +splitted_fn = attachment.name.rsplit('.', maxsplit=2) > +if len(splitted_fn) == 1: > +raise ValidationError( > +'We do not allow uploading files without an extension.' > +) > + > +ext = splitted_fn[-1] > +if not ext in settings.ALLOWED_EXTENSIONS: > +raise ValidationError( > +'This type of file is not allowed.' > +) > + > +# Widelands map file > +if ext == 'wmf': > +raise ValidationError( > +'This seems to be a widelands map file. Please upload \ > +it at our maps section.' > +) > + > +# Widelands savegame (*.wgf) and widelands replay (*.wrpl.wgf) > +# are not the same. > +if ext == 'wgf' and not splitted_fn[-2] == 'wrpl': > +if not _zip_contains(settings.WGF_CONTENT_CHECK): > +raise ValidationError( > +'This is not a valid widelands savegame.' > +) > + > +# Widelands replay > +if ext == 'wrpl': > +raise ValidationError( > +'This file is part of a replay. Please zip it together with \ > +the corresponding .wrpl.wgf file and upload again.' > +) > + > +if ext == 'zip': > +if _is_zip() == None: > +raise ValidationError( > +'This is not a valid zip file.' > +) > + > +# Widelands AI configuration > +if ext == 'wai': > +wai = configparser.ConfigParser() > +try: > +wai.read(tmp_file_path) > +wai_sections = wai.sections() > +if len(settings.ALLOWED_WAI_SECTIONS) == len(wai_sections): > +for section in settings.ALLOWED_WAI_SECTIONS: > +if section not in wai_sections: > +raise > +else: > +raise > +except: > +raise ValidationError( > +'This not a valid wai file.' > +) > + > +# Checks by MimeType > +# Get MIME-Type from python-magic > +magic_mime = magic.from_file(tmp_file_path, mime=True) > +magic_mime = _split_mime(magic_mime) > +send_mime = _split_mime(attachment.content_type) > + > +# Check for valid image file. Use te mime-type provided by python-magic, > +# because for a renamed image the wrong mime-type is send by the browser. > +if magic_mime['maintype'] == 'image': > +if not _is_image(): > +raise ValidationError( > +'This is not a valid image: %(file)s', > +params={'file': attachment.name} > +) > + > +# Compare Mime type send by browser and Mime type from python-magic. > +# We only compare the main type (the first part) because the second > +# part may not be recoginzed correctly. E.g. for .lua the submitted > +# type is 'text/x-lua' but 'x-lua' is not official at all. See: > +# https://www.iana.org/assignments/media-types/media-types.xhtml > +# Unrecoginzed extension
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Already installed. ;) -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
stonerl, can you install and configure clamav on the server, please? The current branch implemented a check with clamdscan, which needs a clamav daemon. We can also stick with clamscan, which can be run on demand, but this much slow: A file check last 55 sec. on my machine, whereas clamdscan usually needs only 0,1 sec. The current branch is not running on alpha, yet. Since i am afk for some some days, i'll shut down alpha now. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Review: Resubmit I have to stop working on this, other wise i fear to change many other things :-D Anyway i think this works. wai files need some special treatment though. Please test on alpha: https://alpha.widelands.org/ -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is subscribed to branch lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
> Other extensions that we're using for Widelands & that might be interesting: > .wai - AI Ok > .wmf - Map I forgot to mention: If the extension is wmf, an errormessage is shown: "This seems to be a widelands map file. Please upload it at our maps section." > .wrpl - Replay - useless with the accompanying .wgf though. I am planning to make a wikipage describing, beside other things, the usage of replays, e.g. they have to be zipped together before uploading and link that wikipage in the upload form. But i have to check for .wrpl.wgf. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
2. I have no opinion on this at this time. Maybe 10 or 20? We can easily change the value if it becomes a problem. > Files without extension aren't allowed (can be problematic e.g. with the > campvis file) campvis will be replaced by campaigns.conf for the next version, so don't worry about it - we can allow .conf Other extensions that we're using for Widelands & that might be interesting: .wai - AI .wmf - Map .wrpl - Replay - useless with the accompanying .wgf though. > Do we need a check for each allowed extension? Since attachments are marked for download anyway, I'd say that checking for those that are easily checked will do for now. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
I am a bit lost here... Some checks are made now, but i am unsure if we need them all. What is implemented: 1. Link of Attachment: If a user clicks on a link of an attachment, he will be ever prompted for a download (or to open the file with an associated program), even if it is a file which the browser may can display, e.g. an image (png, jpg) or text file. This is not optimal, but i think it is more secure. 2. Restricting upload permission A user has only permission to upload files, if he has had written 5 posts prior. The number of 5 derives from MAX_HIDDEN_POST at the moment, but i think it's better to have an own value for this. What number do we want? 3. Allowed extensions: Added a list: ALLOWED_EXTENSIONS = ['wgf', 'jpg', 'jpeg', 'gif', 'png', 'ogg', 'lua', 'ods', 'zip', 'json', 'txt', 'csv'] I am unsure if this list will be ever complete. E.g. some may want to upload some other types of files (e.g. py, odg, doc, ...) 4. Extension handling: - Files without extension aren't allowed (can be problematic e.g. with the campvis file) - For 'wgf' files: Check if some base entries can be found (e.g. '/binary/' or '/minimap.png') - For image files: Check if this is really an image using the Pillow library. This finds corrupted .png but not corrupted .jpg Do we need a check for each allowed extension? 5. Comparing Mime-Types: When uploading a file, a Mime-Type (content-type) is also submitted. The submitted mime-type is mostly derived from the extension of the file. E.g. if you rename a file from 'image.png' to 'image.txt' the OS (or browser) sends the Mime-type 'text/plain', which is obviously wrong. To prevent such mime-type mismatch, a check is made which compares the sent mime-type with the mime-type derived from python-magic. e.g. python magic will show for 'image.txt' the mime-type 'image/png'. As said, i am a bit lost, not really knowing if we need all this checks, or if they are enough at all :-S Any opinions? -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
> Everyone can rename 'image.js' into 'image.png'... That's true. It would still be an advantage though if the browser then doesn't execute it. Doing a full validation too is definitely a better idea. > What about restricting uploads to users who have written x posts prior? Also a good idea -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Currently there is no restriction on file types. The problem is that a file may not contain what the extension says it should be. Everyone can rename 'image.js' into 'image.png'... A list of allowed extension do not suffer. I'll try to implement some checks for validating a files type and probably an 'allowed extension list'. What about restricting uploads to users who have written x posts prior? From my side this can be implemented. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
Code LGTM. Do we have a restriction on file types? We won't want people to upload malicious JavaScript ans stuff lie that, so we should have a list of legal file extensions at least. -- https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. ___ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp
[Widelands-dev] [Merge] lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website
kaputtnik has proposed merging lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. Commit message: Allow attachments in the forum Requested reviews: Widelands Developers (widelands-dev) Related bugs: Bug #964452 in Widelands Website: "Suggestion: Allow uploads to the site" https://bugs.launchpad.net/widelands-website/+bug/964452 Bug #1833658 in Widelands Website: "Create a possibility to upload tournament replay" https://bugs.launchpad.net/widelands-website/+bug/1833658 For more details, see: https://code.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/+merge/370342 Made attachments python3 compatible: https://bazaar.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/revision/545 Set allowed file size to 5 Mb (as we have for nginx) Delete attachment when deleting a post: https://bazaar.launchpad.net/~widelands-dev/widelands-website/pybb_attachments/revision/548 Added template for showing attachments. Style tweaks, example: https://bugs.launchpad.net/widelands-website/+bug/964452/+attachment/5277903/+files/attachments_1.png Autoreload css for the users if this got merged, so the users don't have to hit CTRL+F5 I'll do some explanations in the wiki and announce this change. Probably with the option to remove it again if we get too many problematic attachments. -- Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/pybb_attachments into lp:widelands-website. === modified file 'mainpage/settings.py' --- mainpage/settings.py 2019-04-11 16:11:21 + +++ mainpage/settings.py 2019-07-18 20:25:31 + @@ -191,7 +191,8 @@ # Pybb Configuration # ## # See also pybb defaults in pybb.settings.py -PYBB_ATTACHMENT_ENABLE = False # disable gzip middleware when enabling attachments +PYBB_ATTACHMENT_ENABLE = True +PYBB_ATTACHMENT_SIZE_LIMIT = 1024*1024*5 #5MB PYBB_DEFAULT_MARKUP = 'markdown' INTERNAL_PERM='pybb.can_access_internal' # The permission string derived from pybb.models.category === modified file 'pybb/forms.py' --- pybb/forms.py 2019-03-20 21:32:32 + +++ pybb/forms.py 2019-07-18 20:25:31 + @@ -1,6 +1,6 @@ import re from datetime import datetime -import os.path +import os from django import forms from django.conf import settings @@ -69,9 +69,15 @@ name=memfile.name, post=post) dir = os.path.join(settings.MEDIA_ROOT, pybb_settings.ATTACHMENT_UPLOAD_TO) -fname = '%d.0' % post.id +if not os.path.exists(dir): +os.makedirs(dir) + +fname = '{}.0'.format(post.id) path = os.path.join(dir, fname) -file(path, 'w').write(memfile.read()) + +with open(path, 'wb') as f: +f.write(memfile.read()) + obj.path = fname obj.save() === modified file 'pybb/models.py' --- pybb/models.py 2019-04-11 15:20:33 + +++ pybb/models.py 2019-07-18 20:25:31 + @@ -345,6 +345,11 @@ def delete(self, *args, **kwargs): self_id = self.id head_post_id = self.topic.posts.order_by('created')[0].id + +if self.attachments.all(): +for attach in self.attachments.all(): +attach.delete() + super(Post, self).delete(*args, **kwargs) self.topic.save() @@ -398,7 +403,7 @@ super(Attachment, self).save(*args, **kwargs) if not self.hash: self.hash = hashlib.sha1( -str(self.id) + settings.SECRET_KEY).hexdigest() +str(self.id).encode('utf-8') + settings.SECRET_KEY.encode('utf-8')).hexdigest() super(Attachment, self).save(*args, **kwargs) def __str__(self): @@ -407,19 +412,13 @@ def get_absolute_url(self): return reverse('pybb_attachment', args=[self.hash]) -def size_display(self): -size = self.size -if size < 1024: -return '%b' % size -elif size < 1024 * 1024: -return '%dKb' % int(size / 1024) -else: -return '%.2fMb' % (size / float(1024 * 1024)) - def get_absolute_path(self): return os.path.join(settings.MEDIA_ROOT, pybb_settings.ATTACHMENT_UPLOAD_TO, self.path) +def delete(self, *args, **kwargs): +os.remove(self.get_absolute_path()) +super(Attachment, self).delete(*args, **kwargs) if notification is not None: signals.post_save.connect(notification.handle_observations, sender=Post) === modified file 'pybb/static/css/forum.css' --- pybb/static/css/forum.css 2019-02-28 16:09:16 + +++ pybb/static/css/forum.css 2019-07-18 20:25:31 + @@ -132,6 +132,10 @@ border: 1px solid #47; } +.attachment { + display: inline-block +} + /*/ /* Edit/add Post */ /* related */ === modified file 'pybb/template