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 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 suplied 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 // conatains a clas="..." attribut 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 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 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 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 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 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 227 OUString SAL_CALL FilterDetect::getImplementationName( ) 228 throw (RuntimeException) 229 { 230 return FilterDetect_getImplementationName(); 231 } 232 233 sal_Bool SAL_CALL FilterDetect::supportsService( const OUString& rServiceName ) 234 throw (RuntimeException) 235 { 236 return FilterDetect_supportsService( rServiceName ); 237 } 238 239 Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames( ) 240 throw (RuntimeException) 241 { 242 return FilterDetect_getSupportedServiceNames(); 243 } 244