From 3b2430b614b471a43b3e058e351ecd411c88619a Mon Sep 17 00:00:00 2001
From: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date: Fri, 25 Oct 2013 17:10:30 +0200
Subject: [PATCH] explicitly check if PUT() is called with PUT request method.

---
 product/ERP5/Document/Coordinate.py  |  8 +++++---
 product/ERP5/Document/File.py        |  4 ----
 product/ERP5Form/Form.py             |  3 +++
 product/ERP5Type/WebDAVSupport.py    |  5 +++++
 product/ERP5Type/mixin/component.py  |  3 +++
 product/ERP5Type/patches/OFSImage.py | 11 +++++++++++
 product/Localizer/MessageCatalog.py  |  3 +++
 7 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/product/ERP5/Document/Coordinate.py b/product/ERP5/Document/Coordinate.py
index 21d8e9deeb..5e21e2d810 100644
--- a/product/ERP5/Document/Coordinate.py
+++ b/product/ERP5/Document/Coordinate.py
@@ -28,6 +28,7 @@
 
 import zope.interface
 from AccessControl import ClassSecurityInfo
+from zExceptions import Forbidden
 
 from Products.ERP5Type import Permissions, PropertySheet, interfaces
 from Products.ERP5Type.Base import Base
@@ -220,9 +221,10 @@ class Coordinate(Base):
       """
           Handle HTTP / WebDAV / FTP PUT requests.
       """
-      if not NoWL:
-        self.dav__init(REQUEST, RESPONSE)
-        self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
+      self.dav__init(REQUEST, RESPONSE)
+      self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
+      if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+        raise Forbidden, 'REQUEST_METHOD should be PUT.'
       body = REQUEST.get('BODY', '')
       try:
         self._writeFromPUT( body )
diff --git a/product/ERP5/Document/File.py b/product/ERP5/Document/File.py
index 8643dbba4c..a6fcb196b8 100644
--- a/product/ERP5/Document/File.py
+++ b/product/ERP5/Document/File.py
@@ -201,10 +201,6 @@ class File(Document, CMFFile):
     else:
       return str(data)
 
-  security.declareProtected(Permissions.ModifyPortalContent,'PUT')
-  def PUT(self, REQUEST, RESPONSE):
-    CMFFile.PUT(self, REQUEST, RESPONSE)
-
   # DAV Support
   PUT = CMFFile.PUT
   security.declareProtected(Permissions.FTPAccess, 'manage_FTPstat',
diff --git a/product/ERP5Form/Form.py b/product/ERP5Form/Form.py
index 0315788086..d037e657e6 100644
--- a/product/ERP5Form/Form.py
+++ b/product/ERP5Form/Form.py
@@ -45,6 +45,7 @@ from ZODB.POSException import ConflictError
 from zExceptions import Redirect
 from Acquisition import aq_base
 from Products.PageTemplates.Expressions import SecureModuleImporter
+from zExceptions import Forbidden
 
 from Products.ERP5Type.PsycoWrapper import psyco
 from Products.ERP5Type.Base import Base
@@ -772,6 +773,8 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate):
         """Handle HTTP PUT requests."""
         self.dav__init(REQUEST, RESPONSE)
         self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
+        if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+            raise Forbidden, 'REQUEST_METHOD should be PUT.'
         body=REQUEST.get('BODY', '')
         # Empty the form (XMLToForm is unable to empty things before reopening)
         for k in self.get_field_ids():
diff --git a/product/ERP5Type/WebDAVSupport.py b/product/ERP5Type/WebDAVSupport.py
index 5a6b493a1a..69d782a33f 100644
--- a/product/ERP5Type/WebDAVSupport.py
+++ b/product/ERP5Type/WebDAVSupport.py
@@ -26,6 +26,7 @@ from Products.CMFDefault.utils import html_headcheck
 from Products.CMFDefault.utils import bodyfinder
 from Products.CMFDefault.utils import SimpleHTMLParser as CMFSimpleHTMLParser
 from zLOG import LOG
