Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
cloudooo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
7
Merge Requests
7
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
cloudooo
Commits
56edddf6
Commit
56edddf6
authored
Feb 09, 2017
by
Boris Kocherov
1
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'nexedi'
parents
7f44ed79
00604a3a
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
911 additions
and
104 deletions
+911
-104
README.rst
README.rst
+58
-34
cloudooo/handler/ffmpeg/handler.py
cloudooo/handler/ffmpeg/handler.py
+13
-0
cloudooo/handler/imagemagick/handler.py
cloudooo/handler/imagemagick/handler.py
+13
-0
cloudooo/handler/ooo/handler.py
cloudooo/handler/ooo/handler.py
+33
-1
cloudooo/handler/ooo/tests/testOooHandler.py
cloudooo/handler/ooo/tests/testOooHandler.py
+497
-0
cloudooo/handler/ooo/tests/testOooMimemapper.py
cloudooo/handler/ooo/tests/testOooMimemapper.py
+2
-0
cloudooo/handler/ooo/tests/testOooServer.py
cloudooo/handler/ooo/tests/testOooServer.py
+15
-22
cloudooo/handler/pdf/handler.py
cloudooo/handler/pdf/handler.py
+15
-1
cloudooo/handler/pdf/tests/testPdfHandler.py
cloudooo/handler/pdf/tests/testPdfHandler.py
+13
-0
cloudooo/handler/wkhtmltopdf/handler.py
cloudooo/handler/wkhtmltopdf/handler.py
+21
-2
cloudooo/handler/wkhtmltopdf/tests/testWkhtmltopdfHandler.py
cloudooo/handler/wkhtmltopdf/tests/testWkhtmltopdfHandler.py
+12
-0
cloudooo/handler/x2t/handler.py
cloudooo/handler/x2t/handler.py
+64
-12
cloudooo/handler/x2t/tests/data/test_body.xlsy
cloudooo/handler/x2t/tests/data/test_body.xlsy
+1
-0
cloudooo/handler/x2t/tests/testX2tHandler.py
cloudooo/handler/x2t/tests/testX2tHandler.py
+30
-6
cloudooo/interfaces/manager.py
cloudooo/interfaces/manager.py
+1
-1
cloudooo/manager.py
cloudooo/manager.py
+106
-25
cloudooo/util.py
cloudooo/util.py
+17
-0
No files found.
README.rst
View file @
56edddf6
Install Cloudooo
================
::
$ python2.6 setup.py install
Warnings:
Warnings:
- you must have installed setuptools>=0.6c11 in this python.
Install LibreOffice / OpenOffice.org
====================================
Install LibreOffice or OpenOffice.org.
Install LibreOffice or OpenOffice.org.
- http://www.libreoffice.org/download/
- http://download.openoffice.org/
Create Configuration File
=========================
The configuration file is used to start the application using paster.
The configuration file is used to start the application using paster.
::
$ cp ./cloudooo/sample/sample.conf . # Copy to current folder
The next step is define some attributes in cloudooo.conf:
The next step is define some attributes in cloudooo.conf:
- working_path - folder to run the application. This folder need be created.
- uno_path - folder where UNO library is installed (ex. /opt/libreoffice/basis-link/program/)
- soffice_binary_path - folder where soffice.bin is installed (ex. /opt/libreoffice/program/)
...
...
@@ -27,9 +33,14 @@ Create Configuration File
Run Application
===============
::
$ paster serve ./cloudooo.conf
or run as a daemon:
or run as a daemon:
::
$ paster serve ./cloudoo.conf --daemon
...
...
@@ -37,48 +48,61 @@ Run Application
Stop Application
================
::
$ kill -1 PASTER_PID
Warning: always use SIGHUP because only with this signal all processes are
stopped correctly.
Warning: always use SIGHUP because only with this signal all processes are stopped correctly.
Cloudooo Description
====================
- XMLRPC + WSGI will be one bridge for easy access to LibreOffice / OpenOffice.org. This will implement one XMLRPC server into WSGI (Paster).
- PyUno is used to connect to LibreOffice / OpenOffice.org stated with open socket. The features will be handled all by pyuno.
- Only a process will have access to LibreOffice / OpenOffice.org by time.
- All clients receive the same object(proxy) when connects with XMLRPC Server.
Managing LibreOffice / OpenOffice.org process
- start 'soffice.bin';
- Pyuno start 'soffice.bin' processes and the communication is through sockets;
- start 'soffice.bin':
- Pyuno start 'soffice.bin' processes and the communication is through sockets
- 'soffice.bin' processes run in brackground;
- control 'soffice.bin';
- If the socket lose the connection, cloudooo kills the process, restartes processes and submit again the file;
- control 'soffice.bin':
- If the socket lose the connection, cloudooo kills the process, restarts processes and submit again the file;
XMLRPC Server - XMLRPC + WSGI
-----------------------------
- Send document to 'soffice.bin' and return the document converted with metadata;
- Send document to 'soffice.bin' and return the document converted with metadata
- XMLRPC receives a file and connects to 'soffice.bin' process by pyuno;
- The pyuno opens a new document, write, add metadata and returns the document edited or converted to xmlrpc and it return the document to the user;
- When finalize the use of 'soffice.bin', should make sure that it was finalized;
- Export to another format;
- Invite document and return metadata only;
- Edit metadata of the document;
- Problems and possible solution
- Export to another format;
- Invite document and return metadata only;
- Edit metadata of the document;
- Problems and possible solutions
- 'soffice.bin' is stalled;
- finalize the process, start 'soffice.bin' and submit the document again(without restart the cloudooo);
- finalize the process, start 'soffice.bin' and submit the document again (without restart the cloudooo);
- 'soffice.bin' is crashed;
- finalize the process, verify if all the process was killed, start 'soffice.bin' and submit the document again(without restart the cloudooo)
- 'soffice.bin' received the document and stalled;
- if 'soffice.bin' isn't responding, kill the process and start
- The document that was sent is corrupt;
- The document that was sent is corrupted;
- write in log the error and verify that the process aren't in memory
...
...
cloudooo/handler/ffmpeg/handler.py
View file @
56edddf6
...
...
@@ -123,3 +123,16 @@ class Handler(object):
return
self
.
input
.
getContent
()
finally
:
self
.
input
.
trash
()
@
staticmethod
def
getAllowedConversionFormatList
(
source_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('audio/ogg;codecs=opus', 'Opus Audio File Format'),
('video/webm', 'Webm Video File Format'),
...
]
"""
# XXX NotImplemented
return
[]
cloudooo/handler/imagemagick/handler.py
View file @
56edddf6
...
...
@@ -91,3 +91,16 @@ class Handler(object):
metadata -- expected an dictionary with metadata.
"""
raise
NotImplementedError
@
staticmethod
def
getAllowedConversionFormatList
(
source_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('image/jpeg', 'Jpeg Image File Format'),
('image/png', 'Png Image File Format'),
...
]
"""
# XXX NotImplemented
return
[]
cloudooo/handler/ooo/handler.py
View file @
56edddf6
...
...
@@ -29,6 +29,7 @@
import
json
import
re
import
pkg_resources
import
mimetypes
from
base64
import
decodestring
,
encodestring
from
os
import
environ
,
path
from
subprocess
import
Popen
,
PIPE
...
...
@@ -39,7 +40,7 @@ from cloudooo.handler.ooo.mimemapper import mimemapper
from
cloudooo.handler.ooo.document
import
FileSystemDocument
from
cloudooo.handler.ooo.monitor.timeout
import
MonitorTimeout
from
cloudooo.handler.ooo.monitor
import
monitor_sleeping_time
from
cloudooo.util
import
logger
from
cloudooo.util
import
logger
,
parseContentType
from
psutil
import
pid_exists
try
:
...
...
@@ -238,6 +239,37 @@ class Handler(object):
self
.
document
.
trash
()
return
doc_loaded
@
staticmethod
def
getAllowedConversionFormatList
(
source_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('application/vnd.oasis.opendocument.text', 'ODF Text Document'),
('application/pdf', 'PDF - Portable Document Format'),
...
]
"""
# XXX please never guess extension from mimetype
output_set
=
set
()
if
"/"
in
source_mimetype
:
parsed_mimetype_type
=
parseContentType
(
source_mimetype
).
gettype
()
# here `guess_all_extensions` never handles mimetype parameters
# (even for `text/plain;charset=UTF-8` which is standard)
extension_list
=
mimetypes
.
guess_all_extensions
(
parsed_mimetype_type
)
# XXX never guess
else
:
extension_list
=
[
source_mimetype
]
for
ext
in
extension_list
:
for
ext
,
title
in
mimemapper
.
getAllowedExtensionList
(
extension
=
ext
.
replace
(
"."
,
""
)):
if
ext
in
(
"fodt"
,
".fodt"
):
# BBB
output_set
.
add
((
"application/vnd.oasis.opendocument.text-flat-xml"
,
title
))
continue
if
ext
:
mimetype
,
_
=
mimetypes
.
guess_type
(
"a."
+
ext
)
# XXX never guess
if
mimetype
:
output_set
.
add
((
mimetype
,
title
))
return
list
(
output_set
)
def
bootstrapHandler
(
configuration_dict
):
# Bootstrap handler
from
signal
import
signal
,
SIGINT
,
SIGQUIT
,
SIGHUP
...
...
cloudooo/handler/ooo/tests/testOooHandler.py
View file @
56edddf6
...
...
@@ -187,6 +187,503 @@ class TestHandler(HandlerTestCase):
self
.
assertTrue
(
content_tree
.
xpath
(
'//text:variable-get[text() = "DISPLAY ME"]'
,
namespaces
=
content_tree
.
nsmap
))
def
testGetAllowedConversionFormatList_TextPlain
(
self
):
"""Test allowed conversion format for text/plain with charset parameter"""
def
get
(
*
args
,
**
kw
):
return
sorted
(
Handler
.
getAllowedConversionFormatList
(
*
args
,
**
kw
))
text_plain_output_list
=
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text - Choose Encoding'
)]
self
.
assertEquals
(
get
(
"text/plain;ignored=param"
),
text_plain_output_list
)
self
.
assertEquals
(
get
(
"text/plain;charset=UTF-8;ignored=param"
),
text_plain_output_list
)
self
.
assertEquals
(
get
(
"text/plain;charset=US-ASCII;ignored=param"
),
text_plain_output_list
)
def
testGetAllowedConversionFormatList_ApplicationMsword
(
self
):
"""Test allowed conversion format for application/msword"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/msword;ignored=param"
)),
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text - Choose Encoding'
)
])
def
testGetAllowedConversionFormatList_ApplicationPdf
(
self
):
"""Test allowed conversion format for application/pdf"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/pdf;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_TextRtf
(
self
):
"""Test allowed conversion format for text/rtf"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"text/rtf;ignored=param"
)),
[])
def
testGetAllowedConversionFormatList_ApplicationVndOasisOpendocumentText
(
self
):
"""Test allowed conversion format for application/vnd.oasis.opendocument.text"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.oasis.opendocument.text;ignored=param"
)),
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text - Choose Encoding'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndOasisOpendocumentTextFlatXml
(
self
):
"""Test allowed conversion format for application/vnd.oasis.opendocument.text-flat-xml"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.oasis.opendocument.text-flat-xml;ignored=param"
)),
[])
def
testGetAllowedConversionFormatList_ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument
(
self
):
"""Test allowed conversion format for application/vnd.openxmlformats-officedocument.wordprocessingml.document"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document;ignored=param"
)),
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text - Choose Encoding'
)
])
def
testGetAllowedConversionFormatList_ImageJpeg
(
self
):
"""Test allowed conversion format for image/jpeg"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/jpeg;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImagePng
(
self
):
"""Test allowed conversion format for image/png"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/png;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_TextHtml
(
self
):
"""Test allowed conversion format for text/html"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"text/html;ignored=param"
)),
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.ms-excel'
,
'Microsoft Excel 97-2003'
),
(
'application/vnd.ms-excel.sheet.macroEnabled.12'
,
'Microsoft Excel 2007-2016 XML (macro enabled)'
),
(
'application/vnd.oasis.opendocument.spreadsheet'
,
'ODF Spreadsheet'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text'
,
'Text (Writer/Web)'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Microsoft Excel 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Office Open XML Spreadsheet'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'application/vnd.sun.xml.writer'
,
'OpenOffice.org 1.0 Text Document (Writer/Web)'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/csv'
,
'Text CSV'
),
(
'text/html'
,
'HTML Document'
),
(
'text/html'
,
'HTML Document (Calc)'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text (Writer/Web)'
),
(
'text/plain'
,
'Text - Choose Encoding'
),
(
'text/plain'
,
'Text - Choose Encoding (Writer/Web)'
)
])
def
testGetAllowedConversionFormatList_ApplicationPostscript
(
self
):
"""Test allowed conversion format for application/postscript"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/postscript;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndOasisOpendocumentGraphics
(
self
):
"""Test allowed conversion format for application/vnd.oasis.opendocument.graphics"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.oasis.opendocument.graphics;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageGif
(
self
):
"""Test allowed conversion format for image/gif"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/gif;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageSvgXml
(
self
):
"""Test allowed conversion format for image/svg+xml"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/svg+xml;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageTiff
(
self
):
"""Test allowed conversion format for image/tiff"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/tiff;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageXCmuRaster
(
self
):
"""Test allowed conversion format for image/x-cmu-raster"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/x-cmu-raster;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageBmp
(
self
):
"""Test allowed conversion format for image/x-ms-bmp"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/x-ms-bmp;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageXPortableBitmap
(
self
):
"""Test allowed conversion format for image/x-portable-bitmap"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/x-portable-bitmap;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageXPortableGraymap
(
self
):
"""Test allowed conversion format for image/x-portable-graymap"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/x-portable-graymap;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageXPortablePixmap
(
self
):
"""Test allowed conversion format for image/x-portable-pixmap"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/x-portable-pixmap;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ImageXXpixmap
(
self
):
"""Test allowed conversion format for image/x-xpixmap"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"image/x-xpixmap;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Draw)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndMsExcel
(
self
):
"""Test allowed conversion format for application/vnd.ms-excel"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.ms-excel;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/vnd.ms-excel'
,
'Microsoft Excel 97-2003'
),
(
'application/vnd.ms-excel.sheet.macroEnabled.12'
,
'Microsoft Excel 2007-2016 XML (macro enabled)'
),
(
'application/vnd.oasis.opendocument.spreadsheet'
,
'ODF Spreadsheet'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Microsoft Excel 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Office Open XML Spreadsheet'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/csv'
,
'Text CSV'
),
(
'text/html'
,
'HTML Document (Calc)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndMsExcelSheetMacroenabled12
(
self
):
"""Test allowed conversion format for application/vnd.ms-excel.sheet.macroEnabled.12"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.ms-excel.sheet.macroEnabled.12;ignored=param"
)),
[])
def
testGetAllowedConversionFormatList_ApplicationVndOasisOpendocumentSpreadsheet
(
self
):
"""Test allowed conversion format for application/vnd.oasis.opendocument.spreadsheet"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.oasis.opendocument.spreadsheet;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/vnd.ms-excel'
,
'Microsoft Excel 97-2003'
),
(
'application/vnd.ms-excel.sheet.macroEnabled.12'
,
'Microsoft Excel 2007-2016 XML (macro enabled)'
),
(
'application/vnd.oasis.opendocument.spreadsheet'
,
'ODF Spreadsheet'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Microsoft Excel 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Office Open XML Spreadsheet'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/csv'
,
'Text CSV'
),
(
'text/html'
,
'HTML Document (Calc)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndOpenXmlFormatsOfficedocumentSpreadsheetmlSheet
(
self
):
"""Test allowed conversion format for application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/vnd.ms-excel'
,
'Microsoft Excel 97-2003'
),
(
'application/vnd.ms-excel.sheet.macroEnabled.12'
,
'Microsoft Excel 2007-2016 XML (macro enabled)'
),
(
'application/vnd.oasis.opendocument.spreadsheet'
,
'ODF Spreadsheet'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Microsoft Excel 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Office Open XML Spreadsheet'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/csv'
,
'Text CSV'
),
(
'text/html'
,
'HTML Document (Calc)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndSunXmlWriter
(
self
):
"""Test allowed conversion format for application/vnd.sun.xml.writer"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.sun.xml.writer;ignored=param"
)),
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text - Choose Encoding'
)
])
def
testGetAllowedConversionFormatList_TextCsv
(
self
):
"""Test allowed conversion format for text/csv"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"text/csv;ignored=param"
)),
[
(
'application/msword'
,
'Microsoft Word 97-2003'
),
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/rtf'
,
'Rich Text'
),
(
'application/vnd.ms-excel'
,
'Microsoft Excel 97-2003'
),
(
'application/vnd.ms-excel.sheet.macroEnabled.12'
,
'Microsoft Excel 2007-2016 XML (macro enabled)'
),
(
'application/vnd.oasis.opendocument.spreadsheet'
,
'ODF Spreadsheet'
),
(
'application/vnd.oasis.opendocument.text'
,
'ODF Text Document'
),
(
'application/vnd.oasis.opendocument.text'
,
'Text (Writer/Web)'
),
(
'application/vnd.oasis.opendocument.text-flat-xml'
,
'Flat XML ODF Text Document'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Microsoft Excel 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'Office Open XML Spreadsheet'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Microsoft Word 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'Office Open XML Text'
),
(
'application/vnd.sun.xml.writer'
,
'OpenOffice.org 1.0 Text Document (Writer/Web)'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'text/csv'
,
'Text CSV'
),
(
'text/html'
,
'HTML Document'
),
(
'text/html'
,
'HTML Document (Calc)'
),
(
'text/html'
,
'HTML Document (Writer)'
),
(
'text/plain'
,
'Text (Writer/Web)'
),
(
'text/plain'
,
'Text - Choose Encoding'
),
(
'text/plain'
,
'Text - Choose Encoding (Writer/Web)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndOasisOpendocumentPresentation
(
self
):
"""Test allowed conversion format for application/vnd.oasis.opendocument.presentation"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.oasis.opendocument.presentation;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003 AutoPlay'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing (Impress)'
),
(
'application/vnd.oasis.opendocument.presentation'
,
'ODF Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Microsoft PowerPoint 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Office Open XML Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Microsoft PowerPoint 2007-2013 XML AutoPlay'
),
# TEST it
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Office Open XML Presentation AutoPlay'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Impress)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation
(
self
):
"""Test allowed conversion format for application/vnd.openxmlformats-officedocument.presentationml.presentation"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.openxmlformats-officedocument.presentationml.presentation;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003 AutoPlay'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing (Impress)'
),
(
'application/vnd.oasis.opendocument.presentation'
,
'ODF Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Microsoft PowerPoint 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Office Open XML Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Microsoft PowerPoint 2007-2013 XML AutoPlay'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Office Open XML Presentation AutoPlay'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Impress)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshow
(
self
):
"""Test allowed conversion format for application/vnd.openxmlformats-officedocument.presentationml.slideshow"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.openxmlformats-officedocument.presentationml.slideshow;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003 AutoPlay'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing (Impress)'
),
(
'application/vnd.oasis.opendocument.presentation'
,
'ODF Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Microsoft PowerPoint 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Office Open XML Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Microsoft PowerPoint 2007-2013 XML AutoPlay'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Office Open XML Presentation AutoPlay'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Impress)'
)
])
def
testGetAllowedConversionFormatList_ApplicationVndMsPowerpoint
(
self
):
"""Test allowed conversion format for application/vnd.ms-powerpoint"""
self
.
assertEquals
(
sorted
(
Handler
.
getAllowedConversionFormatList
(
"application/vnd.ms-powerpoint;ignored=param"
)),
[
(
'application/pdf'
,
'PDF - Portable Document Format'
),
(
'application/postscript'
,
'EPS - Encapsulated PostScript'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003'
),
(
'application/vnd.ms-powerpoint'
,
'Microsoft PowerPoint 97-2003 AutoPlay'
),
(
'application/vnd.oasis.opendocument.graphics'
,
'ODF Drawing (Impress)'
),
(
'application/vnd.oasis.opendocument.presentation'
,
'ODF Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Microsoft PowerPoint 2007-2013 XML'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.presentation'
,
'Office Open XML Presentation'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Microsoft PowerPoint 2007-2013 XML AutoPlay'
),
(
'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
,
'Office Open XML Presentation AutoPlay'
),
(
'image/gif'
,
'GIF - Graphics Interchange Format'
),
(
'image/jpeg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'image/png'
,
'PNG - Portable Network Graphic'
),
(
'image/svg+xml'
,
'SVG - Scalable Vector Graphics'
),
(
'image/tiff'
,
'TIFF - Tagged Image File Format'
),
(
'image/x-ms-bmp'
,
'BMP - Windows Bitmap'
),
(
'text/html'
,
'HTML Document (Impress)'
)
])
def
test_suite
():
return
make_suite
(
TestHandler
)
cloudooo/handler/ooo/tests/testOooMimemapper.py
View file @
56edddf6
...
...
@@ -74,8 +74,10 @@ drawing_expected_tuple = (
web_expected_tuple
=
(
(
'html'
,
'HTML Document'
),
(
'jpg'
,
'JPEG - Joint Photographic Experts Group'
),
(
'odt'
,
'Text (Writer/Web)'
),
(
'pdf'
,
'PDF - Portable Document Format'
),
(
'png'
,
'PNG - Portable Network Graphic'
),
(
'sxw'
,
'OpenOffice.org 1.0 Text Document (Writer/Web)'
),
(
'txt'
,
'Text (Writer/Web)'
),
(
'txt'
,
'Text - Choose Encoding (Writer/Web)'
),
...
...
cloudooo/handler/ooo/tests/testOooServer.py
View file @
56edddf6
...
...
@@ -66,20 +66,18 @@ class TestServer(TestCase):
"""Verify if getAllowedExtensionList returns is a list with extension and
ui_name. The request is by extension"""
doc_allowed_list
=
self
.
proxy
.
getAllowedExtensionList
({
'extension'
:
"doc"
})
doc_allowed_list
.
sort
()
for
arg
in
doc_allowed_list
:
self
.
assertTrue
(
tuple
(
arg
)
in
text_expected_tuple
,
"%s not in %s"
%
(
arg
,
text_expected_tuple
))
# Verify all expected types ("doc" MAY NOT be present)
self
.
assertEquals
(
sorted
([(
a
,
b
)
for
a
,
b
in
doc_allowed_list
if
a
!=
"doc"
]),
sorted
(
list
(
filter
(
lambda
(
a
,
b
):
a
!=
"doc"
,
text_expected_tuple
))))
def
testGetAllowedExtensionListByMimetype
(
self
):
"""Verify if getAllowedExtensionList returns is a list with extension and
ui_name. The request is by mimetype"""
request_dict
=
{
"mimetype"
:
"application/msword"
}
msword_allowed_list
=
self
.
proxy
.
getAllowedExtensionList
(
request_dict
)
msword_allowed_list
.
sort
()
for
arg
in
msword_allowed_list
:
self
.
assertTrue
(
tuple
(
arg
)
in
text_expected_tuple
,
"%s not in %s"
%
(
arg
,
text_expected_tuple
))
# Verify all expected types ("doc" MAY NOT be present)
self
.
assertEquals
(
sorted
([(
a
,
b
)
for
a
,
b
in
msword_allowed_list
if
a
!=
"doc"
]),
sorted
(
list
(
filter
(
lambda
(
a
,
b
):
a
!=
"doc"
,
text_expected_tuple
))))
def
ConversionScenarioList
(
self
):
return
[
...
...
@@ -381,14 +379,9 @@ class TestServer(TestCase):
response_code
,
response_dict
,
response_message
=
\
self
.
proxy
.
getAllowedTargetItemList
(
mimetype
)
self
.
assertEquals
(
response_code
,
200
)
# Verify if all expected types are in response list
for
arg
in
text_expected_tuple
:
self
.
assertTrue
(
list
(
arg
)
in
response_dict
[
'response_data'
],
"%s not in %s"
%
(
arg
,
response_dict
[
'response_data'
]))
# Verify if all types in response list are expected
for
arg
in
response_dict
[
'response_data'
]:
self
.
assertTrue
(
tuple
(
arg
)
in
text_expected_tuple
,
"%s not in %s"
%
(
arg
,
text_expected_tuple
))
# Verify all expected types ("odt" MAY NOT be present)
self
.
assertEquals
(
sorted
([(
a
,
b
)
for
a
,
b
in
response_dict
[
'response_data'
]
if
a
!=
"odt"
]),
sorted
(
list
(
filter
(
lambda
(
a
,
b
):
a
!=
"odt"
,
text_expected_tuple
))))
def
testGetTableItemListFromOdt
(
self
):
"""Test if getTableItemList can get the table item list from odt file"""
...
...
@@ -481,10 +474,10 @@ class TestServer(TestCase):
data
=
encodestring
(
open
(
"./data/granulate_test.odt"
).
read
())
image_list
=
self
.
proxy
.
getImageItemList
(
data
,
"odt"
)
self
.
assertEquals
([[
'10000000000000C80000009CBF079A6E41EE290C.jpg'
,
''
],
[
'10000201000000C80000004E
F26C99A54A61B987
.png'
,
'TioLive Logo'
],
[
'10000201000000C80000004E
F26C99A54A61B987
.png'
,
''
],
[
'10000201000000C80000004E
85B3F70C71E07CE8
.png'
,
'TioLive Logo'
],
[
'10000201000000C80000004E
85B3F70C71E07CE8
.png'
,
''
],
[
'2000004F0000423300001370ADF6545B2997B448.svm'
,
'Python Logo'
],
[
'10000201000000C80000004E
F26C99A54A61B987
.png'
,
'Again TioLive Logo'
]],
[
'10000201000000C80000004E
85B3F70C71E07CE8
.png'
,
'Again TioLive Logo'
]],
image_list
)
def
testGetImageItemListFromDoc
(
self
):
...
...
@@ -492,10 +485,10 @@ class TestServer(TestCase):
data
=
encodestring
(
open
(
"./data/granulate_test.doc"
).
read
())
image_list
=
self
.
proxy
.
getImageItemList
(
data
,
"doc"
)
self
.
assertEquals
([[
'10000000000000C80000009CBF079A6E41EE290C.jpg'
,
''
],
[
'10000201000000C80000004E
F26C99A54A61B987
.png'
,
'TioLive Logo'
],
[
'10000201000000C80000004E
F26C99A54A61B987
.png'
,
''
],
[
'10000201000000C80000004E
85B3F70C71E07CE8
.png'
,
'TioLive Logo'
],
[
'10000201000000C80000004E
85B3F70C71E07CE8
.png'
,
''
],
[
'2000031600004233000013702113A0E70B910778.wmf'
,
'Python Logo'
],
[
'10000201000000C80000004E
F26C99A54A61B987
.png'
,
'Again TioLive Logo'
]],
[
'10000201000000C80000004E
85B3F70C71E07CE8
.png'
,
'Again TioLive Logo'
]],
image_list
)
def
testGetImageFromOdt
(
self
):
...
...
cloudooo/handler/pdf/handler.py
View file @
56edddf6
...
...
@@ -29,7 +29,7 @@
from
zope.interface
import
implements
from
cloudooo.interfaces.handler
import
IHandler
from
cloudooo.file
import
File
from
cloudooo.util
import
logger
from
cloudooo.util
import
logger
,
parseContentType
from
subprocess
import
Popen
,
PIPE
from
tempfile
import
mktemp
...
...
@@ -115,3 +115,17 @@ class Handler(object):
return
self
.
document
.
getContent
()
finally
:
self
.
document
.
trash
()
@
staticmethod
def
getAllowedConversionFormatList
(
source_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('text/plain', 'Plain Text'),
...
]
"""
source_mimetype
=
parseContentType
(
source_mimetype
).
gettype
()
if
source_mimetype
in
(
"application/pdf"
,
"pdf"
):
return
[(
"text/plain"
,
"Plain Text"
)]
return
[]
cloudooo/handler/pdf/tests/testPdfHandler.py
View file @
56edddf6
...
...
@@ -64,6 +64,19 @@ class TestHandler(HandlerTestCase):
self
.
assertEquals
(
metadata
[
"title"
],
'Set Metadata Test'
)
self
.
assertEquals
(
metadata
[
'creator'
],
'gabriel
\
'
@'
)
def
testGetAllowedConversionFormatList
(
self
):
"""Test all combination of mimetype
None of the types below define any mimetype parameter to not ignore so far.
"""
get
=
Handler
.
getAllowedConversionFormatList
# Handled mimetypes
self
.
assertEquals
(
get
(
"application/pdf;ignored=param"
),
[(
"text/plain"
,
"Plain Text"
)])
# Unhandled mimetypes
self
.
assertEquals
(
get
(
"text/plain;ignored=param"
),
[])
self
.
assertEquals
(
get
(
"text/plain;charset=UTF-8;ignored=param"
),
[])
def
test_suite
():
return
make_suite
(
TestHandler
)
cloudooo/handler/wkhtmltopdf/handler.py
View file @
56edddf6
...
...
@@ -28,9 +28,9 @@
from
zope.interface
import
implements
from
cloudooo.interfaces.handler
import
IHandler
from
cloudooo.file
import
File
from
cloudooo.util
import
logger
from
cloudooo.util
import
logger
,
parseContentType
from
subprocess
import
Popen
,
PIPE
from
tempfile
import
mktemp
from
tempfile
import
mktemp
,
mkdtemp
from
os.path
import
basename
from
base64
import
b64decode
...
...
@@ -55,6 +55,9 @@ class Handler(object):
)
return
path
def
makeTempDir
(
self
,
*
args
,
**
kw
):
return
mkdtemp
(
*
args
,
dir
=
self
.
file
.
directory_name
,
**
kw
)
def
convertPathToUrl
(
self
,
path
):
if
path
.
startswith
(
"/"
):
return
"file://"
+
path
...
...
@@ -96,6 +99,20 @@ class Handler(object):
"""
raise
NotImplementedError
@
staticmethod
def
getAllowedConversionFormatList
(
source_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('application/pdf', 'PDF - Portable Document Format'),
...
]
"""
source_mimetype
=
parseContentType
(
source_mimetype
).
gettype
()
if
source_mimetype
in
(
"text/html"
,
"htm"
,
"html"
):
return
[(
"application/pdf"
,
"PDF - Portable Document Format"
)]
return
[]
def
makeSwitchOptionList
(
self
,
allowed_option_list
,
option_dict
):
"""
A switch option is enable if it exists.
...
...
@@ -342,6 +359,8 @@ class Handler(object):
"include_in_outline"
,
],
conversion_kw
)
command
+=
self
.
makeSwitchOptionList
([
"default_header"
],
conversion_kw
)
# put cache in the temp dir - to disable cache
command
+=
[
"--cache-dir"
,
self
.
makeTempDir
(
prefix
=
"cache"
)]
command
+=
self
.
makeOneStringArgumentOptionList
([
#"cache_dir", # we decide
"encoding"
,
...
...
cloudooo/handler/wkhtmltopdf/tests/testWkhtmltopdfHandler.py
View file @
56edddf6
...
...
@@ -77,6 +77,18 @@ class TestHandler(HandlerTestCase):
handler
=
Handler
(
self
.
tmp_url
,
""
,
"png"
,
**
self
.
kw
)
self
.
assertRaises
(
NotImplementedError
,
handler
.
setMetadata
)
def
testGetAllowedConversionFormatList
(
self
):
"""Test all combination of mimetype
None of the types below define any mimetype parameter to not ignore so far.
"""
get
=
Handler
.
getAllowedConversionFormatList
# Handled mimetypes
self
.
assertEquals
(
get
(
"text/html;ignored=param"
),
[(
"application/pdf"
,
"PDF - Portable Document Format"
)])
# Unhandled mimetypes
self
.
assertEquals
(
get
(
"application/pdf;ignored=param"
),
[])
def
test_suite
():
return
make_suite
(
TestHandler
)
cloudooo/handler/x2t/handler.py
View file @
56edddf6
...
...
@@ -35,7 +35,8 @@ from zope.interface import implements
from
cloudooo.interfaces.handler
import
IHandler
from
cloudooo.file
import
File
from
cloudooo.util
import
logger
,
zipTree
,
unzip
from
cloudooo.util
import
logger
,
zipTree
,
unzip
,
parseContentType
from
cloudooo.handler.ooo.handler
import
Handler
as
OOoHandler
AVS_OFFICESTUDIO_FILE_UNKNOWN
=
"0"
AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX
=
"65"
...
...
@@ -93,6 +94,9 @@ class Handler(object):
The source format of the inputed file
"""
self
.
base_folder_url
=
base_folder_url
self
.
_data
=
data
self
.
_source_format
=
source_format
self
.
_init_kw
=
kw
self
.
file
=
File
(
base_folder_url
,
data
,
source_format
)
self
.
environment
=
kw
.
get
(
"env"
,
{})
...
...
@@ -113,6 +117,7 @@ class Handler(object):
config_file_name
=
os
.
path
.
join
(
root_dir
,
"config.xml"
)
if
source_format
in
yformat_tuple
:
if
self
.
_data
.
startswith
(
"PK
\
x03
\
x04
"
):
os
.
mkdir
(
input_dir
)
unzip
(
self
.
file
.
getUrl
(),
input_dir
)
for
_
,
_
,
files
in
os
.
walk
(
input_dir
):
...
...
@@ -169,14 +174,61 @@ class Handler(object):
self
.
file
.
trash
()
def
getMetadata
(
self
,
base_document
=
False
):
"""Returns a dictionary with all metadata of document.
along with the metadata
.
r
"""Returns a dictionary with all metadata of document.
/!\
No
t Implemented: no format are handled correctly
.
"""
raise
NotImplementedError
# XXX Cloudooo takes the first handler that can "handle" source_mimetype.
# However, docx documents metadata can only be "handled" by the ooo handler.
# Handlers should provide a way to tell if such capability is available for the required source mimetype.
# We have to define a precise direction on how to know/get what are handlers capabilities according to Cloudooo configuration.
# And then, this method MUST raise on unhandled format. Here xformats are "handled" by cheating.
if
self
.
_source_format
in
(
"docx"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
,
"xlsx"
,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
,
"pptx"
,
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
,
):
return
OOoHandler
(
self
.
base_folder_url
,
self
.
_data
,
self
.
_source_format
,
**
self
.
_init_kw
).
getMetadata
(
base_document
)
return
{}
def
setMetadata
(
self
,
metadata
=
{}):
"""Returns image with new metadata.
r"""Returns document with new metadata.
/!\
No
t Implemented: no format are handled correctly.
Keyword arguments:
metadata -- expected an dictionary with metadata.
"""
raise
NotImplementedError
# XXX Cloudooo takes the first handler that can "handle" source_mimetype.
# However, docx documents metadata can only be "handled" by the ooo handler.
# Handlers should provide a way to tell if such capability is available for the required source mimetype.
# We have to define a precise direction on how to know/get what are handlers capabilities according to Cloudooo configuration.
# And then, this method MUST raise on unhandled format. Here xformats are "handled" by cheating.
if
self
.
_source_format
in
(
"docx"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
,
"xlsx"
,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
,
"pptx"
,
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
,
):
return
OOoHandler
(
self
.
base_folder_url
,
self
.
_data
,
self
.
_source_format
,
**
self
.
_init_kw
).
setMetadata
(
metadata
)
return
self
.
file
.
getContent
()
@
staticmethod
def
getAllowedConversionFormatList
(
source_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('application/x-asc-text', 'OnlyOffice Text Document'),
...
]
"""
source_mimetype
=
parseContentType
(
source_mimetype
).
gettype
()
if
source_mimetype
in
(
"docx"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
):
return
[(
"application/x-asc-text"
,
"OnlyOffice Text Document"
)]
if
source_mimetype
in
(
"docy"
,
"application/x-asc-text"
):
return
[(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
,
"Word 2007 Document"
)]
if
source_mimetype
in
(
"xlsx"
,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
):
return
[(
"application/x-asc-spreadsheet"
,
"OnlyOffice Spreadsheet"
)]
if
source_mimetype
in
(
"xlsy"
,
"application/x-asc-spreadsheet"
):
return
[(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
,
"Excel 2007 Spreadsheet"
)]
if
source_mimetype
in
(
"pptx"
,
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
):
return
[(
"application/x-asc-presentation"
,
"OnlyOffice Presentation"
)]
if
source_mimetype
in
(
"ppty"
,
"application/x-asc-presentation"
):
return
[(
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
,
"PowerPoint 2007 Presentation"
)]
return
[]
cloudooo/handler/x2t/tests/data/test_body.xlsy
0 → 100644
View file @
56edddf6
XLSY;v2;5883;BAKAAgAAA+cHAAAEAwgAAAD3FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGMFAAAAEQAAAAEMAAAABwEAAAAACAEAAAAABAoAAAAFAAAAAAUAAAAABnwAAAAHGgAAAAQGCgAAAEEAcgBpAGEAbAAGBQAAAAAAACRABxoAAAAEBgoAAABBAHIAaQBhAGwABgUAAAAAAAAkQAcaAAAABAYKAAAAQQByAGkAYQBsAAYFAAAAAAAAJEAHGgAAAAQGCgAAAEEAcgBpAGEAbAAGBQAAAAAAACRACB8AAAAJGgAAAAAGDgAAAEcARQBOAEUAUgBBAEwAAQSkAAAADhYDAAADPwAAAAABAQEBAQMBAQYEAAAAAAcEAAAAAAgEAAAAAAkEpAAAAA0GGAAAAAABBAEEAAAAAAUBAAYEAAAAAAcBAAgBAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQBAAAACQQAAAAAAyEAAAAAAQABAQADAQEGBAAAAAAHBAAAAAAIBAEAAAAJBAAAAAADIQAAAAABAAEBAAMBAQYEAAAAAAcEAAAAAAgEAgAAAAkEAAAAAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQCAAAACQQAAAAAAyEAAAAAAQABAQADAQEGBAAAAAAHBAAAAAAIBAAAAAAJBAAAAAADIQAAAAABAAEBAAMBAQYEAAAAAAcEAAAAAAgEAAAAAAkEAAAAAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQAAAAACQQAAAAAAyEAAAAAAQABAQADAQEGBAAAAAAHBAAAAAAIBAAAAAAJBAAAAAADIQAAAAABAAEBAAMBAQYEAAAAAAcEAAAAAAgEAAAAAAkEAAAAAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQAAAAACQQAAAAAAyEAAAAAAQABAQADAQEGBAAAAAAHBAAAAAAIBAAAAAAJBAAAAAADIQAAAAABAAEBAAMBAQYEAAAAAAcEAAAAAAgEAAAAAAkEAAAAAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQAAAAACQQAAAAAAyEAAAAAAQABAQADAQEGBAAAAAAHBAAAAAAIBAAAAAAJBAAAAAADIQAAAAABAAEBAAMBAQYEAAAAAAcEAAAAAAgEAQAAAAkEKwAAAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQBAAAACQQpAAAAAyEAAAAAAQABAQADAQEGBAAAAAAHBAAAAAAIBAEAAAAJBCwAAAADIQAAAAABAAEBAAMBAQYEAAAAAAcEAAAAAAgEAQAAAAkEKgAAAAMhAAAAAAEAAQEAAwEBBgQAAAAABwQAAAAACAQBAAAACQQJAAAAAkoAAAADRQAAAAABAAEBAAMBAAYEAAAAAAcEAAAAAAgEAAAAAAkEpAAAAAwEAAAAAA0GGAAAAAABBAEEAAAAAAUBAAYEAAAAAAcBAAgBAA8qAQAAECkAAAAABAAAAAAAAAABAQAAAAAEDAAAAE4AbwByAG0AYQBsAAUEAAAAAAAAABAnAAAAAAQAAAADAAAAAQEAAAAABAoAAABDAG8AbQBtAGEABQQAAAAPAAAAEC8AAAAABAAAAAYAAAABAQAAAAAEEgAAAEMAbwBtAG0AYQAgAFsAMABdAAUEAAAAEAAAABAtAAAAAAQAAAAEAAAAAQEAAAAABBAAAABDAHUAcgByAGUAbgBjAHkABQQAAAARAAAAEDUAAAAABAAAAAcAAAABAQAAAAAEGAAAAEMAdQByAHIAZQBuAGMAeQAgAFsAMABdAAUEAAAAEgAAABArAAAAAAQAAAAFAAAAAQEAAAAABA4AAABQAGUAcgBjAGUAbgB0AAUEAAAAEwAAABgAAAAAAwAAAAABAAELAAAAAgYAAAAABAAAAADwDgAAAOsOAAABGwAAAAAGDAAAAFMAaABlAGUAdAAxAAEEAQAAAAIBAgIkAAAAAx8AAAABAQACBAEEAAADBAEAAAAEBAAAAAAFBX+XU/ByCidABAoAAABBADEAOgBDADcAFhEAAAAXDAAAAAQBAAAAAQYBAAAAAQsKAAAAAQWamZmZmZkpQA48AAAAAAVxPQrXowA0QAEFhPuDDJW9OkACBXE9CtejADRAAwWE+4MMlb06QAQFcT0K16MANEAFBXE9CtejADRADwYAAAAAAQEBAQkQBgAAAAABAQEBAAlVBQAACr4AAAAABAEAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAAAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAADwPwUpAAAABQgAAAAAAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAAAEAFQQAAAAUIAAAAAAAAAAIAAAABBAAAAAAAAAACAQAAAAQEEwAAAAABAAwGCgAAAEEAMQArAEIAMQADCAAAAAAAAAAAAAhACr4AAAAABAIAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAEAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAAAAQAUpAAAABQgAAAABAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAACEAFQQAAAAUIAAAAAQAAAAIAAAABBAAAAAAAAAACAQAAAAQEEwAAAAABAAwGCgAAAEEAMgArAEIAMgADCAAAAAAAAAAAABRACr4AAAAABAMAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAIAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAAAIQAUpAAAABQgAAAACAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAAEEAFQQAAAAUIAAAAAgAAAAIAAAABBAAAAAAAAAACAQAAAAQEEwAAAAABAAwGCgAAAEEAMwArAEIAMwADCAAAAAAAAAAAABxACr4AAAAABAQAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAMAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAAAQQAUpAAAABQgAAAADAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAAFEAFQQAAAAUIAAAAAwAAAAIAAAABBAAAAAAAAAACAQAAAAQEEwAAAAABAAwGCgAAAEEANAArAEIANAADCAAAAAAAAAAAACJACr4AAAAABAUAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAQAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAAAUQAUpAAAABQgAAAAEAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAAGEAFQQAAAAUIAAAABAAAAAIAAAABBAAAAAAAAAACAQAAAAQEEwAAAAABAAwGCgAAAEEANQArAEIANQADCAAAAAAAAAAAACZACr4AAAAABAYAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAUAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAAAYQAUpAAAABQgAAAAFAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAAHEAFQQAAAAUIAAAABQAAAAIAAAABBAAAAAAAAAACAQAAAAQEEwAAAAABAAwGCgAAAEEANgArAEIANgADCAAAAAAAAAAAACpACr4AAAAABAcAAAACBZqZmZmZmSlAAwEABgEABAaiAAAABSkAAAAFCAAAAAYAAAAAAAAAAQQAAAAAAAAAAgEAAAAEAwgAAAAAAAAAAAAcQAUpAAAABQgAAAAGAAAAAQAAAAEEAAAAAAAAAAIBAAAABAMIAAAAAAAAAAAAIEAFQQAAAAUIAAAABgAAAAIAAAABBAAAAAAAAAAC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
\ No newline at end of file
cloudooo/handler/x2t/tests/testX2tHandler.py
View file @
56edddf6
...
...
@@ -51,6 +51,8 @@ class TestHandler(HandlerTestCase):
def
testConvertXlsy
(
self
):
"""Test conversion of xlsy to xlsx and back"""
x_data
=
Handler
(
self
.
tmp_url
,
open
(
"data/test_body.xlsy"
).
read
(),
"xlsy"
,
**
self
.
kw
).
convert
(
"xlsx"
)
self
.
assertIn
(
"xl/"
,
x_data
[:
2000
])
x_data
=
Handler
(
self
.
tmp_url
,
open
(
"data/test.xlsy"
).
read
(),
"xlsy"
,
**
self
.
kw
).
convert
(
"xlsx"
)
self
.
assertIn
(
"xl/"
,
x_data
[:
2000
])
...
...
@@ -81,16 +83,38 @@ class TestHandler(HandlerTestCase):
self
.
assertTrue
(
y_body_data
.
startswith
(
"DOCY;v5;7519;"
),
"%r... does not start with 'DOCY;v5;7519;'"
%
(
y_body_data
[:
20
],))
y_zip
.
open
(
"media/image1.png"
)
def
testgetMetadata
FromImage
(
self
):
"""Test getMetadata
not implemented form yformats
"""
def
testgetMetadata
(
self
):
"""Test getMetadata
from yformats (not implemented)
"""
handler
=
Handler
(
self
.
tmp_url
,
""
,
"xlsy"
,
**
self
.
kw
)
self
.
assertRaises
(
NotImplementedError
,
handler
.
getMetadata
)
# Of course, expected behavior should be a dict of internal metadata
# but don't know how to handle it so far.
self
.
assertEquals
(
handler
.
getMetadata
(),
{})
def
testsetMetadata
(
self
):
"""Test setMetadata
not implemented for yformats
"""
"""Test setMetadata
for yformats (not implemented)
"""
handler
=
Handler
(
self
.
tmp_url
,
""
,
"xlsy"
,
**
self
.
kw
)
self
.
assertRaises
(
NotImplementedError
,
handler
.
setMetadata
)
# Of course, expected behavior should be an updated data with new
# internal metadata but don't know how to handle it so far.
self
.
assertEquals
(
handler
.
setMetadata
(),
""
)
def
testGetAllowedConversionFormatList
(
self
):
"""Test all combination of mimetype
None of the types below define any mimetype parameter to not ignore so far.
"""
get
=
Handler
.
getAllowedConversionFormatList
self
.
assertEquals
(
get
(
"application/x-asc-text;ignored=param"
),
[(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
,
"Word 2007 Document"
)])
self
.
assertEquals
(
get
(
"application/x-asc-spreadsheet;ignored=param"
),
[(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
,
"Excel 2007 Spreadsheet"
)])
self
.
assertEquals
(
get
(
"application/x-asc-presentation;ignored=param"
),
[(
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
,
"PowerPoint 2007 Presentation"
)])
self
.
assertEquals
(
get
(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document;ignored=param"
),
[(
"application/x-asc-text"
,
"OnlyOffice Text Document"
)])
self
.
assertEquals
(
get
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;ignored=param"
),
[(
"application/x-asc-spreadsheet"
,
"OnlyOffice Spreadsheet"
)])
self
.
assertEquals
(
get
(
"application/vnd.openxmlformats-officedocument.presentationml.presentation;ignored=param"
),
[(
"application/x-asc-presentation"
,
"OnlyOffice Presentation"
)])
def
test_suite
():
return
make_suite
(
TestHandler
)
cloudooo/interfaces/manager.py
View file @
56edddf6
...
...
@@ -87,7 +87,7 @@ class IManager(Interface):
metadata_dict : Metadatas to include in content
"""
def
getAllowedConversionFormatList
(
source_mimetype
):
def
getAllowedConversionFormatList
(
s
elf
,
s
ource_mimetype
):
"""Returns a list content_type and their titles which are supported
by enabled handlers.
...
...
cloudooo/manager.py
View file @
56edddf6
...
...
@@ -28,11 +28,11 @@
##############################################################################
import
mimetypes
from
mimetypes
import
guess_all_extensions
,
guess_extension
from
mimetypes
import
guess_
type
,
guess_
all_extensions
,
guess_extension
from
base64
import
encodestring
,
decodestring
from
zope.interface
import
implements
from
interfaces.manager
import
IManager
,
IERP5Compatibility
from
cloudooo.util
import
logger
from
cloudooo.util
import
logger
,
parseContentType
from
cloudooo.interfaces.granulate
import
ITableGranulator
from
cloudooo.interfaces.granulate
import
IImageGranulator
from
cloudooo.interfaces.granulate
import
ITextGranulator
...
...
@@ -41,6 +41,7 @@ from fnmatch import fnmatch
#XXX Must be removed
from
cloudooo.handler.ooo.granulator
import
OOGranulator
from
cloudooo.handler.ooo.mimemapper
import
mimemapper
from
cloudooo.handler.wkhtmltopdf.handler
import
Handler
as
WkhtmltopdfHandler
class
HandlerNotFound
(
Exception
):
pass
...
...
@@ -59,6 +60,35 @@ def getHandlerClass(source_format, destination_format, mimetype_registry,
raise
HandlerNotFound
(
'No Handler found for %r=>%r'
%
(
source_format
,
destination_format
))
def
BBB_guess_type
(
url
):
base
=
url
.
split
(
"/"
)[
-
1
].
lstrip
(
"."
)
# if base.endswith(".ms.docx"): return ("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Microsoft Word 2007-2013 XML")
split
=
base
.
split
(
"."
)
ext
=
''
if
len
(
split
)
==
1
else
split
[
-
1
]
return
{
"docy"
:
(
"application/x-asc-text"
,
None
),
"xlsy"
:
(
"application/x-asc-spreadsheet"
,
None
),
"ppty"
:
(
"application/x-asc-presentation"
,
None
),
}.
get
(
ext
,
None
)
or
guess_type
(
url
)
def
BBB_guess_extension
(
mimetype
,
title
=
None
):
return
{
# title : extension
"Flat XML ODF Text Document"
:
".fodt"
,
"MET - OS/2 Metafile"
:
".met"
,
"Microsoft Excel 2007-2013 XML"
:
".ms.xlsx"
,
"Microsoft PowerPoint 2007-2013 XML"
:
".ms.pptx"
,
"Microsoft PowerPoint 2007-2013 XML AutoPlay"
:
".ms.ppsx"
,
"Microsoft Word 2007-2013 XML"
:
".ms.docx"
,
}.
get
(
title
,
None
)
or
{
# mediatype : extension
"application/postscript"
:
".eps"
,
"application/vnd.ms-excel"
:
".xls"
,
"application/vnd.ms-excel.sheet.macroenabled.12"
:
".xlsm"
,
"application/vnd.ms-powerpoint"
:
".ppt"
,
"text/plain"
:
".txt"
,
"image/jpeg"
:
".jpg"
,
}.
get
(
parseContentType
(
mimetype
).
gettype
(),
None
)
or
guess_extension
(
mimetype
)
class
Manager
(
object
):
"""Manipulates requisitons of client and temporary files in file system."""
...
...
@@ -84,6 +114,19 @@ class Manager(object):
"""
self
.
kw
[
'zip'
]
=
zip
self
.
kw
[
'refresh'
]
=
refresh
# XXX Force the use of wkhtmltopdf handler if converting from html to pdf
# with conversion parameters.
# This is a hack that quickly enables the use of wkhtmltopdf without
# conflicting with other "html to pdf" conversion method
# (i.e. using the ooo handler) that does not use such a parameter.
# This hack should be removed after defining and implementing a way to
# use the conversion_kw in a possible interoperable way between all
# "html to pdf" handlers.
if
(
conversion_kw
and
source_format
in
(
"html"
,
"text/html"
)
and
destination_format
in
(
"pdf"
,
"application/pdf"
)):
handler_class
=
WkhtmltopdfHandler
else
:
handler_class
=
getHandlerClass
(
source_format
,
destination_format
,
self
.
mimetype_registry
,
...
...
@@ -143,36 +186,69 @@ class Manager(object):
return
metadata_dict
def
getAllowedExtensionList
(
self
,
request_dict
=
{}):
"""List types which can be generated from given type
"""BBB: extension should not be used, use MIMEType with getAllowedConversionFormatList
List extension which can be generated from given type
Type can be given as:
- content type
- filename extension
- document type ('text', 'spreadsheet', 'presentation' or 'drawing')
e.g
self.getAllowedMimetypeList(dict(document_type="text"))
return extension_list
- document type
"""
mimetype
=
request_dict
.
get
(
'mimetype'
)
extension
=
request_dict
.
get
(
'extension'
)
document_type
=
request_dict
.
get
(
'document_type'
)
if
mimetype
:
allowed_extension_list
=
[]
for
ext
in
guess_all_extensions
(
mimetype
):
ext
=
ext
.
replace
(
'.'
,
''
)
extension_list
=
mimemapper
.
getAllowedExtensionList
(
extension
=
ext
,
document_type
=
document_type
)
for
extension
in
extension_list
:
if
extension
not
in
allowed_extension_list
:
allowed_extension_list
.
append
(
extension
)
return
allowed_extension_list
elif
extension
:
extension
=
extension
.
replace
(
'.'
,
''
)
return
mimemapper
.
getAllowedExtensionList
(
extension
=
extension
,
document_type
=
document_type
)
if
not
mimetype
:
if
extension
:
mimetype
,
_
=
BBB_guess_type
(
"a."
+
extension
)
elif
document_type
:
# BBB no other choice than to ask ooo.mimemapper
return
mimemapper
.
getAllowedExtensionList
(
document_type
=
document_type
)
if
mimetype
:
allowed_extension_set
=
set
()
for
content_type
,
title
in
self
.
getAllowedConversionFormatList
(
mimetype
):
ext
=
BBB_guess_extension
(
content_type
,
title
)
if
ext
:
allowed_extension_set
.
add
((
ext
.
lstrip
(
'.'
),
title
))
return
list
(
allowed_extension_set
)
or
[(
''
,
''
)]
else
:
return
[(
''
,
''
)]
def
getAllowedConversionFormatList
(
self
,
source_mimetype
):
r"""Returns a list content_type and their titles which are supported
by enabled handlers.
[('application/vnd.oasis.opendocument.text', 'ODF Text Document'),
('application/pdf', 'PDF - Portable Document Format'),
...
]
This methods gets handler conversion mimetype availability according
to Cloudooo's mimetype registry.
/!\
u
nlike `self.getAllowedExtensionList`, it may return empty list
instead of `[('', '')]`.
/!\
the returned list may have the same mimetype twice with different title.
"""
handler_dict
=
{}
# handler_dict["ooo"] = ["text/*", "application/*"]
for
entry
in
self
.
mimetype_registry
:
split_entry
=
entry
.
split
()
if
fnmatch
(
source_mimetype
,
split_entry
[
0
]):
if
split_entry
[
2
]
in
handler_dict
:
handler_dict
[
split_entry
[
2
]].
append
(
split_entry
[
1
])
else
:
handler_dict
[
split_entry
[
2
]]
=
[
split_entry
[
1
]]
output_mimetype_set
=
set
()
for
handler
,
mimetype_filter_list
in
handler_dict
.
items
():
for
output_mimetype
in
self
.
handler_dict
[
handler
].
getAllowedConversionFormatList
(
source_mimetype
):
for
mimetype_filter
in
mimetype_filter_list
:
if
fnmatch
(
output_mimetype
[
0
],
mimetype_filter
):
output_mimetype_set
.
add
(
output_mimetype
)
break
return
list
(
output_mimetype_set
)
def
run_convert
(
self
,
filename
=
''
,
data
=
None
,
meta
=
None
,
extension
=
None
,
orig_format
=
None
):
"""Method to support the old API. Wrapper getFileMetadataItemList but
...
...
@@ -242,7 +318,7 @@ class Manager(object):
"""
# calculate original extension required by convertFile from
# given content_type (orig_format)
original_extension
=
guess_extension
(
orig_format
).
strip
(
'.'
)
original_extension
=
BBB_
guess_extension
(
orig_format
).
strip
(
'.'
)
# XXX - ugly way to remove "/" and "."
orig_format
=
orig_format
.
split
(
'.'
)[
-
1
]
orig_format
=
orig_format
.
split
(
'/'
)[
-
1
]
...
...
@@ -282,7 +358,12 @@ class Manager(object):
"""
response_dict
=
{}
try
:
extension_list
=
self
.
getAllowedExtensionList
({
"mimetype"
:
content_type
})
mimetype_list
=
self
.
getAllowedConversionFormatList
(
content_type
)
extension_list
=
[]
for
m
,
t
in
mimetype_list
:
ext
=
BBB_guess_extension
(
m
,
t
)
if
ext
:
extension_list
.
append
((
ext
.
lstrip
(
'.'
),
t
))
response_dict
[
'response_data'
]
=
extension_list
return
(
200
,
response_dict
,
''
)
except
Exception
,
e
:
...
...
cloudooo/util.py
View file @
56edddf6
...
...
@@ -30,6 +30,8 @@ import logging
import
mimetypes
import
pkg_resources
import
os
import
mimetools
import
cStringIO
from
zipfile
import
ZipFile
,
ZIP_DEFLATED
logger
=
logging
.
getLogger
(
'Cloudooo'
)
...
...
@@ -133,3 +135,18 @@ def unzip(source, destination):
zipfile
=
ZipFile
(
source
)
zipfile
.
extractall
(
destination
)
zipfile
.
close
()
def
parseContentType
(
content_type
):
"""Parses `text/plain;charset="utf-8"` to a mimetools.Message object.
Note: Content type or MIME type are built like `maintype/subtype[;params]`.
parsed_content_type = parseContentType('text/plain;charset="utf-8"')
parsed_content_type.gettype() -> 'text/plain'
parsed_content_type.getmaintype() -> 'text'
parsed_content_type.getsubtype() -> 'plain'
parsed_content_type.getplist() -> 'charset="utf-8"'
parsed_content_type.getparam('charset') -> 'utf-8'
parsed_content_type.typeheader -> 'text/plain;charset="utf-8"'
"""
return
mimetools
.
Message
(
cStringIO
.
StringIO
(
"Content-Type:"
+
content_type
.
replace
(
"
\
r
\
n
"
,
"
\
r
\
n
\
t
"
)))
Boris Kocherov
@bk
mentioned in commit
fc6e4976
·
Feb 17, 2017
mentioned in commit
fc6e4976
mentioned in commit fc6e4976cb0beca6665e8094d89f3fa6e55c6319
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment