Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "interpre.hxx"
11 : #include <rtl/strbuf.hxx>
12 : #include <formula/errorcodes.hxx>
13 : #include <svtools/miscopt.hxx>
14 :
15 : #include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
16 : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
17 : #include <com/sun/star/io/XInputStream.hpp>
18 :
19 : #include "libxml/xpath.h"
20 : #include <datastreamgettime.hxx>
21 : #include <dpobject.hxx>
22 : #include <document.hxx>
23 :
24 : #include <boost/shared_ptr.hpp>
25 : #include <cstring>
26 :
27 : using namespace com::sun::star;
28 :
29 : // TODO: Add new methods for ScInterpreter here.
30 :
31 0 : void ScInterpreter::ScFilterXML()
32 : {
33 0 : sal_uInt8 nParamCount = GetByte();
34 0 : if (MustHaveParamCount( nParamCount, 2 ) )
35 : {
36 0 : OUString aXPathExpression = GetString().getString();
37 0 : OUString aString = GetString().getString();
38 0 : if(aString.isEmpty() || aXPathExpression.isEmpty())
39 : {
40 0 : PushError( errNoValue );
41 0 : return;
42 : }
43 :
44 0 : OString aOXPathExpression = OUStringToOString( aXPathExpression, RTL_TEXTENCODING_UTF8 );
45 0 : const char* pXPathExpr = aOXPathExpression.getStr();
46 0 : OString aOString = OUStringToOString( aString, RTL_TEXTENCODING_UTF8 );
47 0 : const char* pXML = aOString.getStr();
48 :
49 : boost::shared_ptr<xmlParserCtxt> pContext(
50 0 : xmlNewParserCtxt(), xmlFreeParserCtxt );
51 :
52 : boost::shared_ptr<xmlDoc> pDoc( xmlParseMemory( pXML, aOString.getLength() ),
53 0 : xmlFreeDoc );
54 :
55 0 : if(!pDoc)
56 : {
57 0 : PushError( errNoValue );
58 0 : return;
59 : }
60 :
61 : boost::shared_ptr<xmlXPathContext> pXPathCtx( xmlXPathNewContext(pDoc.get()),
62 0 : xmlXPathFreeContext );
63 :
64 : boost::shared_ptr<xmlXPathObject> pXPathObj( xmlXPathEvalExpression(BAD_CAST(pXPathExpr), pXPathCtx.get()),
65 0 : xmlXPathFreeObject );
66 :
67 0 : if(!pXPathObj)
68 : {
69 0 : PushError( errNoValue );
70 0 : return;
71 : }
72 :
73 0 : rtl::OUString aResult;
74 :
75 0 : switch(pXPathObj->type)
76 : {
77 : case XPATH_UNDEFINED:
78 0 : break;
79 : case XPATH_NODESET:
80 : {
81 0 : xmlNodeSetPtr pNodeSet = pXPathObj->nodesetval;
82 0 : if(!pNodeSet)
83 : {
84 0 : PushError( errNoValue );
85 0 : return;
86 : }
87 :
88 0 : size_t nSize = pNodeSet->nodeNr;
89 0 : if( nSize >= 1 )
90 : {
91 0 : if(pNodeSet->nodeTab[0]->type == XML_NAMESPACE_DECL)
92 : {
93 0 : xmlNsPtr ns = reinterpret_cast<xmlNsPtr>(pNodeSet->nodeTab[0]);
94 0 : xmlNodePtr cur = reinterpret_cast<xmlNodePtr>(ns->next);
95 0 : boost::shared_ptr<xmlChar> pChar2(xmlNodeGetContent(cur), xmlFree);
96 0 : aResult = OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), RTL_TEXTENCODING_UTF8);
97 : }
98 : else
99 : {
100 0 : xmlNodePtr cur = pNodeSet->nodeTab[0];
101 0 : boost::shared_ptr<xmlChar> pChar2(xmlNodeGetContent(cur), xmlFree);
102 0 : aResult = OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), RTL_TEXTENCODING_UTF8);
103 : }
104 : }
105 : else
106 : {
107 0 : PushError( errNoValue );
108 0 : return;
109 : }
110 : }
111 0 : PushString(aResult);
112 0 : break;
113 : case XPATH_BOOLEAN:
114 : {
115 0 : bool bVal = pXPathObj->boolval != 0;
116 0 : PushDouble(double(bVal));
117 : }
118 0 : break;
119 : case XPATH_NUMBER:
120 : {
121 0 : double fVal = pXPathObj->floatval;
122 0 : PushDouble(fVal);
123 : }
124 0 : break;
125 : case XPATH_STRING:
126 0 : PushString(OUString::createFromAscii(reinterpret_cast<char*>(pXPathObj->stringval)));
127 0 : break;
128 : case XPATH_POINT:
129 0 : PushNoValue();
130 0 : break;
131 : case XPATH_RANGE:
132 0 : PushNoValue();
133 0 : break;
134 : case XPATH_LOCATIONSET:
135 0 : PushNoValue();
136 0 : break;
137 : case XPATH_USERS:
138 0 : PushNoValue();
139 0 : break;
140 : case XPATH_XSLT_TREE:
141 0 : PushNoValue();
142 0 : break;
143 :
144 0 : }
145 : }
146 : }
147 :
148 0 : void ScInterpreter::ScWebservice()
149 : {
150 0 : sal_uInt8 nParamCount = GetByte();
151 0 : if (MustHaveParamCount( nParamCount, 1 ) )
152 : {
153 0 : OUString aURI = GetString().getString();
154 :
155 0 : if(aURI.isEmpty())
156 : {
157 0 : PushError( errNoValue );
158 0 : return;
159 : }
160 :
161 0 : uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY );
162 0 : if(!xFileAccess.is())
163 : {
164 0 : PushError( errNoValue );
165 0 : return;
166 : }
167 :
168 0 : uno::Reference< io::XInputStream > xStream;
169 : try {
170 0 : xStream = xFileAccess->openFileRead( aURI );
171 : }
172 0 : catch (...)
173 : {
174 : // don't let any exceptions pass
175 0 : PushError( errNoValue );
176 0 : return;
177 : }
178 0 : if ( !xStream.is() )
179 : {
180 0 : PushError( errNoValue );
181 0 : return;
182 : }
183 :
184 0 : const sal_Int32 BUF_LEN = 8000;
185 0 : uno::Sequence< sal_Int8 > buffer( BUF_LEN );
186 0 : OStringBuffer aBuffer( 64000 );
187 :
188 0 : sal_Int32 nRead = 0;
189 0 : while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN )
190 : {
191 0 : aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
192 : }
193 :
194 0 : if ( nRead > 0 )
195 : {
196 0 : aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
197 : }
198 :
199 0 : xStream->closeInput();
200 :
201 0 : OUString aContent = OStringToOUString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
202 0 : PushString( aContent );
203 : }
204 : }
205 :
206 : /**
207 : Returns a string in which all non-alphanumeric characters except stroke and
208 : underscore (-_) have been replaced with a percent (%) sign
209 : followed by hex digits.
210 : It is encoded the same way that the posted data from a WWW form is encoded,
211 : that is the same way as in application/x-www-form-urlencoded media type and
212 : as pwer RFC 3986.
213 :
214 : @see fdo#76870
215 : */
216 0 : void ScInterpreter::ScEncodeURL()
217 : {
218 0 : sal_uInt8 nParamCount = GetByte();
219 0 : if ( MustHaveParamCount( nParamCount, 1 ) )
220 : {
221 0 : OUString aStr = GetString().getString();
222 0 : if ( aStr.isEmpty() )
223 : {
224 0 : PushError( errNoValue );
225 0 : return;
226 : }
227 :
228 0 : OString aUtf8Str( aStr.toUtf8());
229 0 : const sal_Int32 nLen = aUtf8Str.getLength();
230 0 : OStringBuffer aUrlBuf( nLen );;
231 0 : for ( int i = 0; i < nLen; i++ )
232 : {
233 0 : sal_Char c = aUtf8Str[ i ];
234 0 : if ( rtl::isAsciiAlphanumeric( static_cast<sal_uChar>( c ) ) || c == '-' || c == '_' )
235 0 : aUrlBuf.append( c );
236 : else
237 : {
238 0 : aUrlBuf.append( '%' );
239 0 : aUrlBuf.append( OString::number( static_cast<sal_uChar>( c ), 16 ).toAsciiUpperCase() );
240 : }
241 : }
242 0 : PushString( OUString::fromUtf8( aUrlBuf.makeStringAndClear() ) );
243 : }
244 : }
245 :
246 0 : void ScInterpreter::ScDebugVar()
247 : {
248 : // This is to be used by developers only! Never document this for end
249 : // users. This is a convenient way to extract arbitrary internal state to
250 : // a cell for easier debugging.
251 :
252 0 : SvtMiscOptions aMiscOptions;
253 0 : if (!aMiscOptions.IsExperimentalMode())
254 : {
255 0 : PushError(ScErrorCodes::errNoName);
256 0 : return;
257 : }
258 :
259 0 : if (!MustHaveParamCount(GetByte(), 1))
260 : {
261 0 : PushIllegalParameter();
262 0 : return;
263 : }
264 :
265 0 : rtl_uString* p = GetString().getDataIgnoreCase();
266 0 : if (!p)
267 : {
268 0 : PushIllegalParameter();
269 0 : return;
270 : }
271 :
272 0 : OUString aStrUpper(p);
273 :
274 0 : if (aStrUpper == "PIVOTCOUNT")
275 : {
276 : // Set the number of pivot tables in the document.
277 :
278 0 : double fVal = 0.0;
279 0 : if (pDok->HasPivotTable())
280 : {
281 0 : const ScDPCollection* pDPs = pDok->GetDPCollection();
282 0 : fVal = pDPs->GetCount();
283 : }
284 0 : PushDouble(fVal);
285 : }
286 0 : else if (aStrUpper == "DATASTREAM_IMPORT")
287 0 : PushDouble( sc::datastream_get_time( 0 ) );
288 0 : else if (aStrUpper == "DATASTREAM_RECALC")
289 0 : PushDouble( sc::datastream_get_time( 1 ) );
290 0 : else if (aStrUpper == "DATASTREAM_RENDER")
291 0 : PushDouble( sc::datastream_get_time( 2 ) );
292 : else
293 0 : PushIllegalParameter();
294 : }
295 :
296 3 : void ScInterpreter::ScErf()
297 : {
298 3 : sal_uInt8 nParamCount = GetByte();
299 3 : if (MustHaveParamCount( nParamCount, 1 ) )
300 : {
301 3 : double x = GetDouble();
302 3 : PushDouble( ::rtl::math::erf( x ) );
303 : }
304 3 : }
305 :
306 3 : void ScInterpreter::ScErfc()
307 : {
308 3 : sal_uInt8 nParamCount = GetByte();
309 3 : if (MustHaveParamCount( nParamCount, 1 ) )
310 : {
311 3 : double x = GetDouble();
312 3 : PushDouble( ::rtl::math::erfc( x ) );
313 : }
314 3 : }
315 :
316 0 : void ScInterpreter::ScColor()
317 : {
318 0 : sal_uInt8 nParamCount = GetByte();
319 0 : if(MustHaveParamCount(nParamCount, 3, 4))
320 : {
321 0 : double nAlpha = 0;
322 0 : if(nParamCount == 4)
323 0 : nAlpha = rtl::math::approxFloor(GetDouble());
324 :
325 0 : if(nAlpha < 0 || nAlpha > 255)
326 : {
327 0 : PushIllegalArgument();
328 0 : return;
329 : }
330 :
331 0 : double nBlue = rtl::math::approxFloor(GetDouble());
332 :
333 0 : if(nBlue < 0 || nBlue > 255)
334 : {
335 0 : PushIllegalArgument();
336 0 : return;
337 : }
338 :
339 0 : double nGreen = rtl::math::approxFloor(GetDouble());
340 :
341 0 : if(nGreen < 0 || nGreen > 255)
342 : {
343 0 : PushIllegalArgument();
344 0 : return;
345 : }
346 :
347 0 : double nRed = rtl::math::approxFloor(GetDouble());
348 :
349 0 : if(nRed < 0 || nRed > 255)
350 : {
351 0 : PushIllegalArgument();
352 0 : return;
353 : }
354 :
355 0 : double nVal = 256*256*256*nAlpha + 256*256*nRed + 256*nGreen + nBlue;
356 0 : PushDouble(nVal);
357 : }
358 156 : }
359 :
360 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|