diff --git a/.gitignore b/.gitignore
index 17bf7be..4b49871 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,4 +23,3 @@ output.xml
include/
lib/
pip-selfcheck.json
-buildout.cfg
diff --git a/.travis.yml b/.travis.yml
index 4f60eda..2b333bc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,17 +4,16 @@ sudo: false
cache:
pip: true
directories:
- - $HOME/buildout-cache
+ - eggs
env:
# - PLONE_VERSION=4.3.x
- PLONE_VERSION=5.0.x
-before_install:
- - mkdir -p $HOME/buildout-cache/{eggs,downloads}
- - virtualenv .
- - bin/pip install --upgrade pip setuptools zc.buildout
+ - PLONE_VERSION=5.1.x
install:
- - sed -ie "s#plone-x.x.x.cfg#plone-$PLONE_VERSION.cfg#" travis.cfg
- - bin/buildout -N -t 3 -c travis.cfg
+ - virtualenv -p `which python` .
+ - bin/pip install -r requirements.txt
+ - sed -ie "s#test-5.1.x#test-$PLONE_VERSION#" buildout.cfg
+ - bin/buildout -N -t 5
script:
- bin/code-analysis
- bin/test
diff --git a/base.cfg b/buildout.cfg
similarity index 69%
rename from base.cfg
rename to buildout.cfg
index d65f9d0..1f70cdd 100644
--- a/base.cfg
+++ b/buildout.cfg
@@ -1,34 +1,19 @@
[buildout]
+extends=
+ https://raw.github.com/collective/buildout.plonetest/master/test-5.1.x.cfg
+ versions.cfg
+
extensions = mr.developer
-parts =
- instance
- test
+
+package-name = collective.limitfilesizepanel
+package-extras = [test]
+
+parts +=
coverage
test-coverage
code-analysis
dependencychecker
-develop = .
-sources-dir = extras
-auto-checkout =
-
-[instance]
-recipe = plone.recipe.zope2instance
-user = admin:admin
-http-address = 8080
-eggs =
- Plone
- Pillow
- plone.app.debugtoolbar
- collective.limitfilesizepanel[test]
-
-[test]
-recipe = zc.recipe.testrunner
-eggs = ${instance:eggs}
-initialization =
- os.environ['TZ'] = 'UTC'
-defaults = ['-s', 'collective.limitfilesizepanel', '--auto-color', '--auto-progress']
-
[coverage]
recipe = zc.recipe.egg
eggs = coverage
diff --git a/collective/limitfilesizepanel/browser/configure.zcml b/collective/limitfilesizepanel/browser/configure.zcml
index 7ec00d5..2175581 100644
--- a/collective/limitfilesizepanel/browser/configure.zcml
+++ b/collective/limitfilesizepanel/browser/configure.zcml
@@ -2,6 +2,7 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:plone="http://namespaces.plone.org/plone"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="collective.limitfilesizepanel">
@@ -14,6 +15,7 @@
name="limitfilesize-settings"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".controlpanel.LimitFileSizeControlPanel"
+ layer="collective.limitfilesizepanel.interfaces.ILimitFileSizePanelLayer"
permission="collective.limitfilesizepanel.LimitFileSizePanel"
/>
@@ -25,4 +27,13 @@
layer="collective.limitfilesizepanel.interfaces.ILimitFileSizePanelLayer"
allowed_interface=".limitfilesizepanel_view.IHelpersView"
/>
+
+
diff --git a/collective/limitfilesizepanel/browser/limitfilesizepanel_view.py b/collective/limitfilesizepanel/browser/limitfilesizepanel_view.py
index f24c2e3..f70ebe2 100644
--- a/collective/limitfilesizepanel/browser/limitfilesizepanel_view.py
+++ b/collective/limitfilesizepanel/browser/limitfilesizepanel_view.py
@@ -1,13 +1,16 @@
# -*- coding: utf-8 -*-
-from AccessControl import getSecurityManager
from Acquisition import aq_base
+from collective.limitfilesizepanel import messageFactory as _
from collective.limitfilesizepanel.interfaces import ILimitFileSizePanel
from plone import api
from plone.api.exc import InvalidParameterError
from Products.Five.browser import BrowserView
-from zope.interface import implements
+from Products.validation.i18n import safe_unicode
+from zope.i18n import translate
+from zope.interface import implementer
from zope.interface import Interface
from ZPublisher.HTTPRequest import FileUpload
+
try:
from plone.namedfile.interfaces import INamedBlobImageField
from plone.namedfile.interfaces import INamedBlobFileField
@@ -24,6 +27,9 @@ def checkSize(uploadfile, maxsize):
def canBypassValidation():
"""Check if the user has bypass permission"""
+ def newDataOnly():
+ """ Return if the validation is only for new data """
+
def get_maxsize(validator, field, **kwargs):
"""
This is the method called from AT validator
@@ -42,11 +48,18 @@ def get_maxsize_tiny(metatypes):
"""
+@implementer(IHelpersView)
class View(BrowserView):
- '''
+ """
Helper view for file uploads
- '''
- implements(IHelpersView)
+ """
+
+ def newDataOnly(self):
+ """
+ """
+ return api.portal.get_registry_record(
+ 'new_data_only',
+ interface=ILimitFileSizePanel)
def check_size_dx(self, uploadfile, maxsize):
""" check the size of given file """
@@ -56,28 +69,32 @@ def check_size_dx(self, uploadfile, maxsize):
}
if self.canBypassValidation():
return result
-
- new_data_only = api.portal.get_registry_record(
- 'new_data_only',
- interface=ILimitFileSizePanel)
-
- if new_data_only and self.context != api.portal.get():
- # we are in edit, and we don't want validate uploaded files.
- return result
-
- size = float(uploadfile.getSize())
+ if (isinstance(uploadfile, FileUpload) or hasattr(aq_base(uploadfile), 'tell')): # NOQA
+ uploadfile.seek(0, 2) # eof
+ size = float(uploadfile.tell())
+ uploadfile.seek(0)
+ else:
+ size = float(uploadfile.getSize())
sizeMB = (size / (1024 * 1024))
result['sizeMB'] = sizeMB
-
if sizeMB > maxsize:
result['valid'] = False
+ msg = _(
+ 'validation_error',
+ default=u'Validation failed. Uploaded data is too large:'
+ u' ${size}MB (max ${max}MB)',
+ mapping={
+ 'size': safe_unicode('{0:.1f}'.format(sizeMB)),
+ 'max': safe_unicode('{0:.1f}'.format(maxsize))
+ })
+ result['error'] = translate(msg, context=self.request)
return result
def check_size(self, uploadfile, maxsize):
""" check the size of given file """
result = {
'maxsize': maxsize,
- 'valid': True
+ 'valid': True,
}
if self.canBypassValidation():
@@ -108,14 +125,24 @@ def check_size(self, uploadfile, maxsize):
if sizeMB > maxsize:
result['valid'] = False
+ msg = _(
+ 'validation_error',
+ default=u'Validation failed. Uploaded data is too large:'
+ u' ${size}MB (max ${max}MB)',
+ mapping={
+ 'size': safe_unicode('{0:.1f}'.format(sizeMB)),
+ 'max': safe_unicode('{0:.1f}'.format(maxsize))
+ })
+ result['error'] = translate(msg, context=self.request)
return result
def canBypassValidation(self):
"""Check if the user has bypass permission"""
- sm = getSecurityManager()
- return sm.checkPermission(
- "collective.limitfilesizepanel: Bypass limit size", self.context)
+ return api.user.has_permission(
+ 'collective.limitfilesizepanel: Bypass limit size',
+ obj=self.context
+ )
def _get_type_maxsize(self, field, context):
"""Get portal_type/fieldname pair configuration in the registry"""
@@ -201,9 +228,9 @@ def get_maxsize(self, validator, **kwargs):
# get original max size
if 'maxsize' in kwargs:
maxsize = kwargs.get('maxsize')
- elif hasattr(aq_base(instance), 'getMaxSizeFor'):
+ elif hasattr(aq_base(instance), 'getMaxSizeFor'): # noqa
maxsize = instance.getMaxSizeFor(field.getName())
- elif hasattr(field, 'maxsize'):
+ elif hasattr(field, 'maxsize'): # noqa
maxsize = field.maxsize
else:
# set to given default value (default defaults to 0)
diff --git a/collective/limitfilesizepanel/browser/tinymce_upload_p5.py b/collective/limitfilesizepanel/browser/tinymce_upload_p5.py
new file mode 100644
index 0000000..a9691fb
--- /dev/null
+++ b/collective/limitfilesizepanel/browser/tinymce_upload_p5.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+from plone import api
+from plone.app.content.browser.file import FileUploadView as BaseFileUploadView
+
+import mimetypes
+
+
+class FileUpload(BaseFileUploadView):
+ """
+ add filesize validation to tinymce file upload view
+ """
+
+ def __call__(self):
+ filedata = self.request.form.get('file', None)
+ if not filedata:
+ return super(FileUpload, self).__call__()
+ filename = filedata.filename
+ content_type = mimetypes.guess_type(filename)[0] or ''
+ ctr = api.portal.get_tool(name='content_type_registry')
+ portal_type = ctr.findTypeName(
+ filename.lower(), content_type, '') or 'File'
+
+ helper_view = api.content.get_view(
+ name='lfsp_helpers_view',
+ context=self.context,
+ request=self.context.REQUEST,)
+
+ if helper_view.newDataOnly() and '/edit' in self.request.get('HTTP_REFERER'): # noqa
+ return super(FileUpload, self).__call__()
+ maxsize = helper_view.get_maxsize_tiny((portal_type,))
+ if not maxsize:
+ return super(FileUpload, self).__call__()
+
+ size_check = helper_view.check_size_dx(
+ maxsize=maxsize,
+ uploadfile=filedata
+ )
+ if size_check and not size_check.get('valid', False):
+ response = self.request.RESPONSE
+ response.setStatus(403)
+ return size_check.get('error', '')
+ return super(FileUpload, self).__call__()
diff --git a/collective/limitfilesizepanel/configure.zcml b/collective/limitfilesizepanel/configure.zcml
index ebb1413..8e70da0 100644
--- a/collective/limitfilesizepanel/configure.zcml
+++ b/collective/limitfilesizepanel/configure.zcml
@@ -79,7 +79,8 @@
/>
-
+
+
diff --git a/collective/limitfilesizepanel/dx_validators.py b/collective/limitfilesizepanel/dx_validators.py
index 49b1b6d..37b26db 100644
--- a/collective/limitfilesizepanel/dx_validators.py
+++ b/collective/limitfilesizepanel/dx_validators.py
@@ -1,13 +1,11 @@
# -*- coding: utf-8 -*-
-from Products.validation.i18n import safe_unicode
from plone.namedfile.interfaces import INamedBlobImageField
from plone.namedfile.interfaces import INamedBlobFileField
-from collective.limitfilesizepanel import messageFactory as _
from zope.interface import Invalid
from z3c.form import validator
from plone import api
from plone.api.exc import InvalidParameterError
-from zope.i18n import translate
+from plone.dexterity.browser.edit import DefaultEditForm
class DXFileSizeValidator(validator.FileUploadValidator):
@@ -18,7 +16,10 @@ class DXFileSizeValidator(validator.FileUploadValidator):
def validate(self, value):
super(DXFileSizeValidator, self).validate(value)
if not value:
- return
+ return True
+
+ if isinstance(self.view, DefaultEditForm):
+ return True
try:
helper_view = api.content.get_view(
name='lfsp_helpers_view',
@@ -27,10 +28,13 @@ def validate(self, value):
)
except InvalidParameterError:
# the view is enabled only when the product is installed
- return
- if helper_view.canBypassValidation():
return True
- maxsize = helper_view.get_maxsize_dx(self, self.field)
+ if helper_view.newDataOnly() and isinstance(self.view, DefaultEditForm): # noqa
+ return True
+ maxsize = helper_view.get_maxsize_dx(
+ validator=self,
+ field=self.field
+ )
if not maxsize:
return True
@@ -39,20 +43,20 @@ def validate(self, value):
uploadfile=value)
if size_check and not size_check.get('valid', False):
- msg = _(
- 'validation_error',
- default=u"Validation failed. Uploaded data is too large:"
- u" ${size}MB (max ${max}MB)",
- mapping={
- 'size': safe_unicode("%.1f" % size_check.get('sizeMB')),
- 'max': safe_unicode("%.1f" % size_check.get('maxsize'))
- })
- raise Invalid(translate(msg, context=self.context.REQUEST))
+ raise Invalid(size_check.get('error', ''))
return True
-validator.WidgetValidatorDiscriminators(DXFileSizeValidator,
+class ImageFileSizeValidator(DXFileSizeValidator):
+ """ """
+
+
+class FileSizeValidator(DXFileSizeValidator):
+ """ """
+
+
+validator.WidgetValidatorDiscriminators(ImageFileSizeValidator,
field=INamedBlobImageField)
-validator.WidgetValidatorDiscriminators(DXFileSizeValidator,
+validator.WidgetValidatorDiscriminators(FileSizeValidator,
field=INamedBlobFileField)
diff --git a/collective/limitfilesizepanel/overrides.zcml b/collective/limitfilesizepanel/overrides.zcml
index c640efb..9faec37 100644
--- a/collective/limitfilesizepanel/overrides.zcml
+++ b/collective/limitfilesizepanel/overrides.zcml
@@ -23,12 +23,12 @@
diff --git a/collective/limitfilesizepanel/tinymce_upload.py b/collective/limitfilesizepanel/tinymce_upload_p4.py
similarity index 99%
rename from collective/limitfilesizepanel/tinymce_upload.py
rename to collective/limitfilesizepanel/tinymce_upload_p4.py
index daae22b..544d642 100644
--- a/collective/limitfilesizepanel/tinymce_upload.py
+++ b/collective/limitfilesizepanel/tinymce_upload_p4.py
@@ -10,6 +10,8 @@
from Products.TinyMCE.adapters.Upload import Upload as BaseUpload
from Products.validation.i18n import safe_unicode
from zExceptions import BadRequest
+
+import logging
import pkg_resources
try:
@@ -28,12 +30,14 @@
from zope.i18nmessageid import MessageFactory
_ = MessageFactory('plone.tinymce')
-import logging
+
logger = logging.getLogger(__name__)
class Upload(BaseUpload):
-
+ """
+ P4 patch
+ """
def upload(self): # NOQA
"""Adds uploaded file"""
context = aq_inner(self.context)
diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst
index a2f5250..bc48324 100644
--- a/docs/HISTORY.rst
+++ b/docs/HISTORY.rst
@@ -1,10 +1,13 @@
Changelog
=========
-2.0.4 (unreleased)
+2.1.0 (unreleased)
------------------
-- Nothing changed yet.
+- Fix validators for Dexterity fields. Now works well with Files and images
+ [cekk]
+- Add support for Tinymce validation also for Plone 5
+ [cekk]
2.0.3 (2018-01-30)
diff --git a/plone-4.3.x.cfg b/plone-4.3.x.cfg
deleted file mode 100644
index 36b2240..0000000
--- a/plone-4.3.x.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[buildout]
-extends =
- base.cfg
- http://dist.plone.org/release/4.3-latest/versions.cfg
- versions.cfg
diff --git a/plone-5.0.x.cfg b/plone-5.0.x.cfg
deleted file mode 100644
index 3997cd8..0000000
--- a/plone-5.0.x.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[buildout]
-extends =
- base.cfg
- http://dist.plone.org/release/5.0.7/versions.cfg
- versions.cfg
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..78606b7
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+setuptools==38.2.4
+zc.buildout
diff --git a/setup.py b/setup.py
index b50ff4b..f2c99c7 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
from setuptools import setup, find_packages
import os
-version = '2.0.4.dev0'
+version = '2.1.0.dev0'
tests_require = [
'plone.app.testing',
diff --git a/travis.cfg b/travis.cfg
deleted file mode 100644
index e800297..0000000
--- a/travis.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-[buildout]
-extends = plone-x.x.x.cfg
-parts += createcoverage
-
-# caches, see also .travis.yaml
-# one should not depend on '/home/travis' but it seems stable in containers.
-eggs-directory = /home/travis/buildout-cache/eggs
-download-cache = /home/travis/buildout-cache/downloads
-
-[createcoverage]
-recipe = zc.recipe.egg
-eggs = createcoverage
-
-[code-analysis]
-recipe = plone.recipe.codeanalysis
-pre-commit-hook = False
-return-status-codes = True
diff --git a/versions.cfg b/versions.cfg
index 382aec5..0fae0db 100644
--- a/versions.cfg
+++ b/versions.cfg
@@ -1,23 +1,55 @@
[versions]
# Build
+setuptools = 38.5.1
+zc.buildout =
+zope.configuration = 4.1.0
+plone.testing =
+zExceptions = 3.6.1
setuptools =
zc.buildout =
-zc.recipe.egg = 2.0.3
-
-zope.interface = 4.0.5
+mr.developer = >=1.38
+PyYAML = 3.12
+argh = 0.26.2
+args = 0.1.0
+check-manifest = 0.35
+clint = 0.5.1
+colorama = 0.3.7
+configparser = 3.5.0
coverage = 3.7.1
-flake8 = 2.4.0
-flake8-coding = 1.2.2
+createcoverage = 1.5
+enum34 = 1.1.6
+flake8 = 3.3.0
+flake8-blind-except = 0.1.1
+flake8-coding = 1.3.0
+flake8-debugger = 1.4.0
+flake8-deprecated = 1.1
+flake8-isort = 2.1.3
+flake8-pep3101 = 1.0
+flake8-plone-api = 1.2
+flake8-plone-hasattr = 0.1
+flake8-polyfill = 1.0.1
+flake8-print = 2.0.2
+flake8-quotes = 0.9.0
+flake8-string-format = 0.2.3
+flake8-todo = 0.7
+i18ndude = 4.0.1
+isort = 4.2.5
+mccabe = 0.6.1
+pathtools = 0.1.2
+pkginfo = 1.4.1
plone.recipe.codeanalysis = 2.2
-
-Sphinx = 1.3.1
-docutils = 0.12
-Pygments = 2.0
-sphinxcontrib-httpexample = 0.5.2
-
-zest.releaser = 6.7
+plone.testing = 5.0.0
+pycodestyle = 2.3.1
+pyflakes = 1.5.0
+requests-toolbelt = 0.7.1
+robotframework = 3.0
+robotframework-ride = 1.5.2.1
+robotframework-selenium2library = 1.7.4
+robotsuite = 1.7.0
+selenium = 2.53.6
+testfixtures = 4.13.4
twine = 1.8.1
-requests = 2.11.1
-
-plone.testing =
-zope.configuration = 4.0.3
+watchdog = 0.8.3
+z3c.jbot = 0.7.2
+zc.recipe.egg = 2.0.3
+zest.releaser = 6.9