Annotation of ExtFile/ExtImage.py, revision 1.1.1.1

1.1       dwinter     1: """ExtImage product module."""
                      2: ###############################################################################
                      3: #
                      4: # Copyright (c) 2001 Gregor Heine <mac.gregor@gmx.de>. All rights reserved.
                      5: # ExtFile Home: http://www.zope.org/Members/MacGregor/ExtFile/index_html
                      6: #
                      7: # Redistribution and use in source and binary forms, with or without
                      8: # modification, are permitted provided that the following conditions
                      9: # are met:
                     10: #
                     11: # 1. Redistributions of source code must retain the above copyright
                     12: #    notice, this list of conditions and the following disclaimer.
                     13: # 2. Redistributions in binary form must reproduce the above copyright
                     14: #    notice, this list of conditions and the following disclaimer in the
                     15: #    documentation and/or other materials provided with the distribution.
                     16: # 3. The name of the author may not be used to endorse or promote products
                     17: #    derived from this software without specific prior written permission
                     18: #
                     19: # Disclaimer
                     20: #
                     21: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23: # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24: # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25: # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26: # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27: # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28: # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29: # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30: # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31: #   
                     32: #  In accordance with the license provided for by the software upon
                     33: #  which some of the source code has been derived or used, the following
                     34: #  acknowledgement is hereby provided :
                     35: #
                     36: #      "This product includes software developed by Digital Creations
                     37: #      for use in the Z Object Publishing Environment
                     38: #      (http://www.zope.org/)."
                     39: #
                     40: ###############################################################################
                     41: 
                     42: __doc__ = """ExtImage product module.
                     43:     The ExtImage-Product works like the Zope Image-product, but stores the 
                     44:     uploaded image externally in a repository-direcory. It creates a preview
                     45:     of the image (requires PIL)."""
                     46: 
                     47: __version__='1.5.4'
                     48: 
                     49: import Globals
                     50: from Products.ExtFile.ExtFile import *
                     51: from Globals import HTMLFile, MessageDialog, InitializeClass
                     52: from AccessControl import ClassSecurityInfo
                     53: from webdav.Lockable import ResourceLockedError
                     54: import urllib, os, string, types
                     55: from os.path import join, isfile
                     56: from tempfile import TemporaryFile
                     57: 
                     58: from webdav.WriteLockInterface import WriteLockInterface
                     59: from IExtFile import IExtImage
                     60: 
                     61: from zLOG import *
                     62: _SUBSYS = 'ExtImage'
                     63: _debug = 0
                     64: 
                     65: try: from zExceptions import Redirect
                     66: except ImportError: Redirect = 'Redirect'
                     67: 
                     68: from Config import REPOSITORY_UMASK
                     69: 
                     70: NO_PREVIEW = 0
                     71: GENERATE = 1
                     72: UPLOAD_NORESIZE = 2
                     73: UPLOAD_RESIZE = 3
                     74: 
                     75: manage_addExtImageForm = HTMLFile('dtml/extImageAdd', globals()) 
                     76: 
                     77: 
                     78: def manage_addExtImage(self, id='', title='', descr='', file='', preview='', 
                     79:                        content_type='', create_prev=0, maxx='', maxy='', 
                     80:                        ratio=0, permission_check=0, redirect_default_view=0, REQUEST=None):
                     81:     """ Add an ExtImage to a folder. """
                     82:     if not id and getattr(file, 'filename', None) is not None:
                     83:         # generate id from filename and make sure, it has no 'bad' chars
                     84:         id = file.filename
                     85:         id = id[max(string.rfind(id,'/'), 
                     86:                     string.rfind(id,'\\'), 
                     87:                     string.rfind(id,':'))+1:]
                     88:         title = title or id
                     89:         id = normalize_id(id)
                     90:     tempExtImage = ExtImage(id, title, descr, permission_check, redirect_default_view)
                     91:     self._setObject(id, tempExtImage)
                     92:     if file != '':
                     93:         self._getOb(id).manage_file_upload(file, content_type, 0, create_prev, maxx, maxy, ratio)
                     94:     if create_prev==UPLOAD_NORESIZE or create_prev==UPLOAD_RESIZE:
                     95:         self._getOb(id).manage_file_upload(preview, content_type, 1, create_prev, maxx, maxy, ratio)
                     96:     if REQUEST is not None:
                     97:         return self.manage_main(self, REQUEST, update_menu=0)
                     98:     return id
                     99: 
                    100: 
                    101: 
                    102: class ExtImage(ExtFile): 
                    103:     """ The ExtImage-Product works like the Zope Image-product, but stores the 
                    104:         uploaded image externally in a repository-direcory. It can create a 
                    105:         preview of the image (requires PIL)."""
                    106: 
                    107:     __implements__ = (IExtImage, WriteLockInterface)
                    108: 
                    109:     security = ClassSecurityInfo()
                    110:     
                    111:     # what do people think they're adding? 
                    112:     meta_type = 'ExtImage'
                    113:     
                    114:     # default,min,max-sizes for the preview image
                    115:     _image_size={'default':256,'min':1,'max':999} 
                    116:     
                    117:     # store maxx and maxy
                    118:     prev_maxx = _image_size['default']
                    119:     prev_maxy = _image_size['default']
                    120: 
                    121:     ################################
                    122:     # Init method                  #
                    123:     ################################
                    124:     
                    125:     def __init__(self, id, title='', descr='', permission_check=0, redirect_default_view=0): 
                    126:         """ Initialize a new instance of ExtImage """
                    127:         ExtImage.inheritedAttribute("__init__")(self, id, title, descr, permission_check, redirect_default_view)
                    128:         self.prev_filename = []
                    129:         self.prev_content_type = ''
                    130:         self.prev_ratio = 1
                    131:         self.has_preview = 0
                    132:     
                    133:     ################################
                    134:     # Public methods               #
                    135:     ################################
                    136:     
                    137:     def __str__(self):
                    138:         return self.tag()
                    139:     
                    140:     security.declareProtected(ViewPermission, 'tag')
                    141:     def tag(self, preview=0, icon=0, height=None, width=None, alt=None, 
                    142:         scale=0, xscale=0, yscale=0, border='0', REQUEST=None, **args):
                    143:         """ Generate an HTML IMG tag for this image, with customization.
                    144:             Arguments to self.tag() can be any valid attributes of an IMG tag.
                    145:             'src' will always be an absolute pathname, to prevent redundant
                    146:             downloading of images. Defaults are applied intelligently for
                    147:             'height', 'width', and 'alt'. If specified, the 'scale', 'xscale',
                    148:             and 'yscale' keyword arguments will be used to automatically adjust
                    149:             the output height and width values of the image tag.
                    150:             Adopted and adapted from OFS/Image.py
                    151:         """
                    152:         if not self.is_webviewable():
                    153:             preview = 1
                    154:         if not self._access_permitted():
                    155:             preview = 1
                    156:         if preview and not self.has_preview:
                    157:             icon = 1
                    158:         if icon:
                    159:             url = self._static_url(icon=1)
                    160:             img_width, img_height = (32, 32)
                    161:         elif preview:
                    162:             url = self._static_url(preview=1)
                    163:             img_width, img_height = self._getImageSize(self.prev_filename)
                    164:         else:
                    165:             url = self._static_url()
                    166:             img_width, img_height = self._getImageSize(self.filename)
                    167:         height = height or img_height
                    168:         width = width or img_width
                    169:         
                    170:         # Auto-scaling support
                    171:         xdelta = xscale or scale
                    172:         ydelta = yscale or scale
                    173:         if xdelta and width != None:
                    174:             width = str(int(width) * xdelta)
                    175:         if ydelta and height != None:
                    176:             height = str(int(height) * ydelta)
                    177:         
                    178:         if alt is None: alt = self.title or ''
                    179:         strg = '<img src="%s" border="%s" alt="%s"' % \
                    180:                (url, border, alt)
                    181:         if height: strg = '%s height="%s"' % (strg, height)
                    182:         if width: strg = '%s width="%s"' % (strg, width)
                    183:         for key in args.keys():
                    184:             value = args.get(key)
                    185:             strg = '%s %s="%s"' % (strg, key, value)
                    186:         strg="%s />" % (strg)
                    187:         return strg
                    188:     
                    189:     security.declareProtected(ViewPermission, 'preview')
                    190:     def preview(self):
                    191:         """ Return a preview of the image """
                    192:         raise Redirect, self._static_url(preview=1)
                    193:     
                    194:     security.declareProtected(ViewPermission, 'preview_tag')
                    195:     def preview_tag(self):
                    196:         """ Generates the HTML IMG tag for the preview image """
                    197:         return self.tag(preview=1)
                    198:     
                    199:     security.declareProtected(ViewPermission, 'preview_html')
                    200:     def preview_html(self):
                    201:         """ Same as preview_tag """
                    202:         return self.preview_tag()
                    203:     
                    204:     security.declareProtected(ViewPermission, 'is_broken')
                    205:     def is_broken(self):
                    206:         """ Check if external file exists and return true (1) or false (0) """
                    207:         if self.has_preview and self.filename != self.prev_filename:
                    208:             if not self._get_fsname(self.prev_filename):
                    209:                 return 1
                    210:         return ExtImage.inheritedAttribute("is_broken")(self)
                    211:     
                    212:     security.declareProtected(ViewPermission, 'is_webviewable')
                    213:     def is_webviewable(self):
                    214:         """ Return 1 for GIF, JPEG, and PNG images, otherwise return 0 """
                    215:         format = self.format()
                    216:         if format=='JPEG' or format=='GIF' or format=='PNG':
                    217:             return 1
                    218:         else:
                    219:             return 0
                    220:     
                    221:     security.declareProtected(ViewPermission, 'get_prev_size')
                    222:     def get_prev_size(self):
                    223:         """ Returns the size of the preview file """
                    224:         fn = self._get_fsname(self.prev_filename)
                    225:         if fn: 
                    226:             return os.stat(fn)[6]
                    227:         return 0
                    228: 
                    229:     security.declareProtected(ViewPermission, 'prev_rawsize')
                    230:     def prev_rawsize(self):
                    231:         """ Same as get_prev_size """
                    232:         return self.get_prev_size()
                    233:     
                    234:     security.declareProtected(ViewPermission, 'prev_size')
                    235:     def prev_size(self):
                    236:         """ Returns a formatted stringified version of the preview size """
                    237:         return self._bytetostring(self.get_prev_size())
                    238:     
                    239:     security.declareProtected(ViewPermission, 'width')
                    240:     def width(self):
                    241:         """ Pixel width of the image """
                    242:         return self._getImageSize(self.filename)[0]
                    243:         
                    244:     security.declareProtected(ViewPermission, 'height')
                    245:     def height(self):
                    246:         """ Pixel height of the image """
                    247:         return self._getImageSize(self.filename)[1]
                    248:         
                    249:     security.declareProtected(ViewPermission, 'prev_width')
                    250:     def prev_width(self):
                    251:         """ Pixel width of the preview """
                    252:         return self._getImageSize(self.prev_filename)[0]
                    253:         
                    254:     security.declareProtected(ViewPermission, 'prev_height')
                    255:     def prev_height(self):
                    256:         """ Pixel height of the preview """
                    257:         return self._getImageSize(self.prev_filename)[1]
                    258:         
                    259:     security.declareProtected(ViewPermission, 'format')
                    260:     def format(self):
                    261:         """ Get the PIL file format of the image """
                    262:         filename = self._get_fsname(self.filename)
                    263:         try:
                    264:             from PIL import Image
                    265:             im = Image.open(filename)
                    266:             return im.format
                    267:         except:
                    268:             return 'unknown'
                    269:     
                    270:     security.declareProtected(AccessPermission, 'get_prev_filename')
                    271:     def get_prev_filename(self):
                    272:         """ Returns the preview file name for display """
                    273:         return self._fsname(self.prev_filename)
                    274:         
                    275:     ################################
                    276:     # Protected management methods #
                    277:     ################################
                    278:     
                    279:     # Management Interface
                    280:     security.declareProtected(AccessPermission, 'manage_main')
                    281:     manage_main = HTMLFile('dtml/extImageEdit', globals())
                    282:     
                    283:     security.declareProtected(ChangePermission, 'manage_del_prev')
                    284:     def manage_del_prev(self, REQUEST=None):
                    285:         """ Delete the Preview Image """
                    286:         if self.has_preview and self.filename != self.prev_filename:
                    287:             tmp_fn = self._temp_fsname(self.prev_filename)
                    288:             fn = self._fsname(self.prev_filename)
                    289:             if isfile(tmp_fn):
                    290:                 try: os.rename(tmp_fn, fn+'.undo')
                    291:                 except OSError: pass
                    292:                 else:
                    293:                     try: os.remove(fn)
                    294:                     except OSError: pass
                    295:             elif isfile(fn):
                    296:                 try: os.rename(fn, fn+'.undo')
                    297:                 except OSError: pass
                    298:         self.prev_content_type = ''
                    299:         self.has_preview = 0
                    300: 
                    301:         self.ZCacheable_invalidate()
                    302: 
                    303:         if REQUEST is not None:
                    304:             return self.manage_main(self, REQUEST, manage_tabs_message='Preview deleted.')
                    305:     
                    306:     security.declareProtected(ChangePermission, 'manage_create_prev')
                    307:     def manage_create_prev(self, maxx=0, maxy=0, ratio=0, REQUEST=None):
                    308:         """ Create a preview Image """
                    309:         maxx, maxy = self._formatDimensions(maxx, maxy)
                    310:         if maxx!=0 and maxy!=0:
                    311:             self._register()    # Register with TM
                    312:             try:
                    313:                 new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg')
                    314:                 self._createPreview(self.filename, new_fn, maxx, maxy, ratio)
                    315:             finally:
                    316:                 self._dir__unlock()
                    317:         if REQUEST is None:
                    318:             return self.has_preview
                    319:         else:
                    320:             if self.has_preview: 
                    321:                 return self.manage_main(self, REQUEST, manage_tabs_message='Preview created.')
                    322:             elif maxx=='0' and maxy=='0':
                    323:                 return MessageDialog(
                    324:                     title = 'Attention',
                    325:                     message = "You must enter a value > 0",
                    326:                     action = './manage_main',)
                    327:             else:
                    328:                 return MessageDialog(
                    329:                     title = 'Warning',
                    330:                     message = "An error occurred while generating the preview.",
                    331:                     action = './manage_main',)
                    332:                 
                    333:     # File upload Interface
                    334:     security.declareProtected(AccessPermission, 'manage_uploadForm')
                    335:     manage_uploadForm = HTMLFile('dtml/extImageUpload', globals())
                    336:     
                    337:     security.declareProtected(ChangePermission, 'manage_upload')
                    338:     def manage_upload(self, file='', content_type='', is_preview=0,
                    339:                       create_prev=NO_PREVIEW, maxx='', maxy='', ratio=0,
                    340:                       REQUEST=None):
                    341:         """ Upload image from file handle or string buffer """
                    342:         if self.wl_isLocked():
                    343:             raise ResourceLockedError, "File is locked via WebDAV"
                    344: 
                    345:         if type(file) == types.StringType:
                    346:             temp_file = TemporaryFile()
                    347:             temp_file.write(file)
                    348:             temp_file.seek(0)
                    349:         else:
                    350:             temp_file = file
                    351:         return self.manage_file_upload(temp_file, content_type, is_preview,
                    352:                                        create_prev, maxx, maxy, ratio, REQUEST)
                    353: 
                    354:     security.declareProtected(ChangePermission, 'manage_file_upload')
                    355:     def manage_file_upload(self, file='', content_type='', is_preview=0, 
                    356:                            create_prev=NO_PREVIEW, maxx='', maxy='', ratio=0, 
                    357:                            REQUEST=None):
                    358:         """ Upload image from file handle or local directory """
                    359:         if self.wl_isLocked():
                    360:             raise ResourceLockedError, "File is locked via WebDAV"
                    361: 
                    362:         if is_preview:
                    363:             if type(file) == types.StringType:
                    364:                 cant_read_exc = "Can't open: "
                    365:                 try: file = open(file, 'rb')
                    366:                 except: raise cant_read_exc, file
                    367:             maxx, maxy = self._formatDimensions(maxx, maxy)
                    368:             if create_prev==UPLOAD_RESIZE and maxx!=0 and maxy!=0:
                    369:                 self._register()    # Register with TM
                    370:                 try:
                    371:                     new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg')
                    372:                     self._update_data(file, self._temp_fsname(new_fn))
                    373:                 finally:
                    374:                     self._dir__unlock()
                    375:                 self._createPreview(new_fn, new_fn, maxx, maxy, ratio)
                    376:             else:
                    377:                 if content_type:
                    378:                     file = HTTPUpload(file, content_type)
                    379:                 self.prev_content_type = self._get_content_type(file, file.read(100), 
                    380:                                          self.id, self.prev_content_type)
                    381:                 file.seek(0)
                    382:                 self._register()    # Register with TM
                    383:                 try:
                    384:                     new_fn = self._get_ufn(self.prev_filename, content_type=self.prev_content_type)
                    385:                     self._update_data(file, self._temp_fsname(new_fn))
                    386:                 finally:
                    387:                     self._dir__unlock()
                    388:                 self.prev_filename = new_fn
                    389:                 self._initPreview()
                    390:         else:
                    391:             ExtImage.inheritedAttribute("manage_file_upload")(self, file, content_type)
                    392:             if create_prev==GENERATE:
                    393:                 maxx, maxy = self._formatDimensions(maxx, maxy)
                    394:                 if maxx!=0 and maxy!=0:
                    395:                     self._register()    # Register with TM
                    396:                     try:
                    397:                         new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg')
                    398:                         self._createPreview(self.filename, new_fn, maxx, maxy, ratio)
                    399:                     finally:
                    400:                         self._dir__unlock()
                    401:         if REQUEST is not None:
                    402:             return self.manage_main(self, REQUEST, manage_tabs_message='Upload complete.')
                    403:     
                    404:     security.declareProtected(ChangePermission, 'manage_http_upload')
                    405:     def manage_http_upload(self, url, is_preview=0, REQUEST=None):
                    406:         """ Upload image from http-server """
                    407:         if self.wl_isLocked():
                    408:             raise ResourceLockedError, "File is locked via WebDAV"
                    409: 
                    410:         if is_preview:
                    411:             url = urllib.quote(url,'/:')
                    412:             cant_read_exc = "Can't open: "
                    413:             try: file = urllib.urlopen(url)
                    414:             except: raise cant_read_exc, url
                    415:             file = HTTPUpload(file)
                    416:             self.prev_content_type = self._get_content_type(file, file.read(100), 
                    417:                                      self.id, self.prev_content_type)
                    418:             file.seek(0)
                    419:             self._register()    # Register with TM
                    420:             try:
                    421:                 new_fn = self._get_ufn(self.prev_filename, content_type=self.prev_content_type)
                    422:                 self._update_data(file, self._temp_fsname(new_fn))
                    423:             finally:
                    424:                 self._dir__unlock()
                    425:             self.prev_filename = new_fn
                    426:             self._initPreview()
                    427:         else:
                    428:             ExtImage.inheritedAttribute("manage_http_upload")(self, url)
                    429:             #if self.has_preview:
                    430:             #    maxx, maxy = self._formatDimensions(self.prev_maxx, self.prev_maxy)
                    431:             #    self._register()    # Register with TM
                    432:             #    try:
                    433:             #        new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg')
                    434:             #        self._createPreview(self.filename, new_fn, maxx, maxy, self.prev_ratio)
                    435:             #    finally:
                    436:             #        self._dir__unlock()
                    437:         if REQUEST is not None:
                    438:             return self.manage_main(self, REQUEST, manage_tabs_message='Upload complete.')
                    439:     
                    440:     security.declareProtected(ChangePermission, 'PUT')
                    441:     def PUT(self, REQUEST, RESPONSE):
                    442:         """ Handle HTTP PUT requests """
                    443:         RESPONSE = ExtImage.inheritedAttribute("PUT")(self, REQUEST, RESPONSE)
                    444:         if self.has_preview:
                    445:             maxx, maxy = self._formatDimensions(self.prev_maxx, self.prev_maxy)
                    446:             self._register()    # Register with TM
                    447:             try:
                    448:                 # Need to pass in the path as webdav.NullResource calls PUT
                    449:                 # on an unwrapped object.
                    450:                 try:
                    451:                     self.aq_parent # This raises AttributeError if no context
                    452:                 except AttributError:
                    453:                     path = self._get_zodb_path(REQUEST.PARENTS[0])
                    454:                 else:
                    455:                     path = None
                    456:                 new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg', path=path)
                    457:                 self._createPreview(self.filename, new_fn, maxx, maxy, self.prev_ratio)
                    458:             finally:
                    459:                 self._dir__unlock() 
                    460:         return RESPONSE
                    461:     
                    462:     ################################
                    463:     # Private methods              #
                    464:     ################################
                    465:     
                    466:     def _getImageSize(self, filename):
                    467:         """ Return width, height tuple using PIL """
                    468:         filename = self._get_fsname(filename)
                    469:         try:
                    470:             from PIL import Image
                    471:             im = Image.open(filename)
                    472:             return im.size[0], im.size[1]
                    473:         except:
                    474:             return 0, 0
                    475:     
                    476:     def _createPreview(self, from_filename, to_filename, maxx, maxy, ratio):
                    477:         """ Generate a preview using PIL """
                    478:         try:
                    479:             from PIL import Image
                    480:         except ImportError:
                    481:             pass
                    482:         else:
                    483:             imfile = self._get_fsname(from_filename)
                    484:             if imfile:
                    485:                 im = Image.open(imfile) 
                    486:                 if im.mode!='RGB':
                    487:                     im = im.convert('RGB')
                    488:                 filter = Image.BICUBIC
                    489:                 if hasattr(Image, 'ANTIALIAS'): # PIL 1.1.3
                    490:                     filter = Image.ANTIALIAS
                    491:                 if ratio:               # keep aspect-ratio
                    492:                     im.thumbnail((maxx,maxy), filter)
                    493:                 else:                   # distort to fixed size
                    494:                     im = im.resize((maxx,maxy), filter)
                    495:                 umask = os.umask(REPOSITORY_UMASK)
                    496:                 outfile = self._temp_fsname(to_filename)
                    497:                 try:
                    498:                     im.save(outfile, 'JPEG', quality=85)
                    499:                 except:
                    500:                     os.umask(umask)
                    501:                     if isfile(outfile):
                    502:                         try: os.remove(outfile)
                    503:                         except OSError: pass
                    504:                     raise
                    505:                 else:
                    506:                     os.umask(umask)
                    507:                 self.prev_content_type = 'image/jpeg'
                    508:                 self.prev_filename = to_filename
                    509:                 self.prev_maxx = maxx
                    510:                 self.prev_maxy = maxy
                    511:                 self.prev_ratio = ratio
                    512:         self._initPreview()
                    513:     
                    514:     def _initPreview(self):
                    515:         """ Verify the preview """
                    516:         self.ZCacheable_invalidate()
                    517: 
                    518:         prev_width, prev_height = self._getImageSize(self.prev_filename)
                    519:         if prev_width<=0 or prev_height<=0: 
                    520:             self.has_preview = 0
                    521:         else:
                    522:             self.has_preview = 1
                    523:             
                    524:     def _formatDimensions(self, maxx, maxy):
                    525:         """ Make sure, the dimensions are valid int's """
                    526:         if type(maxx) is types.StringType:
                    527:             try: maxx = int(maxx)
                    528:             except ValueError: maxx = self._image_size['default']
                    529:         if type(maxy) is types.StringType:
                    530:             try: maxy = int(maxy)
                    531:             except ValueError: maxy = self._image_size['default']
                    532:         if maxx!=0 and maxy!=0:
                    533:             if maxx<self._image_size['min']: maxx = self._image_size['min']
                    534:             elif maxx>self._image_size['max']: maxx = self._image_size['max']
                    535:             if maxy<self._image_size['min']: maxy = self._image_size['min']
                    536:             elif maxy>self._image_size['max']: maxy = self._image_size['max']
                    537:         return maxx, maxy
                    538:     
                    539:     def _undo(self):
                    540:         """ Restore filename after delete or copy-paste """
                    541:         if self.has_preview and self.filename != self.prev_filename:
                    542:             fn = self._fsname(self.prev_filename)
                    543:             if not isfile(fn) and isfile(fn+'.undo'): 
                    544:                 self._register()    # Register with TM
                    545:                 os.rename(fn+'.undo', self._temp_fsname(self.prev_filename))
                    546:         return ExtImage.inheritedAttribute("_undo")(self)
                    547:     
                    548:     def _get_content_type(self, file, body, id, content_type=None):
                    549:         """ Determine the mime-type """
                    550:         from OFS.Image import getImageInfo
                    551:         ct, w, h = getImageInfo(body)
                    552:         if ct: 
                    553:             content_type = ct
                    554:         else:
                    555:             content_type = ExtImage.inheritedAttribute('_get_content_type')(self, 
                    556:                                                     file, body, id, content_type)
                    557:         return content_type
                    558: 
                    559:     ################################
                    560:     # Special management methods   #
                    561:     ################################
                    562:     
                    563:     security.declarePrivate('manage_afterClone')
                    564:     def manage_afterClone(self, item):
                    565:         """ When a copy of the object is created (zope copy-paste-operation),
                    566:             this function is called by CopySupport.py. A copy of the external 
                    567:             file is created and self.filename is changed.
                    568:         """
                    569:         try: 
                    570:             self.aq_parent # This raises AttributeError if no context
                    571:         except AttributeError: 
                    572:             pass
                    573:         else:
                    574:             result = ExtImage.inheritedAttribute("manage_afterClone")(self, item)
                    575:             self._register()    # Register with TM
                    576:             try:
                    577:                 new_prev_fn = self._get_new_ufn(content_type=self.prev_content_type)
                    578:                 if self.has_preview and self.filename != self.prev_filename:
                    579:                     old_prev_fn = self._get_fsname(self.prev_filename)
                    580:                     if old_prev_fn:
                    581:                         self._update_data(old_prev_fn, self._temp_fsname(new_prev_fn))
                    582:                         self.prev_filename = new_prev_fn
                    583:                     else:
                    584:                         self.prev_filename = []
                    585:                         self.has_preview = 0
                    586:                 elif self.has_preview:
                    587:                     # XXX: This seems to be an impossible state?
                    588:                     old_fn = self._get_fsname(self.filename)
                    589:                     if not old_fn:
                    590:                         self.prev_filename = []
                    591:                         self.has_preview = 0
                    592:                 else:
                    593:                     self.prev_filename = []
                    594:             finally:
                    595:                 self._dir__unlock()
                    596:             return result
                    597:         return ExtImage.inheritedAttribute("manage_afterClone")(self, item)
                    598: 
                    599:     security.declarePrivate('manage_afterAdd')
                    600:     def manage_afterAdd(self, item, container):
                    601:         """ When a copy of the object is created (zope copy-paste-operation),
                    602:             this function is called by CopySupport.py. A copy of the external 
                    603:             file is created and self.filename is changed.
                    604:         """
                    605:         return ExtImage.inheritedAttribute("manage_afterAdd")(self, item, container)
                    606:         
                    607:     security.declarePrivate('manage_beforeDelete')
                    608:     def manage_beforeDelete(self, item, container):
                    609:         """ This method is called, when the object is deleted. To support 
                    610:             undo-functionality and because this happens too, when the object 
                    611:             is moved (cut-paste) or renamed, the external file is not deleted. 
                    612:             It is just renamed to filename.undo and remains in the 
                    613:             repository, until it is deleted manually.
                    614:         """
                    615:         if self.has_preview and self.filename != self.prev_filename:
                    616:             tmp_fn = self._temp_fsname(self.prev_filename)
                    617:             fn = self._fsname(self.prev_filename)
                    618:             if isfile(tmp_fn):
                    619:                 try: os.rename(tmp_fn, fn+'.undo')
                    620:                 except OSError: pass
                    621:                 else:
                    622:                     try: os.remove(fn)
                    623:                     except OSError: pass
                    624:             elif isfile(fn):
                    625:                 try: os.rename(fn, fn+'.undo')
                    626:                 except OSError: pass
                    627:         return ExtImage.inheritedAttribute("manage_beforeDelete")(self, item, container)
                    628: 
                    629:     ################################
                    630:     # Transaction manager methods  #
                    631:     ################################
                    632: 
                    633:     def _finish(self):
                    634:         """ Commits the temporary file """
                    635:         if self.prev_filename and self.filename != self.prev_filename:
                    636:             tmp_fn = self._temp_fsname(self.prev_filename)
                    637:             if _debug: LOG(_SUBSYS, INFO, 'finishing %s' % tmp_fn)
                    638:             if isfile(tmp_fn):
                    639:                 if _debug: LOG(_SUBSYS, INFO, 'isfile %s' % tmp_fn)
                    640:                 fn = self._fsname(self.prev_filename)
                    641:                 try: os.remove(fn)
                    642:                 except OSError: pass
                    643:                 os.rename(tmp_fn, fn)
                    644:         ExtImage.inheritedAttribute('_finish')(self)
                    645:     
                    646:     def _abort(self):
                    647:         """ Deletes the temporary file """
                    648:         if self.prev_filename and self.filename != self.prev_filename:
                    649:             tmp_fn = self._temp_fsname(self.prev_filename)
                    650:             if _debug: LOG(_SUBSYS, INFO, 'aborting %s' % tmp_fn)
                    651:             if isfile(tmp_fn):
                    652:                 if _debug: LOG(_SUBSYS, INFO, 'isfile %s' % tmp_fn)
                    653:                 try: os.remove(tmp_fn)
                    654:                 except OSError: pass
                    655:         ExtImage.inheritedAttribute('_abort')(self)
                    656:         
                    657: 
                    658: InitializeClass(ExtImage)
                    659: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>