appy.pod: xhtml2odt: ability to include images from img tags (anonymously). Non-anonymous solution for a Appy/Zope server only; function 'document': allow to specify size of images in cm or px, or via a 'style' tag; appy.gen: allow to upload images in ckeditor fields; improved error management.
This commit is contained in:
parent
98fafad14a
commit
2bd3fe1eeb
10 changed files with 206 additions and 54 deletions
|
@ -17,10 +17,12 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
import os, os.path, time, shutil, struct, random
|
||||
import os, os.path, time, shutil, struct, random, urlparse
|
||||
from appy.pod import PodError
|
||||
from appy.pod.odf_parser import OdfEnvironment
|
||||
from appy.shared import mimeTypesExts
|
||||
from appy.shared.utils import FileWrapper
|
||||
from appy.shared.dav import Resource
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
FILE_NOT_FOUND = "'%s' does not exist or is not a file."
|
||||
|
@ -32,28 +34,30 @@ PDF_TO_IMG_ERROR = 'A PDF file could not be converted into images. Please ' \
|
|||
class DocImporter:
|
||||
'''Base class used for importing external content into a pod template (an
|
||||
image, another pod template, another odt document...'''
|
||||
def __init__(self, content, at, format, tempFolder, ns, fileNames):
|
||||
def __init__(self, content, at, format, renderer):
|
||||
self.content = content
|
||||
# If content is None, p_at tells us where to find it (file system path,
|
||||
# url, etc)
|
||||
self.at = at
|
||||
# Ensure this path exists.
|
||||
if at and not os.path.isfile(at): raise PodError(FILE_NOT_FOUND % at)
|
||||
# Ensure this path exists, if it is a local path.
|
||||
if at and not at.startswith('http') and not os.path.isfile(at):
|
||||
raise PodError(FILE_NOT_FOUND % at)
|
||||
self.format = format
|
||||
self.res = u''
|
||||
self.ns = ns
|
||||
self.renderer = renderer
|
||||
self.ns = renderer.currentParser.env.namespaces
|
||||
# Unpack some useful namespaces
|
||||
self.textNs = ns[OdfEnvironment.NS_TEXT]
|
||||
self.linkNs = ns[OdfEnvironment.NS_XLINK]
|
||||
self.drawNs = ns[OdfEnvironment.NS_DRAW]
|
||||
self.svgNs = ns[OdfEnvironment.NS_SVG]
|
||||
self.tempFolder = tempFolder
|
||||
self.textNs = self.ns[OdfEnvironment.NS_TEXT]
|
||||
self.linkNs = self.ns[OdfEnvironment.NS_XLINK]
|
||||
self.drawNs = self.ns[OdfEnvironment.NS_DRAW]
|
||||
self.svgNs = self.ns[OdfEnvironment.NS_SVG]
|
||||
self.tempFolder = renderer.tempFolder
|
||||
self.importFolder = self.getImportFolder()
|
||||
# Create the import folder if it does not exist.
|
||||
if not os.path.exists(self.importFolder): os.mkdir(self.importFolder)
|
||||
self.importPath = self.getImportPath(at, format)
|
||||
# A link to the global fileNames dict (explained in renderer.py)
|
||||
self.fileNames = fileNames
|
||||
self.fileNames = renderer.fileNames
|
||||
if at:
|
||||
# Move the file within the ODT, if it is an image and if this image
|
||||
# has not already been imported.
|
||||
|
@ -84,7 +88,10 @@ class DocImporter:
|
|||
'''Gets the path name of the file to dump on disk (within the ODT for
|
||||
images, in a temp folder for docs).'''
|
||||
if not format:
|
||||
format = os.path.splitext(at)[1][1:]
|
||||
if at.startswith('http'):
|
||||
format = '' # We will know it only after the HTTP GET.
|
||||
else:
|
||||
format = os.path.splitext(at)[1][1:]
|
||||
fileName = 'f.%d.%f.%s' % (random.randint(0,10), time.time(), format)
|
||||
return os.path.abspath('%s/%s' % (self.importFolder, fileName))
|
||||
|
||||
|
@ -136,8 +143,7 @@ class PdfImporter(DocImporter):
|
|||
nextImage = '%s/%s%d.jpg' % (imagesFolder, self.imagePrefix, i)
|
||||
if os.path.exists(nextImage):
|
||||
# Use internally an Image importer for doing this job.
|
||||
imgImporter = ImageImporter(None, nextImage, 'jpg',
|
||||
self.tempFolder, self.ns, self.fileNames)
|
||||
imgImporter =ImageImporter(None, nextImage, 'jpg',self.renderer)
|
||||
imgImporter.setAnchor('paragraph')
|
||||
self.res += imgImporter.run()
|
||||
os.remove(nextImage)
|
||||
|
@ -199,17 +205,70 @@ class ImageImporter(DocImporter):
|
|||
# Yes!
|
||||
i = importPath.rfind(self.pictFolder) + 1
|
||||
return importPath[:i] + imagePath
|
||||
# If I am here, the image has not already been imported: copy it.
|
||||
shutil.copy(at, importPath)
|
||||
# The image has not already been imported: copy it.
|
||||
if not at.startswith('http'):
|
||||
shutil.copy(at, importPath)
|
||||
return importPath
|
||||
# The image must be retrieved via a URL. Try to perform a HTTP GET.
|
||||
response = Resource(at).get()
|
||||
if response.code == 200:
|
||||
# At last, I can get the file format.
|
||||
self.format = mimeTypesExts[response.headers['Content-Type']]
|
||||
importPath += self.format
|
||||
f = file(importPath, 'wb')
|
||||
f.write(response.body)
|
||||
f.close()
|
||||
return importPath
|
||||
# The HTTP GET did not work, maybe for security reasons (we probably
|
||||
# have no permission to get the file). But maybe the URL was a local
|
||||
# one, from an application server running this POD code. In this case,
|
||||
# if an image resolver has been given to POD, use it to retrieve the
|
||||
# image.
|
||||
imageResolver = self.renderer.imageResolver
|
||||
if not imageResolver:
|
||||
# Return some default image explaining that the image wasn't found.
|
||||
import appy.pod
|
||||
podFolder = os.path.dirname(appy.pod.__file__)
|
||||
img = os.path.join(podFolder, 'imageNotFound.jpg')
|
||||
self.format = 'jpg'
|
||||
importPath += self.format
|
||||
f = file(img)
|
||||
imageContent = f.read()
|
||||
f.close()
|
||||
f = file(importPath, 'wb')
|
||||
f.write(imageContent)
|
||||
f.close()
|
||||
else:
|
||||
# The imageResolver is a Zope application. From it, we will
|
||||
# retrieve the object on which the image is stored and get
|
||||
# the file to download.
|
||||
urlParts = urlparse.urlsplit(at)
|
||||
path = urlParts[2][1:]
|
||||
obj = imageResolver.unrestrictedTraverse(path.split('/')[:-1])
|
||||
zopeFile = getattr(obj, urlParts[3].split('=')[1])
|
||||
appyFile = FileWrapper(zopeFile)
|
||||
self.format = mimeTypesExts[appyFile.mimeType]
|
||||
importPath += self.format
|
||||
appyFile.dump(importPath)
|
||||
return importPath
|
||||
|
||||
def setImageInfo(self, anchor, wrapInPara, size):
|
||||
def setImageInfo(self, anchor, wrapInPara, size, sizeUnit, style):
|
||||
# Initialise anchor
|
||||
if anchor not in self.anchorTypes:
|
||||
raise PodError(self.WRONG_ANCHOR % str(self.anchorTypes))
|
||||
self.anchor = anchor
|
||||
self.wrapInPara = wrapInPara
|
||||
self.size = size
|
||||
self.sizeUnit = sizeUnit
|
||||
# Put CSS attributes from p_style in a dict.
|
||||
self.cssAttrs = {}
|
||||
for attr in style.split(';'):
|
||||
if not attr.strip(): continue
|
||||
name, value = attr.strip().split(':')
|
||||
value = value.strip()
|
||||
if value.endswith('px'): value = value[:-2]
|
||||
if value.isdigit(): value=int(value)
|
||||
self.cssAttrs[name.strip()] = value
|
||||
|
||||
def run(self):
|
||||
# Some shorcuts for the used xml namespaces
|
||||
|
@ -222,19 +281,37 @@ class ImageImporter(DocImporter):
|
|||
i = self.importPath.rfind(self.pictFolder)
|
||||
imagePath = self.importPath[i+1:].replace('\\', '/')
|
||||
self.fileNames[imagePath] = self.at
|
||||
# Compute image size, or retrieve it from self.size if given
|
||||
# Retrieve image size from self.size.
|
||||
width = height = None
|
||||
if self.size:
|
||||
width, height = self.size
|
||||
else:
|
||||
if self.sizeUnit == 'px':
|
||||
# Convert it to cm
|
||||
width = float(width) / pxToCm
|
||||
height = float(height) / pxToCm
|
||||
# Override self.size if 'height' or 'width' is found in self.cssAttrs
|
||||
if 'width' in self.cssAttrs:
|
||||
width = float(self.cssAttrs['width']) / pxToCm
|
||||
if 'height' in self.cssAttrs:
|
||||
height = float(self.cssAttrs['height']) / pxToCm
|
||||
# If width and/or height is missing, compute it.
|
||||
if not width or not height:
|
||||
width, height = getSize(self.importPath, self.format)
|
||||
if width != None:
|
||||
size = ' %s:width="%fcm" %s:height="%fcm"' % (s, width, s, height)
|
||||
else:
|
||||
size = ''
|
||||
image = '<%s:frame %s:name="%s" %s:z-index="0" %s:anchor-type="%s"%s>' \
|
||||
'<%s:image %s:type="simple" %s:show="embed" %s:href="%s" ' \
|
||||
'%s:actuate="onLoad"/></%s:frame>' % (d, d, imageName, d, t, \
|
||||
self.anchor, size, d, x, x, x, imagePath, x, d)
|
||||
if 'float' in self.cssAttrs:
|
||||
floatValue = self.cssAttrs['float'].capitalize()
|
||||
styleInfo = '%s:style-name="podImage%s" ' % (d, floatValue)
|
||||
self.anchor = 'char'
|
||||
else:
|
||||
styleInfo = ''
|
||||
image = '<%s:frame %s%s:name="%s" %s:z-index="0" ' \
|
||||
'%s:anchor-type="%s"%s><%s:image %s:type="simple" ' \
|
||||
'%s:show="embed" %s:href="%s" %s:actuate="onLoad"/>' \
|
||||
'</%s:frame>' % (d, styleInfo, d, imageName, d, t, self.anchor,
|
||||
size, d, x, x, x, imagePath, x, d)
|
||||
if hasattr(self, 'wrapInPara') and self.wrapInPara:
|
||||
image = '<%s:p>%s</%s:p>' % (t, image, t)
|
||||
self.res += image
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue