r304 - in zope-attachmentfield/trunk: . Extensions debian doc i18n skins/attachmentfield

Jérémy Bobbio lunar-guest at costa.debian.org
Fri Oct 13 20:51:33 UTC 2006


Author: lunar-guest
Date: 2006-10-13 20:51:32 +0000 (Fri, 13 Oct 2006)
New Revision: 304

Added:
   zope-attachmentfield/trunk/FlexStorage.py
   zope-attachmentfield/trunk/doc/HOWTO
   zope-attachmentfield/trunk/i18n/attachmentfield-cs.po
   zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy
   zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy.metadata
   zope-attachmentfield/trunk/skins/attachmentfield/sample/
Modified:
   zope-attachmentfield/trunk/AttachmentField.py
   zope-attachmentfield/trunk/AttachmentFieldTool.py
   zope-attachmentfield/trunk/AttachmentHandler.py
   zope-attachmentfield/trunk/AttachmentService.py
   zope-attachmentfield/trunk/AudioAttachment.py
   zope-attachmentfield/trunk/AutocadAttachment.py
   zope-attachmentfield/trunk/CHANGES
   zope-attachmentfield/trunk/CompressedAttachment.py
   zope-attachmentfield/trunk/DummyAttachment.py
   zope-attachmentfield/trunk/Extensions/Install.py
   zope-attachmentfield/trunk/FlashAttachment.py
   zope-attachmentfield/trunk/HTMLAttachment.py
   zope-attachmentfield/trunk/ImageAttachment.py
   zope-attachmentfield/trunk/MSAccessAttachment.py
   zope-attachmentfield/trunk/MSExcelAttachment.py
   zope-attachmentfield/trunk/MSPowerpointAttachment.py
   zope-attachmentfield/trunk/MSProjectAttachment.py
   zope-attachmentfield/trunk/MSWordAttachment.py
   zope-attachmentfield/trunk/OO2Attachment.py
   zope-attachmentfield/trunk/OOAttachment.py
   zope-attachmentfield/trunk/PDFAttachment.py
   zope-attachmentfield/trunk/PhotoshopAttachment.py
   zope-attachmentfield/trunk/PortalTransformsAttachment.py
   zope-attachmentfield/trunk/RTFAttachment.py
   zope-attachmentfield/trunk/TarGzAttachment.py
   zope-attachmentfield/trunk/TextAttachment.py
   zope-attachmentfield/trunk/VideoAttachment.py
   zope-attachmentfield/trunk/VisioAttachment.py
   zope-attachmentfield/trunk/ZipAttachment.py
   zope-attachmentfield/trunk/cvs2cl.pl
   zope-attachmentfield/trunk/debian/changelog
   zope-attachmentfield/trunk/skins/attachmentfield/attachment_download.py
   zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt
   zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt.metadata
   zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_widget.pt
   zope-attachmentfield/trunk/skins/attachmentfield/preview_popup.pt
   zope-attachmentfield/trunk/version.txt
Log:
Update to upstream version 1.3.10.


Modified: zope-attachmentfield/trunk/AttachmentField.py
===================================================================
--- zope-attachmentfield/trunk/AttachmentField.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/AttachmentField.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23491 $"
+__version__ = "$Revision: 30579 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: AttachmentField.py 23491 2006-05-15 13:44:47Z glenfant $
+# $Id: AttachmentField.py 30579 2006-09-19 13:58:17Z manuco $
 __docformat__ = 'restructuredtext'
 
 import urllib
@@ -59,6 +59,8 @@
 from Products.AttachmentField.interfaces.attachmentfield import IAttachmentField
 import AttachmentHandler
 
+from FlexStorage import FlexStorage
+
 ##DEFAULT_ID = "attach"
 ##ZAA_READ_PERMISSION = Permissions.access_contents_information
 ##ZAA_WRITE_PERMISSION = Permissions.change_images_and_files
@@ -73,13 +75,39 @@
 _indexed_ = "_%s_AF_indexed"
 _preview_ = "_%s_AF_preview"
 
+
+
+def getContentTypesWithAttachmentFields(instance):
+    """
+        Look for all content types that use AttachmentField, and return
+        a dictionnary with
+        keys : all content type names that use AttachmentField
+        values : a list of all fields name that are AttachementField in
+            this content type
+    """
+    archetypeTool = getToolByName(instance, 'archetype_tool')
+    types = archetypeTool.listRegisteredTypes()
+    result = {}
+    for type in types:
+        fields = type["schema"].fields()
+        typeName = type["name"]
+        for field in fields:
+            if isinstance(field, AttachmentField):
+                if typeName in result.keys():
+                    result[typeName].append(field.getName())
+                else:
+                    result[typeName] = [field.getName()]
+    return result
+
+
+
 class AttachmentField(Field.FileField):
     """
     A base class to handle file fields. This is based on Archetypes.
     When the file is uploaded, it's stored, as the File field, as a File class.
 
     See FileField.set() :
-    
+
         value = File(self.getName(), '', value, mimetype)
         setattr(value, 'filename', f_name or self.getName())
         ObjectField.set(self, instance, value, **kwargs)
@@ -88,6 +116,13 @@
     __implements__ = (Field.FileField.__implements__, IAttachmentField)
     security = ClassSecurityInfo()
 
+
+    _properties = Field.FileField._properties.copy()
+    _properties.update({
+            "storage": FlexStorage()
+        })
+
+
     def get(self, instance, mimetype = None, **kwargs):
         """Get value. If mime_type is 'text/plain', we retreive the
         indexed string. If it's text/html, we get the preview back.
@@ -108,109 +143,29 @@
         self._reset(instance)
         return Field.FileField.set(self, instance, value, **kwargs)
 
-    security.declarePrivate('download')
-    def download(self, instance, REQUEST=None, RESPONSE=None):
-        """Use storage download method or field one"""
-        
-        obj = self.get(instance)
-        
-        if obj is not None and hasattr(aq_base(obj), 'download'):
-            return obj.download(REQUEST)
-        else:
-            return Field.FileField.download(self, instance, REQUEST, RESPONSE)
-
-##    def _process_input(self, value, default=None,
-##                       mimetype=None, **kwargs):
-##        # We also need to handle the case where there is a baseUnit
-##        # for this field containing a valid set of data that would
-##        # not be reuploaded in a subsequent edit, this is basically
-##        # migrated from the old BaseObject.set method
-##        from ZPublisher.HTTPRequest import FileUpload
-##        from ZODB.POSException import ConflictError
-##        if not (isinstance(value, FileUpload) or type(value) is FileType) \
-##          and shasattr(value, 'read') and shasattr(value, 'seek'):
-##            # support StringIO and other file like things that aren't either
-##            # files or FileUploads
-##            value.seek(0) # rewind
-##            kwargs['filename'] = getattr(value, 'filename', '')
-##            mimetype = getattr(value, 'mimetype', None)
-##            value = value.read()
-##        if isinstance(value, Pdata):
-##            # Pdata is a chain of Pdata objects but we can easily use str()
-##            # to get the whole string from a chain of Pdata objects
-##            value = str(value)
-##        if type(value) in Field.STRING_TYPES:
-##            filename = kwargs.get('filename', '')
-##            if mimetype is None:
-##                mimetype, enc = guess_content_type(filename, value, mimetype)
-##            if not value:
-##                return default, mimetype, filename
-##            return value, mimetype, filename
-##        elif IBaseUnit.isImplementedBy(value):
-##            return value.getRaw(), value.getContentType(), value.getFilename()
-
-##        value = aq_base(value)
-
-##        if ((isinstance(value, FileUpload) and value.filename != '') or
-##              (type(value) is FileType and value.name != '')):
-##            filename = ''
-##            if isinstance(value, FileUpload) or shasattr(value, 'filename'):
-##                filename = value.filename
-##            if isinstance(value, FileType) or shasattr(value, 'name'):
-##                filename = value.name
-##            # Get only last part from a 'c:\\folder\\file.ext'
-##            filename = filename.split('\\')[-1]
-##            value.seek(0) # rewind
-##            value = value.read()
-##            if mimetype is None:
-##                mimetype, enc = guess_content_type(filename, value, mimetype)
-##            size = len(value)
-##            if size == 0:
-##                # This new file has no length, so we keep the orig
-##                return default, mimetype, filename
-##            else:
-##                return value, mimetype, filename
-
-##        # wrap VirtualFile object
-##        if hasattr(value, '__of__'):
-##            value = value.__of__(value)
-##        if isinstance(value, File):
-##            # OFS.Image.File based
-##            filename = value.filename
-##            mimetype = value.content_type
-##            data = value.data
-##            if len(data) == 0:
-##                return default, mimetype, filename
-##            else:
-##                return data, mimetype, filename
-
-##        klass = getattr(value, '__class__', None)
-##        raise FileFieldException('Value is not File or String (%s - %s)' %
-##                                 (type(value), klass))
-
     security.declarePublic("getFilename")
     def getFilename(self, instance, fromBaseUnit=True):
         """
         getFilename(self, instance, ) => return the filename
         We split to return only a file name and not a whole path.
         """
-        
+
         # Get object or data
         accessor = self.getAccessor(instance)
-        
+
         if self.isEmpty(instance) or accessor is None:
             return ''
-        
+
         obj = accessor()
         fn = ''
-        
+
         if hasattr(obj.aq_explicit, 'filename'):
             fn = obj.filename
         elif hasattr(obj.aq_explicit, 'getFilename'):
             fn = obj.getFilename()
         else:
             fn = Field.FileField.getFilename(self, instance, fromBaseUnit)
-            
+
         fn = string.split(fn, '/')[-1]
         fn = string.split(fn, '\\')[-1]
         return fn
@@ -227,36 +182,6 @@
             return self.default_content_type
         return str(mimetype)
 
-
-##    def getContentType(self, instance, fromBaseUnit=True):
-##        """
-##        getContentType(self, instance, fromBaseUnit=True) => return the content type
-##        """
-##        # Get object or data
-##        accessor = self.getAccessor(instance)
-
-##        # Empty object : we use the default content type
-##        if self.isEmpty(instance) or accessor is None:
-##            Log(LOG_DEBUG, "returning defaut content type", self.default_content_type)
-##            return self.default_content_type
-
-##        # Look at the underlying structure
-##        obj = accessor()
-##        if hasattr(obj.aq_explicit, 'mimetype'):
-##            ret = obj.mimetype
-##        elif hasattr(obj.aq_explicit, 'getContentType'):
-##            ret = obj.getContentType()
-##        else:
-##            ret = Field.FileField.getContentType(self, instance, fromBaseUnit)
-##        Log(LOG_DEBUG, "Mimetype before correction: ", ret)
-
-##        # Correct the type we guessed if needed
-##        if ret in ("application/octet-stream", 'text/x-unknown-content-type', ):
-##            ret = self.guessMimeTypeFromContent(instance)
-##        Log(LOG_DEBUG, "After correction, it's...", ret)
-
-##        return ret
-
     def getSize(self, instance):
         """
         getSize(self, instance) => return file size
@@ -352,7 +277,7 @@
 
         # Return it
         return getattr(instance, _preview_ % name, None)
-    
+
     def getIcon(self, instance):
         """
         getIcon(self, instance) => return the underlying file class icon (object)
@@ -393,5 +318,5 @@
     description='Used for storing files with advanced features.',
     )
 
-    
 
+

Modified: zope-attachmentfield/trunk/AttachmentFieldTool.py
===================================================================
--- zope-attachmentfield/trunk/AttachmentFieldTool.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/AttachmentFieldTool.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 30579 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: AttachmentFieldTool.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: AttachmentFieldTool.py 30579 2006-09-19 13:58:17Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -34,6 +34,7 @@
 from OFS.SimpleItem import SimpleItem
 from Products.CMFCore.utils import UniqueObject
 from Globals import InitializeClass
+from zExceptions import BadRequest
 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 
 # CMF imports
@@ -43,10 +44,16 @@
 
 # Other imports
 import AttachmentService
+import AttachmentField
+import FlexStorage
 
 _www = os.path.join(os.path.dirname(__file__), 'www')
 
-class AttachmentFieldTool(UniqueObject, AttachmentService.AttachmentService):
+class AttachmentFieldTool(
+    UniqueObject,
+    AttachmentService.AttachmentService,
+    PropertyManager,
+):
     """
     AttachmentFieldTool tool
     """
@@ -54,20 +61,135 @@
     id = 'portal_attachment'
     meta_type = 'AttachmentField Tool'
     security = ClassSecurityInfo()
-##    manage_options=(
-##        (
-##        { 'label' : 'Overview'
-##        , 'action' : 'manage_overview'
-##        },
-##        ) + 
-##        ActionProviderBase.manage_options + 
-##        PropertyManager.manage_options + 
-##        SimpleItem.manage_options
-##        )
 
-    #
-    #   ZMI methods
-    #
+    _properties = (
+        {
+            'id'  : 'contentDisposition',
+            'type': 'selection',
+            'mode': 'w',
+            'select_variable' : 'getAvailableContentDisposition',
+        },
+    )
 
-    
+    manage_options = (
+        AttachmentService.AttachmentService.manage_options +
+        PropertyManager.manage_options
+    )
+
+    security.declarePrivate('manage_afterAdd')
+    def manage_afterAdd(self, item, container):
+        return self.migrate()
+
+
+    security.declareProtected(CMFCorePermissions.ManagePortal, "migrate")
+    def migrate(self):
+        """
+            Check that all properties are present and correctly initialized.
+            If not, install them with a safe default value.
+            It is safe to call it multiple times.
+        """
+        checkFor = [
+            ("contentDisposition", self.getAvailableContentDisposition()[0]),
+            ("currentFlexStorageBackend", "AttributeStorage"), ## ZODB
+        ]
+        rValue = ""
+        for attr, default in checkFor:
+            if not hasattr(self, attr):
+                setattr(self, attr, default)
+                rValue += "Added: %s\n" % attr
+        if rValue == "":
+            return "Tool was already up to date."
+        return rValue + "\nTool succesfully updated!"
+
+
+    def getAvailableContentDisposition(self):
+        return [
+            "attachment",
+            "inline"
+        ]
+
+    def getAvailableFlexStorageBackends(self):
+        ## FlexStorage object is not singleton and doesn't hold any properties
+        ## of it's own. It is safe to build on the fly instances without damage.
+        return FlexStorage.FlexStorage().getAvailableFlexStorages()
+
+    def getSample(self, type):
+        sampleLinks = {
+            "attachment": self.absolute_url() + "/sample/contentDispositionAttachment",
+            "inline": self.absolute_url() + "/sample/contentDispositionInline",
+        }
+        return sampleLinks[type]
+
+    def getContentDisposition(self):
+        return self.contentDisposition
+
+    def getCurrentFlexStorageBackend(self):
+        return self.currentFlexStorageBackend
+
+    def setCurrentFlexStorageBackend(self, newStorageName):
+        ## FlexStorage object is not singleton and doesn't hold any properties
+        ## of it's own. It is safe to build on the fly instances without damage.
+        FlexStorage.FlexStorage().changeFlexStorageBackend(
+            self,
+            newStorageName,
+            AttachmentField.getContentTypesWithAttachmentFields(self)
+        )
+
+    def manageDownload(self, context, traverse_subpath):
+        """
+            Manage downlad mechanism (headers, etc)
+        """
+
+        request = context.REQUEST
+        response = request.RESPONSE
+
+        if len(traverse_subpath) != 1:
+            raise BadRequest("Attachment download called with wrong reference.")
+
+        fieldName = traverse_subpath[0]
+        field = context.getField(fieldName)
+
+        if not field:
+            raise BadRequest("Attachment download called on unexistent field: %s" % fieldName)
+        elif hasattr(field, 'getFields'):
+            index = int(request.form.get(name))
+            field = field.getFields()[index + 1]
+
+
+        widget = field.widget
+        if hasattr(widget, "contentDisposition"):
+            if widget.contentDisposition in self.getAvailableContentDisposition():
+                ## disposition is defined by widget
+                disposition = widget.contentDisposition
+            else:
+                raise ValueError(
+                    "contentDisposition %s is not in %s." % (
+                        widget.contentDisposition, self.getAvailableContentDisposition()
+                    )
+                )
+        else:
+            ## default site wide choice
+            disposition = self.getContentDisposition()
+
+        ## We have to force disposition to "attachment" when content type is text/*
+        ## Alexander Limi said:
+        ## Crucially, absolutely NO files with the MIME type text/* should ever be  
+        ## rendered inline, since this opens up for uploading HTML files and using  
+        ## them as spam redirection URLs. Internet Explorer renders anything with  
+        ## text/* as HTML, so it is not sufficient to just block text/html,  
+        ## unfortunately.
+
+        contentType = field.getContentType(context)
+        if contentType.startswith("text/"):
+            disposition = "attachment"
+
+        result = field.download(context, request)
+
+        response.setHeader(
+            'Content-Disposition',
+            '%s; filename="%s"' % (disposition, field.getFilename(context))
+        )
+        return result
+
+
 InitializeClass(AttachmentFieldTool)

Modified: zope-attachmentfield/trunk/AttachmentHandler.py
===================================================================
--- zope-attachmentfield/trunk/AttachmentHandler.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/AttachmentHandler.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: AttachmentHandler.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: AttachmentHandler.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -74,20 +74,23 @@
     # Instanciate the class
     handler = handler_class()        # We instanciate it
 
-    # Compute the converter and previewer paths
-    index_path = handler.getIndexPath(None, None)
-    preview_path = handler.getPreviewPath(None, None)
-    if index_path:
-        handler.index_program = getConverterProgram(
-            handler.converter_type,
-            index_path,
+    if handler.is_external_conv:
+        # Compute the converter and previewer paths
+        index_path = handler.getIndexPath(None, None)
+        preview_path = handler.getPreviewPath(None, None)
+        if index_path:
+            handler.index_program = getConverterProgram(
+                handler
             )
-    if preview_path:
-        handler.preview_program = getConverterProgram(
-            handler.converter_type,
-            preview_path,
+        if preview_path:
+            handler.preview_program = getConverterProgram(
+                handler
             )
+    else:
+        handler.index_program = None
+        handler.preview_program = None
 
+
     # Store the class
     class_name = handler_class.__name__
     __HANDLERS__.append((class_name, handler, ))
@@ -112,9 +115,9 @@
     # No match. Have to return the dummy handler
     Log(LOG_DEBUG, "No match, we fall back to the dummy handler", dummy)
     return dummy
-        
 
 
+
 class AbstractHandler(Implicit, ):
     """
     CODING INFORMATION : If you create additional methods or properties in ZAbstractAttachment that must
@@ -138,6 +141,8 @@
         "small_icon_file",                      # (string) of the SMALL icon name IN A PLONE SKIN.
         "content_types",                        # List (of strings) of content_types supported by the class
 
+        "is_external_conv",                     # is the converter using an external programm ?
+        "is_working",                           # is the converter producing anything meaningfull ?
         "index_path",                           # Index program relative path
         "index_arguments",                      # Converter program args. File name will be '%s'.
         "index_encoding",                       # Encoding managed by the encoder (output only - input is nonsence as it's most likely binary data!) or None
@@ -155,6 +160,7 @@
     small_icon_file = INVALID_VALUE
     content_types = INVALID_VALUE               # Supported content-types (tuple of strings)
 
+    is_external_conv = INVALID_VALUE
     index_path = INVALID_VALUE
     index_arguments = INVALID_VALUE
     index_encoding = INVALID_VALUE
@@ -164,7 +170,10 @@
     preview_encoding = INVALID_VALUE
     preview_format = INVALID_VALUE
 
+    program_found = False
+    error = False ## if true, gui will display it.
 
+
     __CHECK_INTERFACE__ = 1             # Special attribute to enforce IF checking
 
     #                                                                   #
@@ -210,7 +219,7 @@
 
     def getIndexableValue(self, field, instance):
         """
-        getIndexableValue(self, field, instance) => (possibliy big) string 
+        getIndexableValue(self, field, instance) => (possibliy big) string
         Return the ZCatalog-indexable string for that type.
         """
         Log(LOG_DEBUG, "converting field", field.getName(), self.index_arguments, self.__class__.__name__)
@@ -307,14 +316,14 @@
             f = open(fn, "w+b")
             f.write(content)
             f.close()
-        
+
             # Call converter in the right directory
             Log(LOG_DEBUG, "Calling converter for", filename, "in directory", tempfile.tempdir)
             index = self.callConverter(
                 program,
-                arguments % (fn, ), 
+                arguments % (fn, ),
                 )
-            
+
         finally:
             # Delete attachment file
             if os.path.isfile(fn):
@@ -327,7 +336,7 @@
             if type(encoding) in (type(''), type(u''), ):
                 Log(LOG_DEBUG, "Encoding", encoding)
                 index = index.decode(encoding, "replace")
-                
+
             elif type(encoding) in (type(None),):
                 pass
 
@@ -337,15 +346,15 @@
                         Log(LOG_DEBUG, "Trying encoding", enc)
                         index = index.decode(enc, "replace")
                         break
-                    
+
                     except UnicodeError:
                         Log(LOG_DEBUG, "Encoding", enc, "failed.")
                         pass
 
         # Return the string
         return index
-        
 
+
     #                                                                   #
     #                         HTML PREVIEW SUPPORT                      #
     #                                                                   #
@@ -356,8 +365,8 @@
     _has_body_end = re.compile(r"""</\s*body""", re.I)
     _strip_body_end = re.compile(r"""</\s*body\s*>.*""", re.I | re.S)
     _strip_tags = re.compile(r"""<[^>]+>""", re.I | re.S)
-    
 
+
     def _html_to_text(self, html):
         """crudely convert html to text"""
         Log(LOG_DEBUG, "Stripping html tags")
@@ -374,7 +383,7 @@
         # Regular file size
         Log(LOG_DEBUG, "Stripping style...")
         text = self._strip_style.sub('', text, )
-        
+
         # _strip_body_start regexp may go in infinite loop
         # if there is no body attribute (in certain conditions)
         if self._has_body_start.search(text) is not None:
@@ -416,7 +425,7 @@
         # Check if we can preview
         if self.preview_arguments is None:
             return None
-        
+
         # Call the converter with the proper arguments
         preview = self._convert(
             field,
@@ -426,7 +435,7 @@
             self.preview_encoding,
             )
         Log(LOG_DEBUG, "Getting preview for file", field.getFilename(instance))
-    
+
         # Return the previewable string
         return self._convertOutput(preview, self.preview_format)
 
@@ -457,7 +466,7 @@
         """
         callConverter(self, program_path, arguments = '', report_errors = 1) => convert file using program_path with given arguments.
         Return the output stream of the converter program.
-        
+
         if stdin is given, it is feed into the program. Else, it is ignored.
         if report_errors is true, 2> ~/tempfile is appended at the end of the command line
         """
@@ -478,7 +487,7 @@
             cmd = "%s 2> %s" % (cmd, errfile, )
         else:
             errfile = None
-        
+
         # Actually execute command
         errors = ""
         curdir = os.getcwd()
@@ -488,7 +497,7 @@
             Log(LOG_DEBUG, "We work in", os.getcwd())
             r = os.popen(cmd, "r")
             idx = r.read()
-            
+
         finally:
             # Go back the the current dir
             os.chdir(curdir)
@@ -502,7 +511,7 @@
                 else:
                     errors = f.read()
                     f.close()
-                    
+
             # Remove the temporary directory
             try:
                 for root, dirs, files in os.walk(tmpdir, topdown=False):
@@ -511,7 +520,7 @@
                     for name in dirs:
                         os.rmdir(os.path.join(root, name))
                 os.rmdir(tmpdir)
-                
+
             except:
                 LogException()
                 Log(LOG_NOTICE, "Could not remove temporary stuff in", tmpdir)
@@ -552,6 +561,32 @@
         text = string.strip(text)
         return text
 
+
+    def getGUIIndexProgramCommand(self, field, instance):
+        if not self.is_working:
+            return "<em>unavailable</em>"
+        if not self.is_external_conv:
+            return "<em>internal</em>"
+        elif self.program_found == False:
+            return self.index_path + " " + self.index_arguments + "<br/><strong>not found</strong>"
+        else:
+            return self.index_path + " " + self.index_arguments
+
+    def getGUIPreviewProgramCommand(self, field, instance):
+        if not self.is_working:
+            return "<em>unavailable</em>"
+        if not self.is_external_conv:
+            return "<em>internal</em>"
+        elif self.program_found == False:
+            return self.preview_path + " " + self.preview_arguments + "<br/><strong>not found</strong>"
+        else:
+            return self.preview_path + " " + self.preview_arguments
+
+    def getError(self, field, instance):
+        if self.error:
+            return "error"
+        return ""
+
 #                                                                       #
 #                       External programs interface                     #
 #                                                                       #
@@ -559,15 +594,20 @@
 PACKAGE_HOME = App.Common.package_home(globals())
 if sys.platform == 'win32':
     # Windows platform
-    def getConverterProgram(conv_type, conv_path):
+    def getConverterProgram(converter):
+        conv_type = converter.converter_type
+        conv_path = converter.index_path
+        is_external_conv = converter.is_external_conv
+
         if conv_path is None:
             return None
         if conv_path.lower() == "type":
             return "type"
 
-        program = '"' + os.path.join(PACKAGE_HOME, "converters", conv_type, "win32", conv_path, ) + '"' 
+        program = '"' + os.path.join(PACKAGE_HOME, "converters", conv_type, "win32", conv_path, ) + '"'
         if os.path.isfile(program[1:-1]):
             Log(LOG_DEBUG, "Using '%s' program to convert %s attachments." % (program, conv_type))
+            converter.program_found = True
         else:
             Log(
                 LOG_WARNING,
@@ -576,16 +616,24 @@
                 ),
                 )
             program = None
-            
+            converter.error = True
+
         return program
 
 else:
-    def getConverterProgram(conv_type, conv_path):
+    def getConverterProgram(converter):
+        conv_type = converter.converter_type
+        conv_path = converter.index_path
+        is_external_conv = converter.is_external_conv
         # Unix platform
         import commands
-        if conv_path is None:
+        if not is_external_conv:
             return None         # In case we don't need a program
 
+        if "(internal)" == conv_path or conv_path is None:
+            raise RuntimeError("converter path is invalid, but external conv has been set.")
+
+
         # Try to find the real full path of the program
         program = conv_path
         program = commands.getoutput("which %s" % (program))
@@ -596,8 +644,10 @@
                     conv_path, conv_type,
                     ),
                 )
+            converter.error = True
         else:
             program = string.strip(program)
             Log(LOG_DEBUG, "Using '%s' program to convert %s attachments." % (program, conv_type))
-            
+            converter.program_found = True
+
         return program

Modified: zope-attachmentfield/trunk/AttachmentService.py
===================================================================
--- zope-attachmentfield/trunk/AttachmentService.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/AttachmentService.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -21,9 +21,9 @@
 
 Some of this is taken from PlacelessTranslationService's logic.
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25973 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: AttachmentService.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: AttachmentService.py 25973 2006-07-10 08:46:59Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -89,7 +89,15 @@
     def __init__(self, ):
         self._instance_version = ATTACHMENTFIELD_VERSION
 
+    def isListErroneous(self):
+        import AttachmentHandler
 
+        handlers = AttachmentHandler.__HANDLERS__
+        for name, handler in handlers:
+            if handler.error:
+                return True
+        return False
+
     def listHandlerValues(self,):
         """
         listHandlerValues(self,) => List of attachment handlers
@@ -105,16 +113,19 @@
             ("converter_type", "getContentType", ),
             ("icon_file", "getIconFile", ),
             ("small_icon_file", "getSmallIconFile", ),
-            ("content_types", "getContentTypes", ), 
+            ("content_types", "getContentTypes", ),
             ("index_path", "getIndexPath", ),
             ("index_arguments", "getIndexArguments", ),
+            ("index_program_gui", "getGUIIndexProgramCommand", ),
             ("index_encoding", "getIndexEncoding", ),
             ("preview_path", "getPreviewPath", ),
             ("preview_arguments", "getPreviewArguments", ),
             ("preview_encoding", "getPreviewEncoding", ),
             ("preview_format", "getPreviewFormat", ),
+            ("preview_program_gui", "getGUIPreviewProgramCommand", ),
+            ("error", "getError", ),
             )
-        
+
         ret = {}
 
         for name, handler in handlers:
@@ -135,7 +146,9 @@
                     h[pty] = None
             ret[name] = h
 
-        return ret.values()
+        values = ret.values()
+        values.sort(lambda x, y: cmp(x["class"], y["class"]))
+        return values
 
 
     security.declareProtected(view_management_screens, "listAvailableEncodings")
@@ -173,7 +186,7 @@
         filefield = obj.getField('file')
         content_type = string.lower(file.headers['Content-Type'])
         filename = file.filename
-        
+
         # Process what happens
         content = filefield.get(obj)
         filename = filefield.getFilename(obj)
@@ -274,7 +287,7 @@
             index = "%d words." % (
                 len(string.split(index)),
                 )
-                
+
         except:
             s = StringIO.StringIO()
             traceback.print_exc(file = s, )

Modified: zope-attachmentfield/trunk/AudioAttachment.py
===================================================================
--- zope-attachmentfield/trunk/AudioAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/AudioAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: AudioAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: AudioAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -45,6 +45,9 @@
         "audio/x-mpegurl",
         )
 
+
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/AutocadAttachment.py
===================================================================
--- zope-attachmentfield/trunk/AutocadAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/AutocadAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: AutocadAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: AutocadAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -39,6 +39,8 @@
     small_icon_file = "autocad_small.gif"
     content_types = ('application/acad', 'application/dxf', )
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None
@@ -47,7 +49,7 @@
     preview_arguments = None
     preview_encoding = None
     preview_format = None
-    
 
 
+
 AttachmentHandler.registerHandler(AutocadAttachment)

Modified: zope-attachmentfield/trunk/CHANGES
===================================================================
--- zope-attachmentfield/trunk/CHANGES	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/CHANGES	2006-10-13 20:51:32 UTC (rev 304)
@@ -8,21 +8,46 @@
 * MSWord images support
 
 * Support additional preview for mp3, images, ...
-  
+
 * Add MD5 to check files are not corrupted
 
 * Replace ComputedAttribute by python property() functionnality (Zope 2.8)
 
-1.4 - 2005-06-08
+1.3.10 - 2006-09-19
+====================
+
+* Fix a security hole (inlined text/*)
+
+* Fix SF bug #1542861
+
+1.3.9 - 2006-07-31
 ==================
 
-* Ignore images in MSWord. Added option "-1" to wvWare.exe (2005-06-08 MR)
+* Fix broken installation method (thanks to adf)
 
-* Limit maximum cols and rows for Excel to 100. Configurable in global_symbols.py (2005-06-08 MR)
+1.3.8 - 2006-07-25
+==================
 
-1.3.5 - 2005-05-14
+* introduce the flex storage that allow attachment field to store its content
+  to be stored either in ZODB or with FSS.
+
+1.3.7 - 2006-07-10
 ==================
 
+* fix #1505660 (sourceforge): import statement in OOConverter (2006-06-14 BM)
+
+* add inline (or attachment) view
+
+1.3.6 - 2006-06-08
+==================
+
+* Ignore images in MSWord. Added option "-1" to wvWare.exe (2006-06-08 MR)
+
+* Limit maximum cols and rows for Excel to 100. Configurable in global_symbols.py (2006-06-08 MR)
+
+1.3.5 - 2006-05-14
+==================
+
 * Use of global external editor link and webdav lock (yeah)
 
 * Removed Extenal Editor link (cannot work at field level)
@@ -32,9 +57,9 @@
 1.3.4 - 2006-05-2
 =================
 
-* Add base compatibility with CompoundField product (2005-03-15 ED)
+* Add base compatibility with CompoundField product (2006-03-15 ED)
 
-* Fix lack of permissions when running unit tests (2005-03-15 ED)
+* Fix lack of permissions when running unit tests (2006-03-15 ED)
 
 * Added Photoshop attachment plugin
 
@@ -67,7 +92,7 @@
 
 * Fix an infinite loop which was hanging Zope at 100% CPU
 
-[v1.3RC4 - 20050729] 
+[v1.3RC4 - 20050729]
 
 * Fixing bug in download method of AttachmentField using FileField
   instead of Field.FileField
@@ -75,7 +100,7 @@
 [v1.3RC3 - 20050524]
 
 * Supports correctly MSWord again under Win32
-  
+
 * Fixed Installer to uninstall configlet
 
 * Fixed an unicode bug with PortalTransformsAttachment
@@ -118,7 +143,7 @@
 
 * Code page translation in the callConverter()-like methods
 
-* Archetypes' automatic SearchableText support (contentType argument in get(), 
+* Archetypes' automatic SearchableText support (contentType argument in get(),
   AND 'searchable' field parameter support; eg. we'd disable automatic indexing
   if 'searchable' is false).
 

Modified: zope-attachmentfield/trunk/CompressedAttachment.py
===================================================================
--- zope-attachmentfield/trunk/CompressedAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/CompressedAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: CompressedAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: CompressedAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -49,6 +49,8 @@
         )
 
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/DummyAttachment.py
===================================================================
--- zope-attachmentfield/trunk/DummyAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/DummyAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: DummyAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: DummyAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -40,11 +40,13 @@
     small_icon_file = "unknown_small.gif"
     content_types = (None, )
     converter_type = None
-    
+
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None
-    
+
     preview_path = None
     preview_arguments = None
     preview_encoding = None

Modified: zope-attachmentfield/trunk/Extensions/Install.py
===================================================================
--- zope-attachmentfield/trunk/Extensions/Install.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/Extensions/Install.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 26537 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: Install.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: Install.py 26537 2006-07-31 08:29:18Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -41,38 +41,39 @@
 
 def install(self):
     out = StringIO.StringIO()
-    
+
     # Install skin
     install_subskin(self, out, product_globals)
-    
+
     # Install configlet
     cptool = getToolByName(self, 'portal_controlpanel')
     try:
         cptool.registerConfiglet(**attachmentfield_prefs_configlet)
     except KeyError:
         pass
-    
+
     # Install tool
     add_tool = self.manage_addProduct[PROJECTNAME].manage_addTool
     tool = getattr(self, AttachmentFieldTool.AttachmentFieldTool.id, None)
     if tool is None:
         add_tool(AttachmentFieldTool.AttachmentFieldTool.meta_type)
+    tool = getattr(self, AttachmentFieldTool.AttachmentFieldTool.id, None)
+    print >> out, tool.migrate()
+    print >> out, "Successfully installed %s." % PROJECTNAME
 
-    print >> out, "Successfully installed %s." % PROJECTNAME
-    
     return out.getvalue()
 
 def uninstall(self):
     out = StringIO.StringIO()
-    
+
     # Uninstall configlets
     try:
         cptool = getToolByName(self, 'portal_controlpanel')
         cptool.unregisterApplication(PROJECTNAME)
     except:
         LogException()
-    
+
     print >> out, "Successfully uninstalled %s." % PROJECTNAME
-    
+
     return out.getvalue()
 

Modified: zope-attachmentfield/trunk/FlashAttachment.py
===================================================================
--- zope-attachmentfield/trunk/FlashAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/FlashAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: FlashAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: FlashAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -39,6 +39,8 @@
     small_icon_file = "flash_small.gif"
     content_types = ('application/x-shockwave-flash','application/swf')
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Copied: zope-attachmentfield/trunk/FlexStorage.py (from rev 298, zope-attachmentfield/branches/upstream/current/FlexStorage.py)
===================================================================
--- zope-attachmentfield/trunk/FlexStorage.py	                        (rev 0)
+++ zope-attachmentfield/trunk/FlexStorage.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -0,0 +1,208 @@
+## -*- coding: utf-8 -*-
+## Copyright (C) 2006 Ingeniweb
+
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License
+## along with this program; see the file COPYING. If not, write to the
+## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import StringIO
+
+from AccessControl import ClassSecurityInfo
+
+from Products.CMFCore.utils import getToolByName
+from Products.CMFCore import CMFCorePermissions
+
+from Products.Archetypes.BaseUnit import BaseUnit
+from Products.Archetypes.Storage import StorageLayer
+from Products.Archetypes.interfaces.storage import IStorage
+from Products.Archetypes.interfaces.layer import ILayer
+
+
+class FlexStorage(StorageLayer):
+    """
+        FlexStorage is a storage proxy. It can switch between different storages for
+        content on demand. In example, it can switch data from ZODB (Attribute Storage)
+        to file system (FSS).
+    """
+
+    __implements__ = StorageLayer.__implements__
+
+    ##### WARNING #####
+    # All methods or attribute MUST be different from anything that can be found
+    # in a storage, or it must call this method on the storage
+
+    ## This list contains all the storage that can be used
+    ## First data is the import statement. If import fails, the next storage is tried
+    ## second is the storage name, and the storage class name that will be used
+    ## third is a flog indicating if this is the default choice
+    supportedFlexStorageMethods = [
+        ("from Products.Archetypes.Storage import AttributeStorage", "AttributeStorage"),
+        ("from Products.FileSystemStorage.FileSystemStorage import FileSystemStorage", "FileSystemStorage"),
+    ]
+
+    security = ClassSecurityInfo()
+
+    def __init__(self):
+        self.flexStorages = {}
+        for storageMethodImport, storageName in self.supportedFlexStorageMethods:
+            try:
+                exec storageMethodImport
+                self.flexStorages[storageName] = eval("%s()" % storageName)
+            except ImportError, e:
+                print e
+                ### XXX todo log a warning
+                pass
+
+    security.declarePublic('getAvailableFlexStorages')
+    def getAvailableFlexStorages(self):
+        """
+            Return the list of storage that are working (ie classes are found)
+        """
+        return self.flexStorages.keys()
+
+    security.declarePublic('getName')
+    def getName(self):
+        return self.__class__.__name__
+
+    def __repr__(self):
+        return "<Storage %s>" % (self.getName())
+
+    def __cmp__(self, other):
+        return cmp(self.getName(), other.getName())
+
+
+#    def __getattr__(self, name):
+#        """
+#            Return an attribute of the underlying storage system.
+#
+#            This method is only called if no attribute is found in this class.
+#            It's a fallback method.
+#        """
+#        ## we have to check if the name is prefixed
+#        print "requesting %s" % name
+#        return getattr(self.getFlexStorageBackend(), name)
+
+
+    security.declarePrivate('initializeInstance')
+    def initializeInstance(self, instance, item=None, container=None):
+        storage = self.getFlexStorageBackend(instance)
+        if ILayer.isImplementedBy(storage):
+            return storage.initializeInstance(instance, item, container)
+
+    security.declarePrivate('cleanupInstance')
+    def cleanupInstance(self, instance, item=None, container=None):
+        storage = self.getFlexStorageBackend(instance)
+        if ILayer.isImplementedBy(storage):
+            return storage.cleanupInstance(instance, item, container)
+
+    security.declarePrivate('initializeField')
+    def initializeField(self, instance, field):
+        storage = self.getFlexStorageBackend(instance)
+        if ILayer.isImplementedBy(storage):
+            return storage.initializeField(instance, field)
+
+    security.declarePrivate('cleanupField')
+    def cleanupField(self, instance, field):
+        storage = self.getFlexStorageBackend(instance)
+        if ILayer.isImplementedBy(storage):
+            return storage.cleanupField(instance, field)
+
+    def get(self, name, instance, **kwargs):
+        storage = self.getFlexStorageBackend(instance)
+        return storage.get(name, instance, **kwargs)
+
+    def set(self, name, instance, value, **kwargs):
+        return self.getFlexStorageBackend(instance).set(name, instance, value, **kwargs)
+
+    def unset(self, name, instance, **kwargs):
+        return self.getFlexStorageBackend(instance).unset(name, instance, **kwargs)
+
+    security.declarePublic('getFlexStorageBackend')
+    def getFlexStorageBackend(self, instance):
+        """
+            Return the name of the currently used storage backend
+        """
+        aTool = getToolByName(instance, 'portal_attachment')
+        currentFlexStorageBackend = aTool.currentFlexStorageBackend
+        if currentFlexStorageBackend in self.flexStorages.keys():
+            return self.flexStorages[currentFlexStorageBackend]
+        else:
+            raise RuntimeError("%s requested, but this storage has not been initialized." % currentFlexStorageBackend)
+
+    security.declareProtected(CMFCorePermissions.ManagePortal, "changeFlexStorageBackend")
+    def changeFlexStorageBackend(self, instance, newStorageName, typesWithAF):
+        """
+            Change the backend used to store data. Migrate the already existing
+            fields.
+        """
+        aTool = getToolByName(instance, 'portal_attachment')
+        if aTool.currentFlexStorageBackend == newStorageName:
+            return
+        oldStorage = self.getFlexStorageBackend(instance)
+        aTool.currentFlexStorageBackend = newStorageName
+        newStorage = self.getFlexStorageBackend(instance)
+
+        cat = getToolByName(instance, 'portal_catalog')
+        brains = cat({'portal_type': typesWithAF.keys()})
+        out = StringIO.StringIO()
+        for b in brains:
+            o = b.getObject()
+            fields = typesWithAF[o.portal_type]
+            self.migrateContent(oldStorage, newStorage, o, fields, out)
+            print >> out, ""
+
+        return out.getvalue()
+
+    security.declarePrivate('migrateContent')
+    def migrateContent(self, oldStorage, newStorage, content, fieldNames, out):
+        """
+            Change the storage backend of one content.
+            oldStorage is the old storage where we get the data (and remove it)
+            newStorage is the storage where we put this data
+            content is the content
+        """
+        print >> out, '/'.join(content.getPhysicalPath()), ":",
+
+        for name in fieldNames:
+            print >> out, "'%s'" % name,
+            f = content.getField(name)
+            # error if field has already a content
+            #if f.get_size(content) != 0:
+            #    raise RuntimeError("already set")
+
+            # get content from old storage and delete old storage
+            try:
+                value = oldStorage.get(name, content)
+            except AttributeError:
+                print >> out, "no old value",
+                continue
+
+            # Unwrap value
+            data = BaseUnit(
+                name,
+                str(value),
+                instance=content,
+                filename=getattr(value, "filename", "unknowFilename"),
+                mimetype=value.getContentType(),
+            )
+
+            ### newStorage.initializeField(content, f) #FIXME: really needed?
+            f.set(content, data)
+            oldStorage.unset(name, content)
+            # unset empty files, this avoid empty files on disk
+            if f.get_size(content) == 0:
+                print >> out, "no data, so unset",
+                f.set(content, "DELETE_FILE")
+
+            print >> out, ".",
+

Modified: zope-attachmentfield/trunk/HTMLAttachment.py
===================================================================
--- zope-attachmentfield/trunk/HTMLAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/HTMLAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: HTMLAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: HTMLAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -48,6 +48,8 @@
     content_types = ('text/html', )
     converter_type = "HTML"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"%s"
     index_encoding = None

Modified: zope-attachmentfield/trunk/ImageAttachment.py
===================================================================
--- zope-attachmentfield/trunk/ImageAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/ImageAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: ImageAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: ImageAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -50,6 +50,8 @@
         )
     converter_type = "Image"
 
+    is_external_conv = False
+    is_working = True
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/MSAccessAttachment.py
===================================================================
--- zope-attachmentfield/trunk/MSAccessAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/MSAccessAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: MSAccessAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: MSAccessAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -39,6 +39,8 @@
     small_icon_file = "access_small.gif"
     content_types = ('application/msaccess', 'application/vnd.ms-access', )
 
+    is_external_conv = False
+    is_working = True
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/MSExcelAttachment.py
===================================================================
--- zope-attachmentfield/trunk/MSExcelAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/MSExcelAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 24575 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: MSExcelAttachment.py 24575 2006-06-08 11:33:36Z roeder $
+# $Id: MSExcelAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -50,6 +50,8 @@
     content_types = ('application/excel', 'application/x-excel', 'application/excel', 'application/x-msexcel', 'application/vnd.ms-excel', )
     converter_type = "MSExcel"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"-xc:0-%d -xr:0-%d"%(MAX_COLS_EXCEL, MAX_ROWS_EXCEL) + r" %s"
     index_encoding = ("CP1252", "utf8", )

Modified: zope-attachmentfield/trunk/MSPowerpointAttachment.py
===================================================================
--- zope-attachmentfield/trunk/MSPowerpointAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/MSPowerpointAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: MSPowerpointAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: MSPowerpointAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -47,6 +47,8 @@
     content_types = ('application/powerpoint', 'application/mspowerpoint', 'application/x-powerpoint', 'application/x-mspowerpoint', 'application/vnd.ms-powerpoint', )
     converter_type = "MSPowerpoint"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"%s"
     index_encoding = ("CP1252", "utf8", )

Modified: zope-attachmentfield/trunk/MSProjectAttachment.py
===================================================================
--- zope-attachmentfield/trunk/MSProjectAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/MSProjectAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: MSProjectAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: MSProjectAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -39,6 +39,8 @@
     small_icon_file = "msproject_small.gif"
     content_types = ('application/msproject', 'application/vnd.ms-project', )
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/MSWordAttachment.py
===================================================================
--- zope-attachmentfield/trunk/MSWordAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/MSWordAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 24578 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: MSWordAttachment.py 24578 2006-06-08 11:37:48Z roeder $
+# $Id: MSWordAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -46,6 +46,8 @@
     content_types = ('application/msword', )
     converter_type = "MSWord"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"-1 %s"          # XXX SHOULD BE "-d DIR %s"
     index_encoding = ("CP1252", "utf8", "latin1", )

Modified: zope-attachmentfield/trunk/OO2Attachment.py
===================================================================
--- zope-attachmentfield/trunk/OO2Attachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/OO2Attachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -53,6 +53,8 @@
         'application/vnd.oasis.opendocument.text-template',
         )
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/OOAttachment.py
===================================================================
--- zope-attachmentfield/trunk/OOAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/OOAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -20,9 +20,9 @@
 programs to convert / preview stuff.
 It's an abstract class and is meant to be overloaded in content-type specific classes.
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: OOAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: OOAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -47,7 +47,7 @@
     """
     An openoffice attachment
     """
-    __CHECK_INTERFACE__ = 0             # Disable IF checking
+    __CHECK_INTERFACE__ = 1
     icon_file = "oo.gif"
     small_icon_file = "oo_small.gif"
     content_types = (
@@ -64,11 +64,13 @@
         )
     converter_type = "OpenOffice"
 
-    index_path = "(internal)"
+    is_external_conv = False
+    is_working = True
+    index_path = None
     index_arguments = None
     index_encoding = ("CP1252", "utf8", "latin1", )
-    
-    preview_path = "(internal)"
+
+    preview_path = None
     preview_arguments = None
     preview_format = "html"
     preview_encoding = ("CP1252", "utf8", "latin1", )
@@ -85,7 +87,7 @@
 
     def getIndexableValue(self, field, instance):
         """
-        getIndexableValue(self, field, instance) => (possibliy big) string 
+        getIndexableValue(self, field, instance) => (possibliy big) string
         Return the ZCatalog-indexable string for that type.
         """
         Log(LOG_DEBUG, "getIndexableValue")
@@ -114,12 +116,12 @@
         Log(LOG_DEBUG, "convert...")
         cnv = oo_to_html()
         return self._html_to_text(cnv.convert_(content,), )
-    
+
     def convertStringToPreview(self, content, content_type, instance):
         """
         convertStringToPreview(self, content) => Utility to convert a string to HTML
         using the converter stuff.
-        """    
+        """
         Log(LOG_DEBUG, "convert...")
         cnv = oo_to_html()
         return self._convertOutput(cnv.convert_(content,), "html")
@@ -140,7 +142,7 @@
 ##                    Log(LOG_DEBUG, "Trying encoding", enc)
 ##                    output = output.decode(enc, )
 ##                    break
-                    
+
 ##                except UnicodeError:
 ##                    Log(LOG_DEBUG, "Encoding", enc, "failed.")
 ##                    pass
@@ -156,6 +158,6 @@
     Log(LOG_WARNING, """libxml2 or libxslt not available. Under windows, download it at http://users.skynet.be/sbi/libxml-python/
     Open-Office indexing will be disabled.""")
 else:
-    import ooconverter
+    from ooconverter import oo_to_html
     AttachmentHandler.registerHandler(OOAttachment)
 

Modified: zope-attachmentfield/trunk/PDFAttachment.py
===================================================================
--- zope-attachmentfield/trunk/PDFAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/PDFAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: PDFAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: PDFAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -48,6 +48,8 @@
     content_types = ('application/pdf', )
     converter_type = "PDF"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"%s -enc UTF-8 -"
     index_encoding = "utf8"

Modified: zope-attachmentfield/trunk/PhotoshopAttachment.py
===================================================================
--- zope-attachmentfield/trunk/PhotoshopAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/PhotoshopAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -45,6 +45,8 @@
                      "application/x-photoshop",
                      "zz-application/zz-winassoc-psd",)
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/PortalTransformsAttachment.py
===================================================================
--- zope-attachmentfield/trunk/PortalTransformsAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/PortalTransformsAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -20,9 +20,9 @@
 programs to convert / preview stuff.
 It's an abstract class and is meant to be overloaded in content-type specific classes.
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: PortalTransformsAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: PortalTransformsAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -52,10 +52,27 @@
 
     It does most of the work for all plugins he's aware of.
     """
-    __CHECK_INTERFACE__ = 0             # Disable IF checking
+    __CHECK_INTERFACE__ = 1
     preview_path = None
+    preview_arguments = None
+    preview_encoding = None
+    preview_format = None
+
     index_path = None
+    converter_type = "Plone Portal transform"
+    icon_file = "unknow.gif"
+    small_icon_file = "unknow_small.gif"
+    content_types=(
+        "none/none",
+    )
+    index_path = None
+    index_arguments = None
+    index_encoding = None
 
+    is_external_conv = False
+    is_working = True
+
+
     # Init method
     def getTransforms(self, field, instance):
         # Loop registered portal transforms to find those which are able to handle
@@ -104,7 +121,7 @@
         if not t:
             return self.unknown_icon_file
         return t[0].icon_path
-        
+
     def getSmallIconFile(self, field, instance):
         # We use Mimetypesregistry to get the icon path
         # If no field has been supplied, we return a default 'unknown' icon
@@ -125,7 +142,7 @@
 
     def getIndexableValue(self, field, instance):
         """
-        getIndexableValue(self, field, instance) => (possibliy big) string 
+        getIndexableValue(self, field, instance) => (possibliy big) string
         Return the ZCatalog-indexable string for that type.
         """
         content = field.get(instance)
@@ -164,7 +181,7 @@
         """
         convertStringToPreview(self, content) => Utility to convert a string to HTML
         using the converter stuff.
-        """    
+        """
         # Return the previewable string
         preview = self._convertStringToMime(content, content_type, instance, "text/html")
         return self._convertOutput(preview, "html")
@@ -176,7 +193,7 @@
         ct = content_type
         if not trans['html_paths'].get(ct, None):
             raise ValueError, "No converter found for content type '%s'" % (ct,)
-        
+
         # Convert it to plain text
         pt = self.getPortalTransforms(None, instance, )
         out = pt.convertTo(
@@ -199,7 +216,7 @@
                     Log(LOG_DEBUG, "Trying encoding", enc)
                     output = output.decode(enc, )
                     break
-                    
+
                 except UnicodeError:
                     Log(LOG_DEBUG, "Encoding", enc, "failed.")
                     pass

Modified: zope-attachmentfield/trunk/RTFAttachment.py
===================================================================
--- zope-attachmentfield/trunk/RTFAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/RTFAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: RTFAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: RTFAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -52,6 +52,8 @@
         )
     converter_type = "RTF"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"%s --nopict -t text"
     index_encoding = ("CP1252", "utf8", "latin1", )

Modified: zope-attachmentfield/trunk/TarGzAttachment.py
===================================================================
--- zope-attachmentfield/trunk/TarGzAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/TarGzAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: TarGzAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: TarGzAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -49,6 +49,8 @@
         'application/tgz',
         )
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r'-tzvf %s'
     index_encoding = ('iso-8859-15', 'utf8')

Modified: zope-attachmentfield/trunk/TextAttachment.py
===================================================================
--- zope-attachmentfield/trunk/TextAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/TextAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: TextAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: TextAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -44,6 +44,8 @@
     content_types = ('text/plain', )
     converter_type = "Text"
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r"%s"
     index_encoding = None

Modified: zope-attachmentfield/trunk/VideoAttachment.py
===================================================================
--- zope-attachmentfield/trunk/VideoAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/VideoAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: VideoAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: VideoAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -51,6 +51,8 @@
         "video/x-sgi-movie",
         )
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/VisioAttachment.py
===================================================================
--- zope-attachmentfield/trunk/VisioAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/VisioAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: VisioAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: VisioAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -47,6 +47,8 @@
                      'application/vnd.ms-visio.viewer',
                      )
 
+    is_external_conv = False
+    is_working = False
     index_path = None
     index_arguments = None
     index_encoding = None

Modified: zope-attachmentfield/trunk/ZipAttachment.py
===================================================================
--- zope-attachmentfield/trunk/ZipAttachment.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/ZipAttachment.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -18,9 +18,9 @@
 """
 AttchmentField
 """
-__version__ = "$Revision: 23006 $"
+__version__ = "$Revision: 25863 $"
 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
-# $Id: ZipAttachment.py 23006 2006-05-02 20:25:43Z encolpe $
+# $Id: ZipAttachment.py 25863 2006-07-07 14:47:14Z manuco $
 __docformat__ = 'restructuredtext'
 
 
@@ -48,6 +48,8 @@
         'application/x-zip-compressed',
         )
 
+    is_external_conv = True
+    is_working = True
     index_path = program
     index_arguments = r'-2z %s'
     index_encoding = ('iso-8859-15', 'utf8')
@@ -56,7 +58,7 @@
     preview_arguments = r'-2zt %s'
     preview_encoding = ('iso-8859-15', 'utf8')
     preview_format = 'pre'
-    
 
 
+
 AttachmentHandler.registerHandler(ZipAttachment)

Modified: zope-attachmentfield/trunk/cvs2cl.pl
===================================================================
--- zope-attachmentfield/trunk/cvs2cl.pl	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/cvs2cl.pl	2006-10-13 20:51:32 UTC (rev 304)
@@ -10,7 +10,7 @@
 ##############################################################
 
 ## $Revision: 15769 $
-## $Date: 2004-10-14 17:33:28 +0200 (Thu, 14 Oct 2004) $
+## $Date: 2004-10-14 17:33:28 +0200 (jeu, 14 oct 2004) $
 ## $Author: pjgrizel $
 ##
 ##   (C) 2001,2002,2003 Martyn J. Pearce <fluffy at cpan.org>, under the GNU GPL.

Modified: zope-attachmentfield/trunk/debian/changelog
===================================================================
--- zope-attachmentfield/trunk/debian/changelog	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/debian/changelog	2006-10-13 20:51:32 UTC (rev 304)
@@ -1,3 +1,9 @@
+zope-attachmentfield (1.3.10-1) UNRELEASED; urgency=low
+
+  * New upstream release
+
+ -- Jérémy Bobbio <jeremy.bobbio at etu.upmc.fr>  Fri, 13 Oct 2006 22:50:54 +0200
+
 zope-attachmentfield (1.3.6-1) unstable; urgency=low
 
   * New upstream release

Copied: zope-attachmentfield/trunk/doc/HOWTO (from rev 298, zope-attachmentfield/branches/upstream/current/doc/HOWTO)
===================================================================
--- zope-attachmentfield/trunk/doc/HOWTO	                        (rev 0)
+++ zope-attachmentfield/trunk/doc/HOWTO	2006-10-13 20:51:32 UTC (rev 304)
@@ -0,0 +1,47 @@
+This file explain a little how to use Attachment Field.
+
+In an archetype content type, you can add an attachment field like any other fields.
+Just write a schema like this:
+
+MySchema = BaseSchema.copy() + Schema((
+
+    ImageField(
+        'logo',
+        widget = ImageWidget(
+            label = "Logo",
+        ),
+    ),
+
+    StringField(
+        'name',
+        widget = StringWidget(
+            label = "Name",
+        ),
+    ),
+
+    AttachmentField(
+        'myFile',
+        widget = AttachmentWidget(
+            label = "My File",
+        ),
+    ),
+))
+
+You will have a content type with three files (an image, a name and an attachment
+field).
+
+You can customize the way files are displayed, field by field, with a special
+attribute of the AttachmentWidget :
+
+    AttachmentField(
+        'myFile',
+        widget = AttachmentWidget(
+            label = "My File",
+->          contentDisposition = "attachment"        <-
+        ),
+    ),
+
+Possible values :
+- attachment when you want the browser asks the user for a plce to save the file
+- inline when you want the browser displays the content inside its window (if possible)
+

Copied: zope-attachmentfield/trunk/i18n/attachmentfield-cs.po (from rev 298, zope-attachmentfield/branches/upstream/current/i18n/attachmentfield-cs.po)
===================================================================
--- zope-attachmentfield/trunk/i18n/attachmentfield-cs.po	                        (rev 0)
+++ zope-attachmentfield/trunk/i18n/attachmentfield-cs.po	2006-10-13 20:51:32 UTC (rev 304)
@@ -0,0 +1,39 @@
+# Gettext Message File for AttachmentField.
+#  <team at language.com>, 2003
+msgid ""
+msgstr ""
+"Project-Id-Version: AttachmentField\n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2006-07-01 14:23+0100\n"
+"Last-Translator: Radim Novotny <novotny.radim at gmail.com>\n"
+"Language-Team: CoreNet <info at corenet.cz>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Language-code: cs\n"
+"Language-name: Czech\n"
+"Preferred-encodings: utf-8\n"
+"Domain: attachmentfield\n"
+
+msgid "Preview"
+msgstr "Náhled"
+
+msgid "label_edit"
+msgstr "Úpravy"
+
+msgid "Edit with External Editor"
+msgstr "Upravit v externím editoru"
+
+msgid "This attachment is not indexed"
+msgstr "Soubor není indexován"
+
+msgid "label_nochange"
+msgstr "Beze změn"
+
+msgid "label_delete_file"
+msgstr "Smazat soubor"
+
+msgid "label_upload_file"
+msgstr "Vložit soubor"
+

Modified: zope-attachmentfield/trunk/skins/attachmentfield/attachment_download.py
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/attachment_download.py	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/skins/attachmentfield/attachment_download.py	2006-10-13 20:51:32 UTC (rev 304)
@@ -1,48 +1,3 @@
 ##parameters=
 
-NotFound = "NotFound"
-request = context.REQUEST
-response = request.RESPONSE
-
-if len(traverse_subpath) != 1:
-    raise NotFound, "Unknown page."
-
-name = traverse_subpath[0]
-field = context.getField(name)
-
-if not field:
-    raise NotFound, "Unknown page."
-elif hasattr(field, 'getFields'):
-    index = int(request.form.get(name))
-    field = field.getFields()[index + 1]
-
-accessor = field.getAccessor(context)
-
-if accessor is None:
-    raise NotFound, "Unknown page."
-
-obj = accessor()
-
-if hasattr(obj.aq_explicit, 'download'):
-    return obj.download(request)
-else:
-    data = ''
-    filename = ''
-    content_type = 'application/octet-stream'
-    size = 0
-    
-    if hasattr(obj.aq_explicit, 'data'):
-        # handle OFS.Image.File and OFS.Image.Image
-        data = str(obj.data)
-        filename = obj.title
-        content_type = obj.getContentType()
-        size = obj.get_size()
-    else:
-        data = str(obj)
-        size = len(data)
-        
-    response.setHeader('Content-Disposition',
-                       'attachment; filename="%s"' % filename)
-    response.setHeader('Content-Type', content_type)
-    response.setHeader('Content-Length', size)
-    response.write(data)
+return context.portal_attachment.manageDownload(context, traverse_subpath)

Modified: zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt	2006-10-13 20:51:32 UTC (rev 304)
@@ -1,8 +1,15 @@
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
-      lang="en"
-      metal:use-macro="here/prefs_main_template/macros/master"
-      i18n:domain="attachmentfield">
+<html
+  xmlns="http://www.w3.org/1999/xhtml"
+  xml:lang="en"
+  lang="en"
+  metal:use-macro="here/prefs_main_template/macros/master"
+  i18n:domain="attachmentfield"
+  xmlns:tal="http://xml.zope.org/namespaces/tal"
+  xmlns:metal="http://xml.zope.org/namespaces/metal"
+  xmlns:i18n="http://xml.zope.org/namespaces/i18n"
 
+>
+
   <metal:block fill-slot="top_slot"
                tal:define="dummy python:request.set('disable_border',1)" />
   <body>
@@ -10,7 +17,7 @@
       <h1 i18n:translate="heading_attachmentfield">
         AttachmentField preferences
       </h1>
-      
+
       <a href=""
          class="link-parent"
          tal:attributes="href string: $portal_url/plone_control_panel"
@@ -18,20 +25,135 @@
          i18n:translate="label_up_to_plone_setup">
       Up to Plone Setup
       </a>
-            
+
       <form name="edit_form"
             action="."
             method="post"
             enctype="multipart/form-data"
-            tal:attributes="action string:${here/getId}/${template/getId}" 
+            tal:attributes="action string:${here/getId}/${template/getId}"
             tal:define="errors options/state/getErrors;
                         atool python:here.portal_attachment;
                         ">
+        <fieldset>
+          <legend i18n:translate="">Configuration</legend>
+          <div
+            class="field"
+            tal:define="tabindex tabindex/next;
+                        value python:request.get('contentDisposition', atool.getContentDisposition())"
+          >
+            <label
+              i18n:translate="contentDisposition"
+            >
+              Content Disposition
+            </label>
 
+            <div class="formHelp" i18n:translate="help_contentDisposition">
+              Choose here the global setting for the content disposition that will
+              be used when downloading a file.<br/>"Inline" means that the content will
+              be displayed inside the browser (if possible, perhaps with pluggins).
+              <br/>"Attachment" means that the browser will ask the user for a filename
+              in order to save the file on the user's file system.
+              <br/>You can test the two methods. Note that, for security reasons,
+              the inline option will not be used for text content types
+              ("text/plain", "text/html" for example).
+            </div>
+            <tal:loop repeat="availableCD atool/getAvailableContentDisposition">
+              <input
+                type="radio"
+                name="content_disposition"
+                class="noborder"
+                tal:attributes="checked python:test(value==availableCD, 'checked', '');
+                                tabindex tabindex;
+                                value availableCD;
+                                id availableCD;
+                                "
+              />
+              <label
+                tal:attributes="for availableCD;"
+                tal:content="availableCD"
+              />
+              <a tal:attributes="href python:atool.getSample(availableCD)">(Test it)</a>
+              <br/>
+            </tal:loop>
+          </div>
+          <div
+            class="field"
+            tal:define="tabindex tabindex/next;
+                        value python:request.get('currentFlexStorageBackend', atool.getCurrentFlexStorageBackend())"
+          >
+            <label
+              i18n:translate="currentFlexStorageBackend"
+            >
+              Storage Backend
+            </label>
+
+            <div class="formHelp" i18n:translate="help_currentFlexStorageBackend">
+              <p>Choose the way the data in attachment fields are saved. The
+              showed options depends of what is already installed on your instance.</p>
+              <p>
+                <strong>AttributeStorage</strong>: Files are stored in
+                <acronym
+                  title="Zope Object Data Base"
+                >
+                  ZODB
+                </acronym>. Easy to use and Plone default storage option
+              </p>
+              <p>
+                <strong>FileSystemStorage</strong>: Files are stored on the filesystem. Faster than
+                AttributeStorage, and reduce ZODB size, but needs the
+                <a href="http://plone.org/products/filesystemstorage">FileSystemStorage product</a> in order to work.
+              </p>
+              <p class="error">
+                Warning: Switching between options is a <strong>sensible operation</strong>
+                that can length from <strong>minutes to hours</strong> if your site contains thousands
+                of files.
+              </p>
+
+            </div>
+            <tal:loop repeat="availableSB atool/getAvailableFlexStorageBackends">
+              <input
+                type="radio"
+                name="storage_backend"
+                class="noborder"
+                tal:attributes="checked python:test(value==availableSB, 'checked', '');
+                                tabindex tabindex;
+                                value availableSB;
+                                id availableSB;
+                                "
+              />
+              <label
+                tal:attributes="for availableSB;"
+                tal:content="availableSB"
+              />
+              <br/>
+            </tal:loop>
+          </div>
+          <tal:todo replace="nothing">
+            Here, we have to add a check box that have to be checked in order to
+            verify that the user has understood what a migration is.
+          </tal:todo>
+
+          <div class="formControls">
+            <input
+              class="context"
+              type="submit"
+              name="form.button.Save"
+              tal:attributes="tabindex tabindex/next;"
+            />
+          </div>
+
+        </fieldset>
         <fieldset>
           <legend i18n:translate="">Information</legend>
-
-            <table class="listing"> 
+            <div
+              class="error"
+              tal:condition="python:atool.isListErroneous()"
+            >
+              Some handlers are not working properly. Check for erroneous lines
+              in the following table.<br/><br/>Note that affected content can be
+              used as usual, but will not be indexed.
+            </div>
+            <table class="listing">
               <thead>
                 <tr>
                   <th></th>
@@ -43,33 +165,38 @@
               </thead>
               <tbody>
                 <tal:loop repeat="handler atool/listHandlerValues">
-                  <tr 
-                    tal:define="klass python:test(repeat['handler'].even(), 'listing odd', 'listing even')"
-                    tal:attributes="class klass">
+                  <tr
+                    tal:define="
+                      klass python:test(repeat['handler'].even(), 'listing odd', 'listing even');
+                      error python:test(handler['error'], 'error', '');
+                    "
+                    tal:attributes="class python:test(error, error, klass)"
+                  >
                     <td>
                       <img tal:attributes="src python: handler['small_icon_file']" />
                     </td>
                     <td>
                       <b><span tal:content="python: handler['class']" /></b>
                     </td>
-                    <td tal:content="structure python: modules['string'].join(handler['mime'], '<br />')">
+                    <td
+                      tal:content=
+                        "structure python: modules['string'].join(handler['mime'], '<br/>')"
+                    >
                     </td>
                     <td>
-                     <span tal:content="python: handler['index_program']" />
-                        <span tal:content="python: handler['index_arguments']" />
+                     <span tal:content="structure python: handler['index_program_gui']" />
                     </td>
                     <td>
-                      <span tal:content="python: handler['preview_program']" />
-                        <span tal:content="python: handler['preview_arguments']" />
+                      <span tal:content="structure python: handler['preview_program_gui']" />
                     </td>
                   </tr>
                 </tal:loop>
               </tbody>
             </table>
-          
+
         </fieldset>
 
-             
+
         <fieldset metal:define-macro="upload">
           <legend i18n:translate="">Test</legend>
 
@@ -79,17 +206,17 @@
                            file request/file | nothing;"
                tal:attributes="class python:test(error, 'field error', 'field')">
 
-              <label for="file" 
+              <label for="file"
                 i18n:translate="">
                 Attachment File
               </label>
 
-              <span class="fieldRequired" 
+              <span class="fieldRequired"
                 title="Required"
                 i18n:attributes="title"
                 i18n:translate="label_required">(Required)</span>
 
-              <div class="formHelp" 
+              <div class="formHelp"
                 i18n:translate="">
                 Select the file you want to test. Please note that this file WILL NOT be saved on the server.
               </div>
@@ -109,18 +236,18 @@
                tal:attributes="class python:test(error, 'field error', 'field')"
               tal:replace="nothing">
 
-              <label for="handler" 
+              <label for="handler"
                 i18n:translate="">
                 Attachment Handler
               </label>
 
-              <span class="fieldRequired" 
+              <span class="fieldRequired"
                 title="Required"
                 i18n:attributes="title"
                 i18n:translate="label_required">(Required)</span>
 
 
-             <div class="formHelp" 
+             <div class="formHelp"
                 i18n:translate="">
                 Select the handler you want to use for this test.
               </div>
@@ -133,7 +260,7 @@
                     size="1"
                     >
               <option value="">(Guess)</option>
-              <option 
+              <option
                 tal:repeat="handler_ atool/listHandlerValues"
                 tal:attributes="
                   value python:handler_['class'];
@@ -145,21 +272,21 @@
           </div>
 
             <div class="formControls">
-              <input class="context" 
-                type="submit" 
+              <input class="context"
+                type="submit"
                 name="form.button.Test"
                 value="Test"
-                i18n:attributes="value" 
+                i18n:attributes="value"
               tal:attributes="tabindex tabindex/next;" />
 
-              <input class="context" 
-                type="submit" 
+              <input class="context"
+                type="submit"
                 name="form.button.Cancel"
                 value="Cancel"
-                i18n:attributes="value" 
+                i18n:attributes="value"
               tal:attributes="tabindex tabindex/next;" />
             </div>
-            
+
           </fieldset>
 
         <input type="hidden" name="form.submitted" value="1" />

Modified: zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt.metadata
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt.metadata	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form.cpt.metadata	2006-10-13 20:51:32 UTC (rev 304)
@@ -10,5 +10,6 @@
 [actions]
 action.success..Test=traverse_to:string:attachmentfield_test
 action.success..Cancel=redirect_to:string:attachmentfield_prefs_form
+action.success..Save=traverse_to:string:attachmentfield_prefs_form_backend
 action.success=redirect_to:string:attachmentfield_prefs_form
 action.failure=traverse_to:string:attachmentfield_prefs_form

Copied: zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy (from rev 298, zope-attachmentfield/branches/upstream/current/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy)
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy	                        (rev 0)
+++ zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy	2006-10-13 20:51:32 UTC (rev 304)
@@ -0,0 +1,18 @@
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters = content_disposition, storage_backend
+##
+
+req = context.REQUEST
+
+atool = context.portal_attachment
+
+atool.manage_changeProperties(contentDisposition=content_disposition)
+
+## safe to call it with the same name
+atool.setCurrentFlexStorageBackend(newStorageName=storage_backend)
+
+return state.set(status="success", portal_status_message="AttachementField configuration succesfully updated.")

Copied: zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy.metadata (from rev 298, zope-attachmentfield/branches/upstream/current/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy.metadata)
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy.metadata	                        (rev 0)
+++ zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_prefs_form_backend.cpy.metadata	2006-10-13 20:51:32 UTC (rev 304)
@@ -0,0 +1,3 @@
+[actions]
+action.success=redirect_to:string:plone_control_panel
+

Modified: zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_widget.pt
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_widget.pt	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/skins/attachmentfield/attachmentfield_widget.pt	2006-10-13 20:51:32 UTC (rev 304)
@@ -52,7 +52,7 @@
              tal:condition="python: showPreviewLink and isPreviewAvailable"
              tal:define="preview_img here/attachmentfield_preview.gif;
                          i18n_title python:here.translate(msgid='Preview', domain='attachmentfield')"
-             tal:attributes="href string:javascript:popupPreview(preview_url='${here_url}/preview_popup',size1=600,size2=400);
+             tal:attributes="href string:javascript:popupPreview(preview_url='${here_url}/preview_popup/${fieldName}',size1=600,size2=400);
                              title i18n_title"
              i18n:attributes="title">
             <img tal:replace="structure python:preview_img.tag(alt=i18n_title, title=i18n_title)" />

Modified: zope-attachmentfield/trunk/skins/attachmentfield/preview_popup.pt
===================================================================
--- zope-attachmentfield/trunk/skins/attachmentfield/preview_popup.pt	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/skins/attachmentfield/preview_popup.pt	2006-10-13 20:51:32 UTC (rev 304)
@@ -48,9 +48,10 @@
   </head>
   
   <body style="background-color: white; background-image: none;"
-        tal:define="file_field python:here.getField('file');
+        tal:define="fieldName python: request['traverse_subpath'][0];
+                    file_field python:here.getField(fieldName);
                     implements_preview python:hasattr(file_field, 'getPreview')">
-    
+
     <div style="text-align: center; margin: 1em auto 1em auto;">
       <tal:block tal:condition="implements_preview">
         <div tal:content="structure python:file_field.getPreview(here)" />

Copied: zope-attachmentfield/trunk/skins/attachmentfield/sample (from rev 298, zope-attachmentfield/branches/upstream/current/skins/attachmentfield/sample)

Modified: zope-attachmentfield/trunk/version.txt
===================================================================
--- zope-attachmentfield/trunk/version.txt	2006-10-13 20:45:58 UTC (rev 303)
+++ zope-attachmentfield/trunk/version.txt	2006-10-13 20:51:32 UTC (rev 304)
@@ -1 +1 @@
-1.3.6
\ No newline at end of file
+1.3.10
\ No newline at end of file




More information about the pkg-zope-commits mailing list