• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / Products.CMFCore / 6123729360

08 Sep 2023 03:43PM UTC coverage: 86.266% (-0.02%) from 86.283%
6123729360

push

github

web-flow
Merge pull request #130 from zopefoundation/zmi_customize_item

ZMI: limit number of resulted folderish objects and show SVG as FSImage

2466 of 3665 branches covered (0.0%)

Branch coverage included in aggregate %.

19 of 19 new or added lines in 3 files covered. (100.0%)

17358 of 19315 relevant lines covered (89.87%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.27
/src/Products/CMFCore/FSImage.py
1
##############################################################################
2
#
3
# Copyright (c) 2001 Zope Foundation and Contributors.
4
#
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
7
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
# FOR A PARTICULAR PURPOSE.
11
#
12
##############################################################################
13
""" Customizable image objects that come from the filesystem.
1✔
14
"""
15

16
import os
1✔
17

18
from AccessControl.class_init import InitializeClass
1✔
19
from AccessControl.SecurityInfo import ClassSecurityInfo
1✔
20
from App.special_dtml import DTMLFile
1✔
21
from OFS.Image import Image
1✔
22
from OFS.Image import getImageInfo
1✔
23

24
from .DirectoryView import registerFileExtension
1✔
25
from .DirectoryView import registerMetaType
1✔
26
from .FSObject import FSObject
1✔
27
from .permissions import FTPAccess
1✔
28
from .permissions import View
1✔
29
from .permissions import ViewManagementScreens
1✔
30
from .utils import _checkConditionalGET
1✔
31
from .utils import _dtmldir
1✔
32
from .utils import _FSCacheHeaders
1✔
33
from .utils import _setCacheHeaders
1✔
34
from .utils import _ViewEmulator
1✔
35

36

37
class FSImage(FSObject):
1✔
38

39
    """FSImages act like images but are not directly
40
    modifiable from the management interface."""
41
    # Note that OFS.Image.Image is not a base class because it is mutable.
42

43
    meta_type = 'Filesystem Image'
1✔
44
    zmi_icon = 'far fa-file-image'
1✔
45
    content_type = 'unknown/unknown'
1✔
46
    alt = ''
1✔
47
    height = ''
1✔
48
    width = ''
1✔
49
    _data = None
1✔
50

51
    manage_options = ({'label': 'Customize', 'action': 'manage_main'},)
1✔
52

53
    security = ClassSecurityInfo()
1✔
54
    security.declareObjectProtected(View)
1✔
55

56
    security.declareProtected(ViewManagementScreens, 'manage_main')
1✔
57
    manage_main = DTMLFile('custimage', _dtmldir)
1✔
58

59
    def __init__(self, id, filepath, fullname=None, properties=None):
1✔
60
        id = fullname or id  # Use the whole filename.
1✔
61
        FSObject.__init__(self, id, filepath, fullname, properties)
1✔
62

63
    def _createZODBClone(self):
1✔
64
        return Image(self.getId(), '', self._readFile(1))
×
65

66
    def _readFile(self, reparse):
1✔
67
        """Read the data from the filesystem.
68
        """
69
        file = open(self._filepath, 'rb')
1✔
70
        try:
1✔
71
            data = self._data = file.read()
1✔
72
        finally:
73
            file.close()
1✔
74

75
        if reparse or self.content_type == 'unknown/unknown':
1✔
76
            try:
1✔
77
                mtime = os.stat(self._filepath).st_mtime
1✔
78
            except Exception:
×
79
                mtime = 0.0
×
80
            if mtime != self._file_mod_time or mtime == 0.0:
1✔
81
                self.ZCacheable_invalidate()
1✔
82
                self._file_mod_time = mtime
1✔
83
            ct, width, height = getImageInfo(data)
1✔
84
            if ct == '' and self.id.endswith('.svg'):
1!
85
                ct = 'image/svg+xml'
×
86
            self.content_type = ct
1✔
87
            self.width = width
1✔
88
            self.height = height
1✔
89
        return data
1✔
90

91
    # The following is mainly taken from OFS/Image.py
92

93
    __str__ = Image.__str__
1✔
94

95
    _image_tag = Image.tag
1✔
96

97
    @security.protected(View)
1✔
98
    def tag(self, *args, **kw):
1✔
99
        # Hook into an opportunity to reload metadata.
100
        self._updateFromFS()
1✔
101
        return self._image_tag(*args, **kw)
1✔
102

103
    @security.protected(View)
1✔
104
    def index_html(self, REQUEST, RESPONSE):
1✔
105
        """
106
        The default view of the contents of a File or Image.
107

108
        Returns the contents of the file or image.  Also, sets the
109
        Content-Type HTTP header to the objects content type.
110
        """
111
        self._updateFromFS()
1✔
112
        view = _ViewEmulator().__of__(self)
1✔
113

114
        # There are 2 Cache Managers which can be in play....
115
        # need to decide which to use to determine where the cache headers
116
        # are decided on.
117
        if self.ZCacheable_getManager() is not None:
1!
118
            self.ZCacheable_set(None)
×
119
        else:
120
            _setCacheHeaders(view, extra_context={})
1✔
121

122
        # If we have a conditional get, set status 304 and return
123
        # no content
124
        if _checkConditionalGET(view, extra_context={}):
1!
125
            return ''
×
126

127
        RESPONSE.setHeader('Content-Type', self.content_type)
1✔
128

129
        # old-style If-Modified-Since header handling.
130
        if self._setOldCacheHeaders():
1✔
131
            # Make sure the CachingPolicyManager gets a go as well
132
            _setCacheHeaders(view, extra_context={})
1✔
133
            return ''
1✔
134

135
        data = self._readFile(0)
1✔
136
        data_len = len(data)
1✔
137
        RESPONSE.setHeader('Content-Length', data_len)
1✔
138
        return data
1✔
139

140
    def _setOldCacheHeaders(self):
1✔
141
        # return False to disable this simple caching behaviour
142
        return _FSCacheHeaders(self)
1✔
143

144
    def modified(self):
1✔
145
        return self.getModTime()
1✔
146

147
    @security.protected(View)
1✔
148
    def getContentType(self):
1✔
149
        """Get the content type of a file or image.
150

151
        Returns the content type (MIME type) of a file or image.
152
        """
153
        self._updateFromFS()
×
154
        return self.content_type
×
155

156
    @security.protected(View)
1✔
157
    def get_size(self):
1✔
158
        """
159
            Return the size of the image.
160
        """
161
        self._updateFromFS()
1✔
162
        return self._data and len(self._data) or 0
1✔
163

164
    security.declareProtected(FTPAccess, 'manage_FTPget')
1✔
165
    manage_FTPget = index_html
1✔
166

167

168
InitializeClass(FSImage)
1✔
169

170
registerFileExtension('gif', FSImage)
1✔
171
registerFileExtension('jpg', FSImage)
1✔
172
registerFileExtension('jpeg', FSImage)
1✔
173
registerFileExtension('png', FSImage)
1✔
174
registerFileExtension('bmp', FSImage)
1✔
175
registerFileExtension('svg', FSImage)
1✔
176
registerMetaType('Image', FSImage)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc