Added
Link Here
|
1 |
#ifndef _OSL_DIAGNOSE_H_ |
2 |
#include <osl/diagnose.h> |
3 |
#endif |
4 |
#ifndef _RTL_TENCINFO_H_ |
5 |
#include <rtl/tencinfo.h> |
6 |
#endif |
7 |
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ |
8 |
#include <com/sun/star/lang/XMultiServiceFactory.hpp> |
9 |
#endif |
10 |
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ |
11 |
#include <com/sun/star/io/XInputStream.hpp> |
12 |
#endif |
13 |
#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_ |
14 |
#include <com/sun/star/xml/sax/XAttributeList.hpp> |
15 |
#endif |
16 |
#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_ |
17 |
#include <com/sun/star/xml/sax/XDocumentHandler.hpp> |
18 |
#endif |
19 |
#ifndef _COM_SUN_STAR_XML_SAX_XPARSER_HPP_ |
20 |
#include <com/sun/star/xml/sax/XParser.hpp> |
21 |
#endif |
22 |
#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HPP |
23 |
#include <com/sun/star/ucb/XCommandEnvironment.hpp> |
24 |
#endif |
25 |
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ |
26 |
#include <com/sun/star/io/XInputStream.hpp> |
27 |
#endif |
28 |
#ifndef _ATTRLIST_HPP_ |
29 |
#include <xmloff/attrlist.hxx> |
30 |
#endif |
31 |
#ifndef _XMLKYWD_HPP |
32 |
#include <xmloff/xmlkywd.hxx> |
33 |
#endif |
34 |
|
35 |
#ifndef _UCBHELPER_CONTENT_HXX |
36 |
#include <ucbhelper/content.hxx> |
37 |
#endif |
38 |
|
39 |
#include <tools/stream.hxx> |
40 |
|
41 |
#include "LotusWordProImportFilter.hxx" |
42 |
|
43 |
#include <vector> |
44 |
|
45 |
using namespace ::rtl; |
46 |
using rtl::OString; |
47 |
using rtl::OUStringBuffer; |
48 |
using rtl::OUString; |
49 |
using com::sun::star::uno::Sequence; |
50 |
using com::sun::star::uno::Reference; |
51 |
using com::sun::star::lang::XComponent; |
52 |
using com::sun::star::uno::Any; |
53 |
using com::sun::star::uno::UNO_QUERY; |
54 |
using com::sun::star::uno::XInterface; |
55 |
using com::sun::star::uno::Exception; |
56 |
using com::sun::star::uno::RuntimeException; |
57 |
using com::sun::star::io::XInputStream; |
58 |
using com::sun::star::lang::XMultiServiceFactory; |
59 |
using com::sun::star::beans::PropertyValue; |
60 |
using com::sun::star::document::XFilter; |
61 |
using com::sun::star::document::XExtendedFilterDetection; |
62 |
using com::sun::star::ucb::XCommandEnvironment; |
63 |
|
64 |
using com::sun::star::document::XImporter; |
65 |
using com::sun::star::xml::sax::XAttributeList; |
66 |
using com::sun::star::xml::sax::XDocumentHandler; |
67 |
using com::sun::star::xml::sax::XParser; |
68 |
|
69 |
// W o r d P r o |
70 |
static const sal_Int8 header[] = { 0x57, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f }; |
71 |
|
72 |
const sal_Int32 MAXCHARS = 65534; |
73 |
|
74 |
// Simple xml importer, currently the importer is very very simple |
75 |
// it only extracts pure text from the wordpro file. Absolutely no formating |
76 |
// information is currently imported. |
77 |
// To reflect the current state of this importer the sax events sent |
78 |
// to the document handler are also the simplest possible. In addition to |
79 |
// the the basic attributes set up for the 'office:document' element |
80 |
// all the imported text is inserted into 'text:p' elements. |
81 |
// The parser extracts the pure text and creates simple a simple 'text:p' |
82 |
// element to contain that text. In the event of the text exceeding |
83 |
// MAXCHARS new 'text:p' elements are created as needed |
84 |
class SimpleXMLImporter |
85 |
{ |
86 |
private: |
87 |
|
88 |
Reference< XDocumentHandler > m_xDocHandler; |
89 |
std::vector< OUString > m_vStringChunks; |
90 |
SvStream& m_InputStream; |
91 |
|
92 |
bool CheckValidData( sal_Int8 nChar ) |
93 |
{ |
94 |
if( ( nChar >= 0x20 && nChar <= 0x7E ) && ( nChar != 0X40 ) ) |
95 |
return true; |
96 |
return false; |
97 |
} |
98 |
|
99 |
void addAttribute( SvXMLAttributeList* pAttrList, const char* key, const char* val ) |
100 |
{ |
101 |
pAttrList->AddAttribute( OUString::createFromAscii( key ), OUString::createFromAscii( val ) ); |
102 |
} |
103 |
|
104 |
void writeTextChunk( const OUString& sChunk ) |
105 |
{ |
106 |
SvXMLAttributeList *pAttrList = new SvXMLAttributeList(); |
107 |
Reference < XAttributeList > xAttrList(pAttrList); |
108 |
|
109 |
pAttrList->AddAttribute( OUString(RTL_CONSTASCII_USTRINGPARAM("text:style-name")), OUString(RTL_CONSTASCII_USTRINGPARAM("Standard"))); |
110 |
|
111 |
m_xDocHandler->startElement( OUString(RTL_CONSTASCII_USTRINGPARAM("text:p")), xAttrList ); |
112 |
m_xDocHandler->characters( sChunk ); |
113 |
m_xDocHandler->endElement( OUString(RTL_CONSTASCII_USTRINGPARAM("text:p") ) ); |
114 |
} |
115 |
|
116 |
void writeDocContentPreamble() |
117 |
{ |
118 |
SvXMLAttributeList *pDocContentPropList = new SvXMLAttributeList(); |
119 |
Reference < XAttributeList > xDocContentList(pDocContentPropList); |
120 |
addAttribute( pDocContentPropList, "xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" ); |
121 |
addAttribute( pDocContentPropList, "xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"); |
122 |
addAttribute( pDocContentPropList, "xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" ); |
123 |
addAttribute( pDocContentPropList, "xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" ); |
124 |
addAttribute( pDocContentPropList, "xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" ); |
125 |
addAttribute( pDocContentPropList, "xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" ); |
126 |
addAttribute( pDocContentPropList, "xmlns:xlink", "http://www.w3.org/1999/xlink" ); |
127 |
addAttribute( pDocContentPropList, "xmlns:dc", "http://purl.org/dc/elements/1.1/" ); |
128 |
addAttribute( pDocContentPropList, "xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0" ); |
129 |
addAttribute( pDocContentPropList, "xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" ); |
130 |
addAttribute( pDocContentPropList, "xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" ); |
131 |
addAttribute( pDocContentPropList, "xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" ); |
132 |
addAttribute( pDocContentPropList, "xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" ); |
133 |
addAttribute( pDocContentPropList, "xmlns:math", "http://www.w3.org/1998/Math/MathML" ); |
134 |
addAttribute( pDocContentPropList, "xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0" ); |
135 |
addAttribute( pDocContentPropList, "xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0" ); |
136 |
addAttribute( pDocContentPropList, "xmlns:ooo", "http://openoffice.org/2004/office" ); |
137 |
addAttribute( pDocContentPropList, "xmlns:ooow", "http://openoffice.org/2004/writer" ); |
138 |
addAttribute( pDocContentPropList, "xmlns:oooc", "http://openoffice.org/2004/calc" ); |
139 |
addAttribute( pDocContentPropList, "xmlns:dom", "http://www.w3.org/2001/xml-events" ); |
140 |
addAttribute( pDocContentPropList, "xmlns:xforms", "http://www.w3.org/2002/xforms" ); |
141 |
addAttribute( pDocContentPropList, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); |
142 |
addAttribute( pDocContentPropList, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); |
143 |
addAttribute( pDocContentPropList, "office:version", "1.0"); |
144 |
m_xDocHandler->startElement(OUString(RTL_CONSTASCII_USTRINGPARAM("office:document-content" ) ), xDocContentList ); |
145 |
} |
146 |
|
147 |
void parseDoc() |
148 |
{ |
149 |
UINT8 nDelim, nDummy, nLen, nData; |
150 |
UINT16 nOpcode; |
151 |
int nCount = 0; |
152 |
OUStringBuffer sBuf( MAXCHARS ); |
153 |
sal_Int32 nChars = 0; |
154 |
|
155 |
while( !m_InputStream.IsEof()) |
156 |
{ |
157 |
m_InputStream >> nDelim; |
158 |
if( nDelim == 0x40 ) |
159 |
{ |
160 |
m_InputStream >> nDummy >> nOpcode; |
161 |
switch( nOpcode ) |
162 |
{ |
163 |
case 0xC00B: // Dictionary Word |
164 |
m_InputStream >> nLen >> nDummy; |
165 |
while( nLen > 0 && !m_InputStream.IsEof() ) |
166 |
{ |
167 |
UINT8 nChar; |
168 |
m_InputStream >> nChar; |
169 |
if( CheckValidData( nChar ) ) |
170 |
{ |
171 |
sBuf.appendAscii( (sal_Char*)(&nChar),1 ); |
172 |
if ( ++nChars >= MAXCHARS ) |
173 |
{ |
174 |
m_vStringChunks.push_back( sBuf.makeStringAndClear() ); |
175 |
nChars = 0; |
176 |
} |
177 |
} |
178 |
nLen--; |
179 |
} |
180 |
break; |
181 |
|
182 |
case 0x0242: // Non Dictionary word |
183 |
m_InputStream >> nData; |
184 |
if( nData == 0x02 ) |
185 |
{ |
186 |
m_InputStream >> nLen >> nDummy; |
187 |
while( nLen > 0 && !m_InputStream.IsEof() ) |
188 |
{ |
189 |
m_InputStream >> nData; |
190 |
if( CheckValidData( nData ) ) |
191 |
{ |
192 |
sBuf.appendAscii( (sal_Char*)(&nData),1 ); |
193 |
if ( ++nChars >= MAXCHARS ) |
194 |
{ |
195 |
m_vStringChunks.push_back( sBuf.makeStringAndClear() ); |
196 |
nChars = 0; |
197 |
} |
198 |
} |
199 |
nLen--; |
200 |
} |
201 |
} |
202 |
break; |
203 |
} |
204 |
} |
205 |
} |
206 |
if ( nChars ) |
207 |
m_vStringChunks.push_back( sBuf.makeStringAndClear() ); |
208 |
} |
209 |
|
210 |
void writeXML() |
211 |
{ |
212 |
if ( m_vStringChunks.size() ) |
213 |
{ |
214 |
m_xDocHandler->startDocument(); |
215 |
SvXMLAttributeList *pAttrList = new SvXMLAttributeList(); |
216 |
writeDocContentPreamble(); // writes "office:document-content" elem |
217 |
Reference < XAttributeList > xAttrList(pAttrList); |
218 |
|
219 |
m_xDocHandler->startElement( OUString(RTL_CONSTASCII_USTRINGPARAM("office:body")), xAttrList ); |
220 |
|
221 |
// process strings imported |
222 |
std::vector< OUString >::const_iterator it = m_vStringChunks.begin(); |
223 |
std::vector< OUString >::const_iterator it_end = m_vStringChunks.end(); |
224 |
for ( ; it!=it_end; ++it ) |
225 |
writeTextChunk( *it ); |
226 |
|
227 |
m_xDocHandler->endElement( OUString(RTL_CONSTASCII_USTRINGPARAM("office:body") ) ); |
228 |
m_xDocHandler->endElement( OUString(RTL_CONSTASCII_USTRINGPARAM("office:document-content"))); |
229 |
m_xDocHandler->endDocument(); |
230 |
} |
231 |
} |
232 |
public: |
233 |
|
234 |
SimpleXMLImporter( const Reference< XDocumentHandler >& xDocHandler, SvStream& rStream ) : m_xDocHandler( xDocHandler ), m_InputStream( rStream ) {} |
235 |
|
236 |
void import() |
237 |
{ |
238 |
parseDoc(); |
239 |
writeXML(); |
240 |
} |
241 |
}; |
242 |
|
243 |
sal_Bool SAL_CALL LotusWordProImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) |
244 |
throw (RuntimeException) |
245 |
{ |
246 |
|
247 |
sal_Int32 nLength = aDescriptor.getLength(); |
248 |
const PropertyValue * pValue = aDescriptor.getConstArray(); |
249 |
OUString sURL; |
250 |
Reference < XInputStream > xInputStream; |
251 |
for ( sal_Int32 i = 0 ; i < nLength; i++) |
252 |
{ |
253 |
if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) |
254 |
pValue[i].Value >>= xInputStream; |
255 |
else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) |
256 |
pValue[i].Value >>= sURL; |
257 |
rtl_TextEncoding encoding = RTL_TEXTENCODING_INFO_ASCII; |
258 |
} |
259 |
if ( !xInputStream.is() ) |
260 |
{ |
261 |
OSL_ASSERT( 0 ); |
262 |
return sal_False; |
263 |
} |
264 |
|
265 |
OString sFileName; |
266 |
sFileName = OUStringToOString(sURL, RTL_TEXTENCODING_INFO_ASCII); |
267 |
|
268 |
SvFileStream inputStream( sURL, STREAM_READ ); |
269 |
if ( inputStream.IsEof() || ( inputStream.GetError() != SVSTREAM_OK ) ) |
270 |
return sal_False; |
271 |
|
272 |
// An XML import service: what we push sax messages to.. |
273 |
OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XMLImporter" ) ); |
274 |
|
275 |
Reference< XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); |
276 |
Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); |
277 |
xImporter->setTargetDocument(mxDoc); |
278 |
|
279 |
SimpleXMLImporter xmlImporter( xInternalHandler, inputStream ); |
280 |
xmlImporter.import(); |
281 |
|
282 |
return sal_True; |
283 |
} |
284 |
|
285 |
sal_Bool SAL_CALL LotusWordProImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) |
286 |
throw (RuntimeException) |
287 |
{ |
288 |
return importImpl ( aDescriptor ); |
289 |
} |
290 |
void SAL_CALL LotusWordProImportFilter::cancel( ) |
291 |
throw (RuntimeException) |
292 |
{ |
293 |
} |
294 |
|
295 |
// XImporter |
296 |
void SAL_CALL LotusWordProImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc ) |
297 |
throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) |
298 |
{ |
299 |
meType = FILTER_IMPORT; |
300 |
mxDoc = xDoc; |
301 |
} |
302 |
|
303 |
// XExtendedFilterDetection |
304 |
OUString SAL_CALL LotusWordProImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) |
305 |
throw( com::sun::star::uno::RuntimeException ) |
306 |
{ |
307 |
|
308 |
OUString sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "" ) ); |
309 |
sal_Int32 nLength = Descriptor.getLength(); |
310 |
sal_Int32 location = nLength; |
311 |
OUString sURL; |
312 |
const PropertyValue * pValue = Descriptor.getConstArray(); |
313 |
Reference < XInputStream > xInputStream; |
314 |
for ( sal_Int32 i = 0 ; i < nLength; i++) |
315 |
{ |
316 |
if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) |
317 |
location=i; |
318 |
else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) |
319 |
pValue[i].Value >>= xInputStream; |
320 |
else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) |
321 |
pValue[i].Value >>= sURL; |
322 |
|
323 |
rtl_TextEncoding encoding = RTL_TEXTENCODING_INFO_ASCII; |
324 |
} |
325 |
|
326 |
Reference< com::sun::star::ucb::XCommandEnvironment > xEnv; |
327 |
if (!xInputStream.is()) |
328 |
{ |
329 |
try |
330 |
{ |
331 |
::ucb::Content aContent(sURL, xEnv); |
332 |
xInputStream = aContent.openStream(); |
333 |
} |
334 |
catch ( Exception& ) |
335 |
{ |
336 |
return ::rtl::OUString(); |
337 |
} |
338 |
|
339 |
if (!xInputStream.is()) |
340 |
return ::rtl::OUString(); |
341 |
} |
342 |
|
343 |
Sequence< ::sal_Int8 > aData; |
344 |
sal_Int32 nLen = sizeof( header ) / sizeof( header[0] ); |
345 |
if ( ( nLen == xInputStream->readBytes( aData, nLen ) ) ) |
346 |
if ( memcmp( ( void* )header, (void*) aData.getConstArray(), nLen ) == 0 ) |
347 |
sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "writer_LotusWordPro_Document" ) ); |
348 |
return sTypeName; |
349 |
} |
350 |
|
351 |
|
352 |
// XInitialization |
353 |
void SAL_CALL LotusWordProImportFilter::initialize( const Sequence< Any >& aArguments ) |
354 |
throw (Exception, RuntimeException) |
355 |
{ |
356 |
Sequence < PropertyValue > aAnySeq; |
357 |
sal_Int32 nLength = aArguments.getLength(); |
358 |
if ( nLength && ( aArguments[0] >>= aAnySeq ) ) |
359 |
{ |
360 |
const PropertyValue * pValue = aAnySeq.getConstArray(); |
361 |
nLength = aAnySeq.getLength(); |
362 |
for ( sal_Int32 i = 0 ; i < nLength; i++) |
363 |
{ |
364 |
if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) |
365 |
{ |
366 |
pValue[i].Value >>= msFilterName; |
367 |
break; |
368 |
} |
369 |
} |
370 |
} |
371 |
} |
372 |
OUString LotusWordProImportFilter_getImplementationName () |
373 |
throw (RuntimeException) |
374 |
{ |
375 |
return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.LotusWordProImportFilter" ) ); |
376 |
} |
377 |
|
378 |
#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" |
379 |
#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" |
380 |
sal_Bool SAL_CALL LotusWordProImportFilter_supportsService( const OUString& ServiceName ) |
381 |
throw (RuntimeException) |
382 |
{ |
383 |
return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || |
384 |
ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); |
385 |
} |
386 |
Sequence< OUString > SAL_CALL LotusWordProImportFilter_getSupportedServiceNames( ) |
387 |
throw (RuntimeException) |
388 |
{ |
389 |
Sequence < OUString > aRet(2); |
390 |
// Sequence < OUString > aRet(1); |
391 |
OUString* pArray = aRet.getArray(); |
392 |
pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); |
393 |
pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); |
394 |
return aRet; |
395 |
} |
396 |
#undef SERVICE_NAME2 |
397 |
#undef SERVICE_NAME1 |
398 |
|
399 |
Reference< XInterface > SAL_CALL LotusWordProImportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) |
400 |
throw( Exception ) |
401 |
{ |
402 |
return (cppu::OWeakObject*) new LotusWordProImportFilter( rSMgr ); |
403 |
} |
404 |
|
405 |
// XServiceInfo |
406 |
OUString SAL_CALL LotusWordProImportFilter::getImplementationName( ) |
407 |
throw (RuntimeException) |
408 |
{ |
409 |
return LotusWordProImportFilter_getImplementationName(); |
410 |
} |
411 |
sal_Bool SAL_CALL LotusWordProImportFilter::supportsService( const OUString& rServiceName ) |
412 |
throw (RuntimeException) |
413 |
{ |
414 |
return LotusWordProImportFilter_supportsService( rServiceName ); |
415 |
} |
416 |
Sequence< OUString > SAL_CALL LotusWordProImportFilter::getSupportedServiceNames( ) |
417 |
throw (RuntimeException) |
418 |
{ |
419 |
return LotusWordProImportFilter_getSupportedServiceNames(); |
420 |
} |