Annotation of ExtFile/ExtImage.py, revision 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>