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 "ScannerTestService.hxx"
25 #include <stdio.h>
26 #include <string.h>
27 #include <wchar.h>
28 #include <rtftok/RTFScanner.hxx>
29 #include <rtftok/RTFScannerHandler.hxx>
30 #include <com/sun/star/io/XStream.hpp>
31 #include <com/sun/star/io/XInputStream.hpp>
32 #include <com/sun/star/io/XSeekable.hpp>
33 #include <com/sun/star/io/XTruncate.hpp>
34 #include <com/sun/star/task/XStatusIndicator.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <ucbhelper/contentbroker.hxx>
37 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
38 #include <osl/process.h>
39 #include <rtl/string.hxx>
40 #include <hash_set>
41 #include <assert.h>
42 #include <cppuhelper/implbase2.hxx>
43 #include <com/sun/star/embed/XTransactedObject.hpp>
44 #include <com/sun/star/embed/XStorage.hpp>
45 #include <com/sun/star/util/XCloseable.hpp>
46 #include <comphelper/storagehelper.hxx>
47 #include <com/sun/star/embed/XTransactedObject.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <comphelper/seqstream.hxx>
51 
52 #include <ctype.h>
53 
54 using namespace ::com::sun::star;
55 
56 namespace writerfilter { namespace rtftok {
57 
58 const sal_Char ScannerTestService::SERVICE_NAME[40] = "debugservices.rtftok.ScannerTestService";
59 const sal_Char ScannerTestService::IMPLEMENTATION_NAME[40] = "debugservices.rtftok.ScannerTestService";
60 
61 struct ScannerTestServiceHelper
62 {
operator ()writerfilter::rtftok::ScannerTestServiceHelper63 	size_t operator()(const rtl::OString &str) const
64 	{
65 		return str.hashCode();
66 	}
operator ()writerfilter::rtftok::ScannerTestServiceHelper67 	bool operator()(const rtl::OString &str1, const rtl::OString &str2) const
68 	{
69 		return str1.compareTo(str2)==0;
70 	}
71 };
72 
73 typedef ::std::hash_set< ::rtl::OString, ScannerTestServiceHelper, ScannerTestServiceHelper > ScannerTestServiceTokenMap;
74 
75 class MyRtfScannerHandler : public writerfilter::rtftok::RTFScannerHandler
76 {
77 	ScannerTestServiceTokenMap destMap;
78 	ScannerTestServiceTokenMap ctrlMap;
79 	std::vector<unsigned char> binBuffer;
80 	int objDataLevel;
81 	int numOfOLEs;
82 	unsigned char hb;
83 	int numOfOLEChars;
84 	uno::Reference<lang::XMultiServiceFactory> xServiceFactory;
85 	uno::Reference<com::sun::star::ucb::XSimpleFileAccess> xFileAccess;
86 	uno::Reference<embed::XStorage> xStorage;
87 
dest(char * token,char *)88 	void dest(char* token, char* /*value*/)
89 	{
90 		destMap.insert(rtl::OString(token));
91 //		printf("{\\*\\%s%s ", token, value);
92 		if (strcmp(token, "objdata")==0)
93 		{
94 			binBuffer.clear();
95 			objDataLevel=1;
96 			numOfOLEChars=0;
97 		}
98 	}
ctrl(char * token,char *)99 	void ctrl(char*token, char* /*value*/)
100 	{
101 		ctrlMap.insert(rtl::OString(token));
102 //		printf("\\%s%s ", token, value);
103 	}
lbrace(void)104 	void lbrace(void)
105 	{
106 //		printf("{");
107 	}
rbrace(void)108 	void rbrace(void)
109 	{
110 #ifndef LINUX
111         unsigned char * binBufferStr = ((unsigned char*)&(*binBuffer.begin()));
112 
113 		if (objDataLevel)
114 		{
115 			int o=0;
116 			unsigned int type=((unsigned int)binBuffer[o]) | ((unsigned int)binBuffer[o+1])<<8 | ((unsigned int)binBuffer[o+2])<<16 | ((unsigned int)binBuffer[o+3]<<24); o+=4;
117 			unsigned int recType=((unsigned int)binBuffer[o]) | ((unsigned int)binBuffer[o+1])<<8 | ((unsigned int)binBuffer[o+2])<<16 | ((unsigned int)binBuffer[o+3]<<24); o+=4;
118 			unsigned int strLen=((unsigned int)binBuffer[o]) | ((unsigned int)binBuffer[o+1])<<8 | ((unsigned int)binBuffer[o+2])<<16 | ((unsigned int)binBuffer[o+3]<<24); o+=4;
119 			unsigned char *str=binBufferStr+o;
120 			o+=strLen;
121 			o+=4; // dummy1
122 			o+=4; // dummy2
123 			unsigned int binLen=((unsigned int)binBuffer[o]) | ((unsigned int)binBuffer[o+1])<<8 | ((unsigned int)binBuffer[o+2])<<16 | ((unsigned int)binBuffer[o+3]<<24); o+=4;
124 			printf("OLE%i \"%s\" type=%i recType=%i binBuffer.size()=%u len=%u\n", numOfOLEs, str, type, recType, (unsigned int)(binBuffer.size()), o+binLen);
125 			//assert(binBuffer.size()==o+binLen);
126 			char buf[100];
127 			sprintf(buf, "ole%02i.ole", numOfOLEs);
128 /*			if 0{
129 			FILE *f=fopen(buf, "w+b");
130 			unsigned char *data=binBuffer.begin();
131 			fwrite(data+o, 1, binLen, f);
132 			fclose(f);
133 			}*/
134 /*
135 			rtl_uString *dir=NULL;
136 			osl_getProcessWorkingDir(&dir);
137 			rtl::OUString absFileUrl;
138 			rtl::OUString fileUrl=rtl::OUString::createFromAscii(buf);
139 			osl_getAbsoluteFileURL(dir, fileUrl.pData, &absFileUrl.pData);
140 			rtl_uString_release(dir);
141 */
142 				comphelper::ByteSequence seq(binLen);
143                 unsigned char *data0=binBufferStr;
144                 memcpy(seq.getArray(), data0+o, binLen);
145 				uno::Reference<io::XInputStream> myStream=new comphelper::SequenceInputStream(seq);
146 //			uno::Reference<io::XStream> myStream=xFileAccess->openFileReadWrite(absFileUrl);
147 //			uno::Reference<io::XStream> myStream(new MyStreamImpl(binBuffer, o));
148             uno::Sequence< uno::Any > aArgs0( 1 );
149             aArgs0[0] <<= myStream;
150 			uno::Reference< container::XNameContainer > xNameContainer(
151             xServiceFactory->createInstanceWithArguments(
152                     ::rtl::OUString::createFromAscii("com.sun.star.embed.OLESimpleStorage" ),
153                     aArgs0 ),
154             uno::UNO_QUERY_THROW );
155 			try {
156 				printf("TRY\n");
157 		::com::sun::star::uno::Sequence< ::rtl::OUString > names=xNameContainer->getElementNames();
158 				printf("OK\n");
159 
160 			for(int i=0;i<names.getLength();i++)
161 			{
162 				rtl::OUString &name=names[i];
163 				wprintf(L"name=%s\n", name.getStr());
164 			}
165 			{
166 				uno::Reference< io::XStream > xContentStream = xStorage->openStreamElement(
167 					rtl::OUString::createFromAscii(buf), embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
168 				uno::Reference<beans::XPropertySet> xContentStreamPropSet(xContentStream, uno::UNO_QUERY_THROW);
169 				xContentStreamPropSet->setPropertyValue(rtl::OUString::createFromAscii("MediaType"), uno::makeAny(rtl::OUString::createFromAscii("application/vnd.sun.star.oleobject")));
170 				uno::Reference<io::XOutputStream> myOutStream=xContentStream->getOutputStream();
171 				uno::Sequence< ::sal_Int8 > seq1(binLen);
172                 unsigned char *data1=binBufferStr;
173                 memcpy(seq1.getArray(), data1+o, binLen);
174 				myOutStream->writeBytes(seq1);
175 				myOutStream->closeOutput();
176 			}
177 
178 			} catch(com::sun::star::uno::RuntimeException &)
179 			{
180 				printf("NOT OK\n");
181 				comphelper::ByteSequence seq2(4+binLen);
182 				//				memcpy(seq2.getArray(), &binLen, 4); assert(0); //TODO linux
183 				seq2[0]= sal::static_int_cast<sal_Int8>(binLen&0xFF);
184 				seq2[1]= sal::static_int_cast<sal_Int8>((binLen>>8)&0xFF);
185 				seq2[2]= sal::static_int_cast<sal_Int8>((binLen>>16)&0xFF);
186 				seq2[3]= sal::static_int_cast<sal_Int8>((binLen>>24)&0xFF);
187                 unsigned char *data2=binBufferStr;
188                 memcpy(seq2.getArray()+4, data2+o, binLen);
189 				uno::Reference<io::XInputStream> myInStream=new comphelper::SequenceInputStream(seq2);
190 				printf("SEQ OK\n");
191 
192 				uno::Reference< io::XStream > xContentStream = xStorage->openStreamElement(
193 					rtl::OUString::createFromAscii(buf), embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
194 				uno::Reference<beans::XPropertySet> xContentStreamPropSet(xContentStream, uno::UNO_QUERY_THROW);
195 				xContentStreamPropSet->setPropertyValue(rtl::OUString::createFromAscii("MediaType"), uno::makeAny(rtl::OUString::createFromAscii("application/vnd.sun.star.oleobject")));
196 				printf("CONTENT STREAM OK\n");
197 
198                 uno::Sequence< uno::Any > aArgs1( 1 );
199                 aArgs1[0] <<= xContentStream;
200 				uno::Reference< container::XNameContainer > xNameContainer2(
201 					xServiceFactory->createInstanceWithArguments(
202                     ::rtl::OUString::createFromAscii("com.sun.star.embed.OLESimpleStorage" ),
203                     aArgs1 ),
204 		            uno::UNO_QUERY_THROW );
205 				printf("OLE STORAGE OK\n");
206 
207 				uno::Any anyStream;
208 				anyStream <<= myInStream;
209 				xNameContainer2->insertByName(rtl::OUString::createFromAscii("\1Ole10Native"), anyStream);
210 				printf("INSERT OK\n");
211 
212 				uno::Reference<embed::XTransactedObject> xTransact(xNameContainer2, uno::UNO_QUERY);
213 				xTransact->commit();
214 			}
215 			objDataLevel--;
216 			numOfOLEs++;
217 		}
218 #endif
219 //		printf("}");
220 	}
addSpaces(int)221 	void addSpaces(int /*count*/)
222 	{
223 //		for(int i=0;i<count;i++)
224 //			printf(" ");
225 
226 	}
addBinData(unsigned char)227 	void addBinData(unsigned char /*data*/)
228 	{
229 //		printf("%02Xh", data);
230 	}
addChar(char ch)231 	void addChar(char ch)
232 	{
233 //		printf("%c", ch);
234 		if (objDataLevel)
235 		{
236 			if (numOfOLEChars%2==0)
237 			{
238 				char c=sal::static_int_cast<char>(toupper(ch));
239 				assert((c<='F' && c>='A') || (c<='9' && c>='0'));
240 				if(c>='A') hb=(unsigned char)(c-'A'+10); else hb=(unsigned char)(c-'0');
241 			}
242 			else
243 			{
244 				unsigned char lb;
245 				char c=sal::static_int_cast<char>(toupper(ch));
246 				assert((c<='F' && c>='A') || (c<='9' && c>='0'));
247 				if(c>='A') lb=(unsigned char)(c-'A'+10); else lb=(unsigned char)(c-'0');
248 				unsigned char r=(hb<<4)|lb;
249 				binBuffer.push_back(r);
250 			}
251 			numOfOLEChars++;
252 		}
253 	}
addCharU(sal_Unicode)254 	void addCharU(sal_Unicode /*ch*/)
255 	{
256 //		printf("\\u%i ", ch);
257 	}
addHexChar(char *)258 	void addHexChar(char* /*hexch*/)
259 	{
260 //		printf("\'%s ", hexch);
261 	}
262 
263 
264 public:
MyRtfScannerHandler(uno::Reference<lang::XMultiServiceFactory> & xServiceFactory_,uno::Reference<com::sun::star::ucb::XSimpleFileAccess> & xFileAccess_,uno::Reference<embed::XStorage> & xStorage_)265 	MyRtfScannerHandler(uno::Reference<lang::XMultiServiceFactory> &xServiceFactory_, uno::Reference<com::sun::star::ucb::XSimpleFileAccess> &xFileAccess_, uno::Reference<embed::XStorage> &xStorage_) :
266             objDataLevel(0), numOfOLEs(0), hb(' '), numOfOLEChars(0),
267     xServiceFactory(xServiceFactory_),
268     xFileAccess(xFileAccess_),
269     xStorage(xStorage_)
270 	{
271 	}
272 
~MyRtfScannerHandler()273     virtual ~MyRtfScannerHandler() {}
274 
dump()275 	void dump()
276 	{
277 		printf("Destinations:\n");
278 		for(ScannerTestServiceTokenMap::iterator i=destMap.begin();i!=destMap.end();i++)
279 		{
280 			printf("  %s\n", i->getStr());
281 		}
282 		printf("Ctrls:\n");
283 		for(ScannerTestServiceTokenMap::iterator i=ctrlMap.begin();i!=ctrlMap.end();i++)
284 		{
285 			printf("  %s\n", i->getStr());
286 		}
287 	}
288 };
289 
290 class RtfInputSourceImpl : public rtftok::RTFInputSource
291 {
292 private:
293 	uno::Reference< io::XInputStream > xInputStream;
294 	uno::Reference< io::XSeekable > xSeekable;
295 	uno::Reference< task::XStatusIndicator > xStatusIndicator;
296 	sal_Int64 bytesTotal;
297 	sal_Int64 bytesRead;
298 public:
RtfInputSourceImpl(uno::Reference<io::XInputStream> & xInputStream_,uno::Reference<task::XStatusIndicator> & xStatusIndicator_)299 	RtfInputSourceImpl(uno::Reference< io::XInputStream > &xInputStream_, uno::Reference< task::XStatusIndicator > &xStatusIndicator_) :
300 	  xInputStream(xInputStream_),
301 	  xStatusIndicator(xStatusIndicator_),
302 	  bytesRead(0)
303 	{
304 		xSeekable=uno::Reference< io::XSeekable >(xInputStream, uno::UNO_QUERY);
305 		if (xSeekable.is())
306 			bytesTotal=xSeekable->getLength();
307 		if (xStatusIndicator.is() && xSeekable.is())
308 		{
309 			xStatusIndicator->start(::rtl::OUString::createFromAscii("Converting"), 100);
310 		}
311 	}
312 
~RtfInputSourceImpl()313     virtual ~RtfInputSourceImpl() {}
314 
read(void * buf,int maxlen)315 	int read(void *buf, int maxlen)
316 	{
317 		uno::Sequence< sal_Int8 > buffer;
318 		int len=xInputStream->readSomeBytes(buffer,maxlen);
319 		if (len>0)
320 		{
321 			sal_Int8 *_buffer=buffer.getArray();
322 			memcpy(buf, _buffer, len);
323 			bytesRead+=len;
324 			if (xStatusIndicator.is())
325 			{
326 				if (xSeekable.is())
327 				{
328 					xStatusIndicator->setValue((int)(bytesRead*100/bytesTotal));
329 				}
330 				else
331 				{
332 					char buf1[100];
333 					sprintf(buf1, "Converted %" SAL_PRIdINT64 " KB", bytesRead/1024);
334 					xStatusIndicator->start(::rtl::OUString::createFromAscii(buf1), 0);
335 				}
336 			}
337 			return len;
338 		}
339 		else
340 		{
341 			if (xStatusIndicator.is())
342 			{
343 				xStatusIndicator->end();
344 			}
345 			return 0;
346 		}
347 	}
348 };
349 
ScannerTestService(const uno::Reference<uno::XComponentContext> & xContext_)350 ScannerTestService::ScannerTestService(const uno::Reference< uno::XComponentContext > &xContext_) :
351 xContext( xContext_ )
352 {
353 }
354 
run(const uno::Sequence<rtl::OUString> & aArguments)355 sal_Int32 SAL_CALL ScannerTestService::run( const uno::Sequence< rtl::OUString >& aArguments ) throw (uno::RuntimeException)
356 {
357 
358   printf("TEST\n");
359 
360 	uno::Sequence<uno::Any> aUcbInitSequence(2);
361 	aUcbInitSequence[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Local"));
362 	aUcbInitSequence[1] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office"));
363 	uno::Reference<lang::XMultiServiceFactory> xServiceFactory(xContext->getServiceManager(), uno::UNO_QUERY_THROW);
364   printf("A\n");
365 	uno::Reference<lang::XMultiComponentFactory> xFactory(xContext->getServiceManager(), uno::UNO_QUERY_THROW );
366   printf("B\n");
367     if (::ucbhelper::ContentBroker::initialize(xServiceFactory, aUcbInitSequence))
368 	{
369   printf("C\n");
370 			rtl::OUString arg=aArguments[0];
371 
372 			uno::Reference<com::sun::star::ucb::XSimpleFileAccess> xFileAccess(
373 			xFactory->createInstanceWithContext(
374 				::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess")),
375 				xContext), uno::UNO_QUERY_THROW );
376 
377 			rtl_uString *dir=NULL;
378 			osl_getProcessWorkingDir(&dir);
379 			rtl::OUString absFileUrl;
380 			osl_getAbsoluteFileURL(dir, arg.pData, &absFileUrl.pData);
381 			rtl_uString_release(dir);
382 
383 			uno::Reference <lang::XSingleServiceFactory> xStorageFactory(
384 				xServiceFactory->createInstance (rtl::OUString::createFromAscii("com.sun.star.embed.StorageFactory")), uno::UNO_QUERY_THROW);
385 
386 			rtl::OUString outFileUrl;
387 			{
388 			rtl_uString *dir1=NULL;
389 			osl_getProcessWorkingDir(&dir1);
390 			osl_getAbsoluteFileURL(dir1, aArguments[1].pData, &outFileUrl.pData);
391 			rtl_uString_release(dir1);
392 			}
393 
394             uno::Sequence< uno::Any > aArgs2( 2 );
395             aArgs2[0] <<= outFileUrl;
396             aArgs2[1] <<= embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE;
397             uno::Reference<embed::XStorage> xStorage(xStorageFactory->createInstanceWithArguments(aArgs2), uno::UNO_QUERY_THROW);
398 			uno::Reference<beans::XPropertySet> xPropSet(xStorage, uno::UNO_QUERY_THROW);
399 			xPropSet->setPropertyValue(rtl::OUString::createFromAscii("MediaType"), uno::makeAny(rtl::OUString::createFromAscii("application/vnd.oasis.opendocument.text")));
400 			uno::Reference<io::XInputStream> xInputStream = xFileAccess->openFileRead(absFileUrl);
401 			uno::Reference< task::XStatusIndicator > xStatusIndicator;
402 
403 		TimeValue t1; osl_getSystemTime(&t1);
404 
405 			RtfInputSourceImpl rtfInputSource(xInputStream, xStatusIndicator);
406 			MyRtfScannerHandler eventHandler(xServiceFactory, xFileAccess, xStorage);
407 			writerfilter::rtftok::RTFScanner *rtfScanner=writerfilter::rtftok::RTFScanner::createRTFScanner(rtfInputSource, eventHandler);
408 
409 			rtfScanner->yylex();
410 			delete rtfScanner;
411 
412 		TimeValue t2; osl_getSystemTime(&t2);
413 		printf("time=%" SAL_PRIuUINT32 "s\n", t2.Seconds-t1.Seconds);
414 
415 //			eventHandler.dump();
416 			uno::Reference<embed::XTransactedObject> xTransact(xStorage, uno::UNO_QUERY);
417 			xTransact->commit();
418 
419 
420         ::ucbhelper::ContentBroker::deinitialize();
421 	}
422 	else
423 	{
424 		fprintf(stderr, "can't initialize UCB");
425 	}
426 	return 0;
427 }
428 
ScannerTestService_getImplementationName()429 ::rtl::OUString ScannerTestService_getImplementationName ()
430 {
431 	return rtl::OUString::createFromAscii ( ScannerTestService::IMPLEMENTATION_NAME );
432 }
433 
ScannerTestService_supportsService(const::rtl::OUString & ServiceName)434 sal_Bool SAL_CALL ScannerTestService_supportsService( const ::rtl::OUString& ServiceName )
435 {
436 	return ServiceName.equals( rtl::OUString::createFromAscii( ScannerTestService::SERVICE_NAME ) );
437 }
ScannerTestService_getSupportedServiceNames()438 uno::Sequence< rtl::OUString > SAL_CALL ScannerTestService_getSupportedServiceNames(  ) throw (uno::RuntimeException)
439 {
440 	uno::Sequence < rtl::OUString > aRet(1);
441 	rtl::OUString* pArray = aRet.getArray();
442 	pArray[0] =  rtl::OUString::createFromAscii ( ScannerTestService::SERVICE_NAME );
443 	return aRet;
444 }
445 
ScannerTestService_createInstance(const uno::Reference<uno::XComponentContext> & xContext)446 uno::Reference< uno::XInterface > SAL_CALL ScannerTestService_createInstance( const uno::Reference< uno::XComponentContext > & xContext) throw( uno::Exception )
447 {
448 	return (cppu::OWeakObject*) new ScannerTestService( xContext );
449 }
450 
451 } } /* end namespace writerfilter::rtftok */
452