+from zExceptions import Forbidden
 
 security = ModuleSecurityInfo( 'Products.ERP5Type.WebDAVSupport' )
 
@@ -117,6 +118,8 @@ class TextContent:
     """ Handle HTTP (and presumably FTP?) PUT requests """
     self.dav__init(REQUEST, RESPONSE)
     self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
+    if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+      raise Forbidden, 'REQUEST_METHOD should be PUT.'
     body = REQUEST.get('BODY', '')
 
     try:
@@ -208,6 +211,8 @@ def PUT(self, REQUEST, RESPONSE):
           return NullResource_PUT(self, REQUEST, RESPONSE)
 
         self.dav__init(REQUEST, RESPONSE)
+        if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+          raise Forbidden, 'REQUEST_METHOD should be PUT.'
 
         name = self.__name__
         parent = self.__parent__
diff --git a/product/ERP5Type/mixin/component.py b/product/ERP5Type/mixin/component.py
index 6b21d1cdb9..6fbaba7b89 100644
--- a/product/ERP5Type/mixin/component.py
+++ b/product/ERP5Type/mixin/component.py
@@ -38,6 +38,7 @@ from Products.ERP5Type import Permissions
 from Products.ERP5Type.Base import Base
 from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
 from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
+from zExceptions import Forbidden
 
 from zLOG import LOG, INFO
 
@@ -290,6 +291,8 @@ class ComponentMixin(PropertyRecordableMixin, Base):
     """
     self.dav__init(REQUEST, RESPONSE)
     self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
+    if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+      raise Forbidden, 'REQUEST_METHOD should be PUT.'
 
     text_content = REQUEST.get('BODY')
     if text_content is None:
diff --git a/product/ERP5Type/patches/OFSImage.py b/product/ERP5Type/patches/OFSImage.py
index 2f85f04e70..aacfde27ce 100644
--- a/product/ERP5Type/patches/OFSImage.py
+++ b/product/ERP5Type/patches/OFSImage.py
@@ -19,6 +19,7 @@
 import OFS.Image
 import struct
 from cStringIO import StringIO
+from zExceptions import Forbidden
 
 def getImageInfo_with_svg_fix(data):
     data = str(data)
@@ -83,3 +84,13 @@ def getImageInfo_with_svg_fix(data):
     return content_type, width, height
 
 OFS.Image.getImageInfo = getImageInfo_with_svg_fix
+
+PUT_orig = OFS.Image.File.PUT
+
+def PUT(self, REQUEST, RESPONSE):
+  """Handle HTTP PUT requests"""
+  if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+    raise Forbidden, 'REQUEST_METHOD should be PUT.'
+  return PUT_orig(self, REQUEST, RESPONSE)
+
+OFS.Image.File.PUT = PUT
diff --git a/product/Localizer/MessageCatalog.py b/product/Localizer/MessageCatalog.py
index 585224e29f..360e7c28d1 100644
--- a/product/Localizer/MessageCatalog.py
+++ b/product/Localizer/MessageCatalog.py
@@ -46,6 +46,7 @@ from zope.i18n import interpolate
 from zope.i18n.interfaces import ITranslationDomain
 from zope.interface import implements
 from zLOG import LOG, INFO
+from zExceptions import Forbidden
 
 # Import from Localizer
 from interfaces import IMessageCatalog
@@ -737,6 +738,8 @@ class POFile(SimpleItem):
     security.declareProtected('Manage messages', 'PUT')
     def PUT(self, REQUEST, RESPONSE):
         """ """
+        if REQUEST.environ['REQUEST_METHOD'] != 'PUT':
+            raise Forbidden, 'REQUEST_METHOD should be PUT.'
         body = REQUEST['BODY']
         self.po_import(self.id, body)
         RESPONSE.setStatus(204)
-- 
2.30.9