1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "filterdetect.hxx"
25 #include <osl/diagnose.h>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/io/XActiveDataSource.hpp>
28 #include <com/sun/star/io/XOutputStream.hpp>
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
32 #include <com/sun/star/xml/sax/InputSource.hpp>
33 #include <com/sun/star/xml/sax/XParser.hpp>
34 #include <com/sun/star/xml/XImportFilter.hpp>
35 #include <com/sun/star/xml/XExportFilter.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/frame/XController.hpp>
38 #include <com/sun/star/task/XStatusIndicator.hpp>
39 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
40 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
41 #include <com/sun/star/style/XStyleLoader.hpp>
42 #include <com/sun/star/io/XInputStream.hpp>
43 #include <com/sun/star/document/XExtendedFilterDetection.hpp>
44 #include <com/sun/star/beans/PropertyState.hpp>
45 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47
48
49 using namespace rtl;
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::document;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::io;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::xml::sax;
56 using namespace com::sun::star::xml;
57 using namespace com::sun::star::task;
58 using namespace com::sun::star::frame;
59 using namespace com::sun::star::container;
60 using namespace com::sun::star::ucb;
61
62
detect(Sequence<PropertyValue> & aArguments)63 OUString SAL_CALL FilterDetect::detect(Sequence< PropertyValue >& aArguments )
64 throw( RuntimeException )
65 {
66 // type name to return
67 OUString sOriginalTypeName;
68 OUString sTypeName;
69 OUString sURL;
70 // stream of the document to be detected
71 Reference< XInputStream > xInStream;
72 for ( sal_Int32 i = 0 ; i < aArguments.getLength(); i++)
73 {
74 OUString aName = aArguments[i].Name;
75 if (aName.equalsAscii("TypeName" ) )
76 aArguments[i].Value >>= sOriginalTypeName;
77 if (aName.equalsAscii("URL" ) )
78 aArguments[i].Value >>= sURL;
79 if (aName.equalsAscii("InputStream" ) )
80 aArguments[i].Value >>= xInStream;
81 }
82
83 if (!xInStream.is())
84 {
85 // open the stream if it was not supplied by the framework
86 Reference< XSimpleFileAccess > xSFI(mxMSF->createInstance(
87 OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess" )), UNO_QUERY);
88 if (sURL.getLength() > 0 && xSFI.is())
89 {
90 try
91 {
92 xInStream = xSFI->openFileRead( sURL);
93 }
94 catch( Exception& )
95 {
96 return sTypeName;
97 }
98 } else {
99 // failed to access UCB
100 return sTypeName;
101 }
102 }
103
104 // flatxml starts with an office:document element. this element
105 // contains a class="..." attribute by which we can deduct the
106 // type of document that is to be loaded
107 //
108 // WARNING:
109 // parsing the plain text of the document is an easy way to do this
110 // but not the purest solution, since namespaces and other xml details
111 // may lead to another syntactic expression of the same document.
112 // this example works for the way the office serializes it's XML stream
113 // but might need extension for other data sources...
114 static OString aDocToken("office:document");
115 // static OString aClassToken("office:class=\"");
116 static OString aMimeTypeToken("office:mimetype=\"");
117
118 sal_Int32 nHeadSize = 4096;
119 Sequence< sal_Int8 > aHeadData(nHeadSize);
120
121 // rewind seekable stream
122 Reference< XSeekable > xSeek(xInStream, UNO_QUERY);
123 if (xSeek.is())
124 xSeek->seek(0);
125
126 long bytestRead = xInStream->readBytes(aHeadData, nHeadSize);
127
128 OString aHead = OString((const sal_Char *)aHeadData.getConstArray(), bytestRead).toAsciiLowerCase();
129
130 // check for document element of flatxml format
131 if (aHead.indexOf(aDocToken) >= 0)
132 {
133 // read document class
134 sal_Int32 n = aHead.indexOf(aMimeTypeToken);
135 if (n >= 0)
136 {
137 n += aMimeTypeToken.getLength();
138 OString aMimeType = aHead.copy(n, aHead.indexOf('\"', n) - n);
139 // return type for class found
140 if (aMimeType.equals("application/x-vnd.oasis.opendocument.text") ||
141 aMimeType.equals("application/vnd.oasis.opendocument.text"))
142 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_writer");
143 else if (aMimeType.equals("application/x-vnd.oasis.opendocument.text-master") ||
144 aMimeType.equals("application/vnd.oasis.opendocument.text-master"))
145 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_master");
146 else if (aMimeType.equals("application/x-vnd.oasis.openoffice.text-global") ||
147 aMimeType.equals("application/vnd.oasis.openoffice.text-global"))
148 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_master");
149 else if (aMimeType.equals("application/x-vnd.oasis.opendocument.spreadsheet") ||
150 aMimeType.equals("application/vnd.oasis.opendocument.spreadsheet"))
151 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_calc");
152 else if (aMimeType.equals("application/x-vnd.oasis.opendocument.drawing") ||
153 aMimeType.equals("application/vnd.oasis.opendocument.drawing"))
154 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_draw");
155 else if (aMimeType.equals("application/x-vnd.oasis.opendocument.presentation") ||
156 aMimeType.equals("application/vnd.oasis.opendocument.presentation"))
157 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_impress");
158 else if (aMimeType.equals("application/x-vnd.oasis.opendocument.presentation") ||
159 aMimeType.equals("application/vnd.oasis.opendocument.presentation"))
160 sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_impress");
161 }
162 }
163 return sTypeName;
164 }
165
166
167 // XInitialization
initialize(const Sequence<Any> & aArguments)168 void SAL_CALL FilterDetect::initialize( const Sequence< Any >& aArguments )
169 throw (Exception, RuntimeException)
170 {
171 Sequence < PropertyValue > aAnySeq;
172 sal_Int32 nLength = aArguments.getLength();
173 if ( nLength && ( aArguments[0] >>= aAnySeq ) )
174 {
175 const PropertyValue * pValue = aAnySeq.getConstArray();
176 nLength = aAnySeq.getLength();
177 for ( sal_Int32 i = 0 ; i < nLength; i++)
178 {
179 if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) )
180 {
181 pValue[i].Value >>= msFilterName;
182 }
183 else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "UserData" ) ) )
184 {
185 pValue[i].Value >>= msUserData;
186 }
187 else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TemplateName" ) ) )
188 {
189 pValue[i].Value>>=msTemplateName;
190 }
191 }
192 }
193 }
194
FilterDetect_getImplementationName()195 OUString FilterDetect_getImplementationName ()
196 throw (RuntimeException)
197 {
198 return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "devguide.officedev.samples.filter.FlatXmlDetect" ) );
199 }
200
201 #define SERVICE_NAME1 "com.sun.star.document.ExtendedTypeDetection"
202
FilterDetect_supportsService(const OUString & ServiceName)203 sal_Bool SAL_CALL FilterDetect_supportsService( const OUString& ServiceName )
204 throw (RuntimeException)
205 {
206 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) );
207 }
208
FilterDetect_getSupportedServiceNames()209 Sequence< OUString > SAL_CALL FilterDetect_getSupportedServiceNames( )
210 throw (RuntimeException)
211 {
212 Sequence < OUString > aRet(2);
213 OUString* pArray = aRet.getArray();
214 pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) );
215 return aRet;
216 }
217 #undef SERVICE_NAME1
218 #undef SERVICE_NAME2
219
FilterDetect_createInstance(const Reference<XMultiServiceFactory> & rSMgr)220 Reference< XInterface > SAL_CALL FilterDetect_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
221 throw( Exception )
222 {
223 return (cppu::OWeakObject*) new FilterDetect( rSMgr );
224 }
225
226 // XServiceInfo
getImplementationName()227 OUString SAL_CALL FilterDetect::getImplementationName( )
228 throw (RuntimeException)
229 {
230 return FilterDetect_getImplementationName();
231 }
232
supportsService(const OUString & rServiceName)233 sal_Bool SAL_CALL FilterDetect::supportsService( const OUString& rServiceName )
234 throw (RuntimeException)
235 {
236 return FilterDetect_supportsService( rServiceName );
237 }
238
getSupportedServiceNames()239 Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames( )
240 throw (RuntimeException)
241 {
242 return FilterDetect_getSupportedServiceNames();
243 }
244