diff --git a/configure.zcml b/configure.zcml
index b2e3506..5e04180 100644
--- a/configure.zcml
+++ b/configure.zcml
@@ -441,6 +441,7 @@
+
diff --git a/media/README.txt b/media/README.txt
new file mode 100644
index 0000000..6f8efcd
--- /dev/null
+++ b/media/README.txt
@@ -0,0 +1,18 @@
+===============================================================
+loops - Linked Objects for Organization and Processing Services
+===============================================================
+
+ ($Id$)
+
+
+Media Asset Management
+======================
+
+ >>> from loops.media.asset import MediaAsset
+
+
+Browser Views
+-------------
+
+ >>> from loops.media.browser.asset import MediaAssetView, MediaAssetNodeView
+
diff --git a/media/__init__.py b/media/__init__.py
new file mode 100644
index 0000000..4bc90fb
--- /dev/null
+++ b/media/__init__.py
@@ -0,0 +1,4 @@
+"""
+$Id$
+"""
+
diff --git a/media/asset.py b/media/asset.py
new file mode 100644
index 0000000..11ebc20
--- /dev/null
+++ b/media/asset.py
@@ -0,0 +1,81 @@
+#
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
+#
+# 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; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Media asset file adapter.
+
+Original authors: Johann Schimpf, Erich Seifert.
+
+$Id$
+"""
+
+from logging import getLogger
+import os
+
+from zope import component
+from zope.cachedescriptors.property import Lazy
+from zope.interface import implements
+
+from cybertools.media.asset import MediaAssetFile
+from cybertools.storage.interfaces import IExternalStorage
+from loops.media.interfaces import IMediaAsset
+from loops.resource import ExternalFileAdapter
+from loops.type import TypeInterfaceSourceList
+
+transformPrefix = 'asset_transform.'
+
+TypeInterfaceSourceList.typeInterfaces += (IMediaAsset,)
+
+
+class MediaAsset(MediaAssetFile, ExternalFileAdapter):
+ """ Concept adapter for extracting metadata from assets and for creating
+ transformation variants.
+ """
+
+ implements(IMediaAsset)
+
+ isMediaAsset = True
+
+ def __init__(self, context):
+ ExternalFileAdapter.__init__(self, context)
+
+ @Lazy
+ def rules(self):
+ result = {}
+ for key, value in self.options.items():
+ if key.startswith(transformPrefix):
+ variant = key[len(transformPrefix):]
+ result[variant] = value
+ return result
+
+ def setData(self, data):
+ ExternalFileAdapter.setData(self, data)
+ if data:
+ self.transform(self.rules)
+ data = property(ExternalFileAdapter.getData, setData)
+
+ def getMimeType(self):
+ return self.context.contentType
+
+ def getDataPath(self):
+ storage = component.getUtility(IExternalStorage, name=self.storageName)
+ return storage.getDir(self.externalAddress,
+ self.options['storage_parameters'])
+
+ def getOriginalData(self):
+ return ExternalFileAdapter.getData(self)
diff --git a/media/browser/__init__.py b/media/browser/__init__.py
new file mode 100644
index 0000000..4bc90fb
--- /dev/null
+++ b/media/browser/__init__.py
@@ -0,0 +1,4 @@
+"""
+$Id$
+"""
+
diff --git a/media/browser/admin.py b/media/browser/admin.py
new file mode 100644
index 0000000..968946a
--- /dev/null
+++ b/media/browser/admin.py
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
+#
+# 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; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+View for regenerating all transformed media assets.
+
+Authors: Johann Schimpf, Erich Seifert.
+
+$Id$
+"""
+
+from logging import getLogger
+import traceback
+from zope import component
+
+from cybertools.media.interfaces import IMediaAsset
+
+
+class RegenerationView(object):
+
+ def __call__(self):
+ conceptType = self.request.get('type')
+ if not conceptType:
+ return '*** No type given!'
+ tMediaAsset = self.context.getLoopsRoot().getConceptManager()[conceptType]
+ # Remove old transformed versions
+ #storageDir = assetManager.options.get("storage_parameters")
+ #print storageDir
+ # Regenerate all media asset transforations
+ resources = tMediaAsset.getResources()
+ logger = getLogger('Asset Manager')
+ errors = 0
+ for res in resources:
+ logger.info('*** regenerating: ' + res.__name__)
+ asset = component.queryAdapter(res, IMediaAsset)
+ if asset != None:
+ try:
+ asset.transform()
+ except:
+ logger.warn(traceback.format_exc())
+ errors += 1
+ if errors:
+ return 'Done - there were %i errors.' % errors
+ return 'Done.'
diff --git a/media/browser/asset.pt b/media/browser/asset.pt
new file mode 100644
index 0000000..c003c62
--- /dev/null
+++ b/media/browser/asset.pt
@@ -0,0 +1,16 @@
+
+
+
+ Title
+
+ Content type
+ image/jpeg
+
+
+
Description
+
Description
+
+
+ ![]()
+
+
diff --git a/media/browser/asset.py b/media/browser/asset.py
new file mode 100644
index 0000000..10f81bc
--- /dev/null
+++ b/media/browser/asset.py
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
+#
+# 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; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Views for displaying media assets.
+
+Authors: Johann Schimpf, Erich Seifert.
+
+$Id$
+"""
+
+from zope.app.pagetemplate import ViewPageTemplateFile
+from zope.cachedescriptors.property import Lazy
+
+from loops.browser.node import NodeView
+from loops.browser.resource import ResourceView
+from loops.common import adapted
+from loops import util
+
+template = ViewPageTemplateFile('asset.pt')
+
+
+class MediaAssetView(ResourceView):
+
+ @Lazy
+ def macro(self):
+ return template.macros['asset']
+
+ def show(self, useAttachment=False):
+ versionId = self.request.get('v')
+ obj = self.adapted
+ data = obj.getData(versionId)
+ contentType = obj.getContentType(versionId)
+ response = self.request.response
+ response.setHeader('Content-Type', contentType)
+ response.setHeader('Content-Length', len(data))
+ #if useAttachment or (
+ # not contentType.startswith('image/') and contentType != 'application/pdf'):
+ if useAttachment:
+ filename = obj.localFilename or getName(self.context)
+ #filename = urllib.quote(filename)
+ filename = NameChooser(getParent(self.context)).normalizeName(filename)
+ response.setHeader('Content-Disposition',
+ 'attachment; filename=%s' % filename)
+ return data
+
+
+class MediaAssetNodeView(NodeView):
+
+ def show(self):
+ return self.targetView('mediaasset.html')
diff --git a/media/browser/configure.zcml b/media/browser/configure.zcml
new file mode 100644
index 0000000..6f60056
--- /dev/null
+++ b/media/browser/configure.zcml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/configure.zcml b/media/configure.zcml
new file mode 100644
index 0000000..59fde62
--- /dev/null
+++ b/media/configure.zcml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/interfaces.py b/media/interfaces.py
new file mode 100644
index 0000000..5cafe7e
--- /dev/null
+++ b/media/interfaces.py
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
+#
+# 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; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Media asset management interface definitions.
+
+$Id$
+"""
+
+from cybertools.media.interfaces import IMediaAsset
+from loops.interfaces import IExternalFile
+
+
+class IMediaAsset(IMediaAsset, IExternalFile):
+
+ pass
+
diff --git a/media/tests.py b/media/tests.py
new file mode 100644
index 0000000..57fd700
--- /dev/null
+++ b/media/tests.py
@@ -0,0 +1,29 @@
+#! /usr/bin/python
+
+"""
+Tests for the 'loops.media' package.
+
+$Id$
+"""
+
+import unittest, doctest
+from zope.testing.doctestunit import DocFileSuite
+from zope.interface.verify import verifyClass
+
+
+class Test(unittest.TestCase):
+ "Basic tests for the media package."
+
+ def testSomething(self):
+ pass
+
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
+ return unittest.TestSuite((
+ unittest.makeSuite(Test),
+ DocFileSuite('README.txt', optionflags=flags),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
diff --git a/security/perm.py b/security/perm.py
index ca402b8..3bbb3cf 100644
--- a/security/perm.py
+++ b/security/perm.py
@@ -31,8 +31,6 @@ from zope.app.securitypolicy.interfaces import IPrincipalRoleManager, IRolePermi
from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager, \
IPrincipalPermissionMap
from zope.app.securitypolicy.zopepolicy import SettingAsBoolean
-from zope.publisher.browser import BrowserView
-from zope.security.proxy import removeSecurityProxy
from zope.traversing.api import getParents
diff --git a/type.py b/type.py
index 51260d3..4e5f783 100644
--- a/type.py
+++ b/type.py
@@ -289,7 +289,7 @@ def getOptionsDict(options):
for opt in options:
if ':' in opt:
key, value = opt.split(':', 1)
- result[key] = value
+ result[key.strip()] = value.strip()
else:
- result['default'].append(opt)
+ result['default'].append(opt.strip())
return result