From 0e070b0d583a3c482f7f72bbd6f2d7c333582965 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Benoi=CC=82t=20Pin?= <pin@cri.ensmp.fr>
Date: Thu, 10 Apr 2014 15:16:06 +0200
Subject: [PATCH] =?utf8?q?Utilisation=20des=20blobs=20pour=20les=20fichier?=
 =?utf8?q?s=20attach=C3=A9s=20(=C3=A0=20l'instar=20des=20photos).=20Nettoy?=
 =?utf8?q?age=20automatique=20des=20pi=C3=A8ces=20jointes=20non=20utilis?=
 =?utf8?q?=C3=A9es.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

---
 AttachmentTool.py                          | 32 +++++++++++++++++++---
 skins/custom_content/document_edit_form.py |  6 ++--
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/AttachmentTool.py b/AttachmentTool.py
index 979148d..87535c7 100644
--- a/AttachmentTool.py
+++ b/AttachmentTool.py
@@ -28,7 +28,8 @@ from Acquisition import aq_base
 from Globals import InitializeClass
 from OFS.SimpleItem import SimpleItem
 from OFS.Folder import Folder
-from OFS.Image import File, cookId
+from OFS.Image import cookId
+from Products.Photo.blobbases import File
 from zExceptions import Unauthorized
 from zExceptions import BadRequest
 from Products.Photo import Photo
@@ -45,7 +46,9 @@ from webdav.common import Locked
 from webdav.common import PreconditionFailed
 from zope.contenttype import guess_content_type
 
-
+from libxml2 import HTML_PARSE_RECOVER, HTML_PARSE_NOERROR, HTML_PARSE_NOWARNING
+from libxml2 import htmlReadDoc
+PARSE_OPTIONS = HTML_PARSE_RECOVER + HTML_PARSE_NOERROR + HTML_PARSE_NOWARNING
 
 class AttachmentTool( UniqueObject, SimpleItem):
     """ Links attachment objects to contents.
@@ -185,7 +188,7 @@ class AttachmentContainer (Folder):
         ob.PUT(REQUEST, RESPONSE)
         RESPONSE.setStatus(httpRespCode)
         RESPONSE.setHeader('Content-Type', 'text/xml;;charset=utf-8')
-        if ob.meta_type == 'File' :
+        if ob.meta_type == 'Blob File' :
             return '<element id="%s" title="%s"/>' % (ob.getId(), escape(ob.title_or_id()))
         elif ob.meta_type == 'Photo' :
             width, height = ob.getResizedImageSize(size=(310, 310))
@@ -195,6 +198,27 @@ class AttachmentContainer (Folder):
                  'width' : width,
                  'height' : height
                  }
-
+    
+    security.declareProtected(ModifyPortalContent, 'removeUnusedAttachments')
+    def removeUnusedAttachments(self, html) :
+        html = '<div>%s</div>' % html
+        doc = htmlReadDoc(html, '', None, PARSE_OPTIONS)
+        used = {}
+
+        hrefs = doc.xpathEval('//a/@href')
+        for href in [a.get_content() for a in hrefs] :
+            if href.startswith('attachments/') :
+                used[href[len('attachments/'):]] = True
+
+        srcs = doc.xpathEval('//img/@src')
+        for src in [a.get_content() for a in srcs] :
+            if src.startswith('attachments/') :
+                parts = src.split('/')
+                if len(parts) >=2 :
+                    used[parts[1]] = True
+        
+        unused = [id for id in self.objectIds() if not used.has_key(id)]
+        if unused :
+            self.manage_delObjects(unused)
 
 InitializeClass(AttachmentContainer)
\ No newline at end of file
diff --git a/skins/custom_content/document_edit_form.py b/skins/custom_content/document_edit_form.py
index d439bd7..8dffe34 100644
--- a/skins/custom_content/document_edit_form.py
+++ b/skins/custom_content/document_edit_form.py
@@ -20,9 +20,9 @@ if change and \
 elif change_and_view and \
         context.validateTextFile(**form) and \
         context.validateHTML(**form) and \
-        context.document_edit_control(text=form.get('text'), text_format='html') and \
-        context.setRedirect(context, 'object/view', **{'ajax':ajax}):
-    return
+        context.document_edit_control(text=form.get('text'), text_format='html') :
+    attachments.removeUnusedAttachments(context.EditableBody())
+    return context.setRedirect(context, 'object/view', **{'ajax':ajax})
 
 
 options = {}
-- 
2.20.1