Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <string.h>
31 : : #include <sal/types.h>
32 : : #include <rtl/alloc.h>
33 : : #include <rtl/ustring.hxx>
34 : : #include <rtl/string.hxx>
35 : : #include <rtl/ustrbuf.hxx>
36 : : #include <rtl/strbuf.hxx>
37 : : #include <tools/date.hxx>
38 : : #include <tools/time.hxx>
39 : : #include <tools/datetime.hxx>
40 : :
41 : : #include <com/sun/star/uno/Reference.hxx>
42 : : #include <com/sun/star/uno/Sequence.hxx>
43 : : #include <com/sun/star/uno/Any.hxx>
44 : : #include <com/sun/star/xforms/XModel.hpp>
45 : : #include <com/sun/star/xml/dom/XNode.hpp>
46 : : #include <com/sun/star/xml/dom/XDocument.hpp>
47 : : #include <com/sun/star/lang/XUnoTunnel.hpp>
48 : :
49 : : #include "xpathlib.hxx"
50 : :
51 : : #include "extension.hxx"
52 : :
53 : : // C interface
54 : :
55 : : using namespace com::sun::star::uno;
56 : : using namespace com::sun::star::xml::dom;
57 : : using namespace com::sun::star::xforms;
58 : : using namespace com::sun::star::lang;
59 : :
60 : 0 : xmlXPathFunction xforms_lookupFunc(void *, const xmlChar *xname, const xmlChar *)
61 : : {
62 : :
63 : 0 : const char *name = (char *)xname;
64 [ # # ]: 0 : if (strcmp("boolean-from-string", name)==0)
65 : 0 : return xforms_booleanFromStringFunction;
66 [ # # ]: 0 : else if ((strcmp("if", name))==0)
67 : 0 : return xforms_ifFunction;
68 [ # # ]: 0 : else if ((strcmp("avg", name))==0)
69 : 0 : return xforms_avgFunction;
70 [ # # ]: 0 : else if ((strcmp("min", name))==0)
71 : 0 : return xforms_minFunction;
72 [ # # ]: 0 : else if ((strcmp("max", name))==0)
73 : 0 : return xforms_maxFunction;
74 [ # # ]: 0 : else if ((strcmp("count-non-empty", name))==0)
75 : 0 : return xforms_countNonEmptyFunction;
76 [ # # ]: 0 : else if ((strcmp("index", name))==0)
77 : 0 : return xforms_indexFunction;
78 [ # # ]: 0 : else if ((strcmp("property", name))==0)
79 : 0 : return xforms_propertyFunction;
80 [ # # ]: 0 : else if ((strcmp("now", name))==0)
81 : 0 : return xforms_nowFunction;
82 [ # # ]: 0 : else if ((strcmp("days-from-date", name))==0)
83 : 0 : return xforms_daysFromDateFunction;
84 [ # # ]: 0 : else if ((strcmp("seconds-from-dateTime", name))==0)
85 : 0 : return xforms_secondsFromDateTimeFunction;
86 [ # # ]: 0 : else if ((strcmp("seconds", name))==0)
87 : 0 : return xforms_secondsFuction;
88 [ # # ]: 0 : else if ((strcmp("months", name))==0)
89 : 0 : return xforms_monthsFuction;
90 [ # # ]: 0 : else if ((strcmp("instance", name))==0)
91 : 0 : return xforms_instanceFuction;
92 [ # # ]: 0 : else if ((strcmp("current", name))==0)
93 : 0 : return xforms_currentFunction;
94 : : else
95 : 0 : return NULL;
96 : : }
97 : :
98 : : // boolean functions
99 : 0 : void xforms_booleanFromStringFunction(xmlXPathParserContextPtr ctxt, int nargs)
100 : : {
101 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
102 [ # # ]: 0 : xmlChar *pString = xmlXPathPopString(ctxt);
103 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
104 [ # # ]: 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
105 [ # # # # ]: 0 : if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("true")) ||
[ # # ]
106 : 0 : aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("1")))
107 [ # # ][ # # ]: 0 : xmlXPathReturnTrue(ctxt);
108 [ # # # # ]: 0 : else if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("false")) ||
[ # # ]
109 : 0 : aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("0")))
110 [ # # ][ # # ]: 0 : xmlXPathReturnFalse(ctxt);
111 : : else
112 [ # # ][ # # ]: 0 : XP_ERROR(XPATH_NUMBER_ERROR);
113 : : }
114 : :
115 : 0 : void xforms_ifFunction(xmlXPathParserContextPtr ctxt, int nargs)
116 : : {
117 [ # # ]: 0 : if (nargs != 3) XP_ERROR(XPATH_INVALID_ARITY);
118 : 0 : xmlChar *s2 = xmlXPathPopString(ctxt);
119 : :
120 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
121 : 0 : xmlChar *s1 = xmlXPathPopString(ctxt);
122 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
123 : 0 : bool aBool = xmlXPathPopBoolean(ctxt);
124 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
125 : :
126 [ # # ]: 0 : if (aBool)
127 : 0 : xmlXPathReturnString(ctxt, s1);
128 : : else
129 : 0 : xmlXPathReturnString(ctxt, s2);
130 : :
131 : : }
132 : :
133 : : // Number Functions
134 : 0 : void xforms_avgFunction(xmlXPathParserContextPtr ctxt, int nargs)
135 : : {
136 : : // use sum(), div() and count()
137 [ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
138 : :
139 : : // save nodeset
140 : 0 : xmlXPathObjectPtr pObject = valuePop(ctxt);
141 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
142 : : //push back a copy
143 : 0 : valuePush(ctxt, xmlXPathObjectCopy(pObject));
144 : : // get the Sum
145 : 0 : xmlXPathSumFunction(ctxt, 1);
146 : 0 : double nSum = xmlXPathPopNumber(ctxt);
147 : : // push a copy once more
148 : 0 : valuePush(ctxt, xmlXPathObjectCopy(pObject));
149 : 0 : xmlXPathCountFunction(ctxt, 1);
150 : 0 : double nCount = xmlXPathPopNumber(ctxt);
151 : : // push args for div()
152 : 0 : xmlXPathReturnNumber(ctxt, nSum);
153 : 0 : xmlXPathReturnNumber(ctxt, nCount);
154 : 0 : xmlXPathDivValues(ctxt);
155 : : // the result is now on the ctxt stack
156 : 0 : xmlXPathFreeObject(pObject);
157 : : }
158 : :
159 : 0 : void xforms_minFunction(xmlXPathParserContextPtr ctxt, int nargs)
160 : : {
161 [ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
162 : 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
163 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
164 : 0 : double nMinimum = 0;
165 : 0 : double nNumber = 0;
166 [ # # ][ # # ]: 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
167 : : {
168 [ # # ][ # # ]: 0 : nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
[ # # ]
169 [ # # ]: 0 : if (xmlXPathIsNaN(nNumber))
170 : : {
171 : 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
172 : 0 : return;
173 : : }
174 [ # # ]: 0 : if (i == 0)
175 : 0 : nMinimum = nNumber;
176 [ # # ]: 0 : else if (nNumber < nMinimum)
177 : 0 : nMinimum = nNumber;
178 : : }
179 : 0 : xmlXPathReturnNumber(ctxt, nMinimum);
180 : : }
181 : :
182 : 0 : void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs)
183 : : {
184 [ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
185 : 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
186 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
187 : 0 : double nMaximum = 0;
188 : 0 : double nNumber = 0;
189 [ # # ][ # # ]: 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
190 : : {
191 [ # # ][ # # ]: 0 : nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
[ # # ]
192 [ # # ]: 0 : if (xmlXPathIsNaN(nNumber))
193 : : {
194 : 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
195 : 0 : return;
196 : : }
197 [ # # ]: 0 : if (i == 0)
198 : 0 : nMaximum = nNumber;
199 [ # # ]: 0 : else if (nNumber > nMaximum)
200 : 0 : nMaximum = nNumber;
201 : : }
202 : 0 : xmlXPathReturnNumber(ctxt, nMaximum);
203 : : }
204 : 0 : void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs)
205 : : {
206 [ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
207 : 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
208 [ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
209 : : xmlChar *aString;
210 : 0 : sal_Int32 nNotEmpty = 0;
211 [ # # ][ # # ]: 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
212 : : {
213 [ # # ][ # # ]: 0 : aString = xmlXPathCastNodeToString(xmlXPathNodeSetItem(pNodeSet, i));
[ # # ]
214 [ # # ]: 0 : if (*aString != 0) nNotEmpty++;
215 : : }
216 : 0 : xmlXPathReturnNumber(ctxt, nNotEmpty);
217 : : }
218 : 0 : void xforms_indexFunction(xmlXPathParserContextPtr /*ctxt*/, int /*nargs*/)
219 : : {
220 : : // function index takes a string argument that is the IDREF of a
221 : : // 'repeat' and returns the current 1-based position of the repeat
222 : : // index of the identified repeat -- see xforms/9.3.1
223 : :
224 : : // doc.getElementByID
225 : : // (...)
226 : 0 : }
227 : :
228 : : // String Functions
229 : : static const char* _version = "1.0";
230 : : static const char* _conformance = "conformance";
231 : 0 : void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs)
232 : : {
233 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
234 [ # # ]: 0 : xmlChar* pString = xmlXPathPopString(ctxt);
235 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
236 [ # # ]: 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
237 [ # # ]: 0 : if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("version")))
238 [ # # ][ # # ]: 0 : xmlXPathReturnString(ctxt, (xmlChar*)_version);
239 [ # # ]: 0 : else if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("conformance-level")))
240 [ # # ][ # # ]: 0 : xmlXPathReturnString(ctxt, (xmlChar*)_conformance);
241 : : else
242 [ # # ][ # # ]: 0 : xmlXPathReturnEmptyString(ctxt);
243 : : }
244 : :
245 : : // Date and Time Functions
246 : :
247 : 0 : static ::rtl::OString makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_True)
248 : : {
249 : 0 : ::rtl::OStringBuffer aDateTimeString;
250 [ # # ]: 0 : aDateTimeString.append((sal_Int32)aDateTime.GetYear());
251 [ # # ]: 0 : aDateTimeString.append("-");
252 [ # # ][ # # ]: 0 : if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
253 [ # # ]: 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
254 [ # # ]: 0 : aDateTimeString.append("-");
255 [ # # ][ # # ]: 0 : if (aDateTime.GetDay()<10) aDateTimeString.append("0");
256 [ # # ]: 0 : aDateTimeString.append((sal_Int32)aDateTime.GetDay());
257 [ # # ]: 0 : aDateTimeString.append("T");
258 [ # # ][ # # ]: 0 : if (aDateTime.GetHour()<10) aDateTimeString.append("0");
259 [ # # ]: 0 : aDateTimeString.append((sal_Int32)aDateTime.GetHour());
260 [ # # ]: 0 : aDateTimeString.append(":");
261 [ # # ][ # # ]: 0 : if (aDateTime.GetMin()<10) aDateTimeString.append("0");
262 [ # # ]: 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMin());
263 [ # # ]: 0 : aDateTimeString.append(":");
264 [ # # ][ # # ]: 0 : if (aDateTime.GetSec()<10) aDateTimeString.append("0");
265 [ # # ]: 0 : aDateTimeString.append((sal_Int32)aDateTime.GetSec());
266 [ # # ][ # # ]: 0 : if (bUTC) aDateTimeString.append("Z");
267 : :
268 : 0 : return aDateTimeString.makeStringAndClear();
269 : : }
270 : :
271 : : // returns current system date and time in canonical xsd:dateTime
272 : : // format
273 : 0 : void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int /*nargs*/)
274 : : {
275 : : /*
276 : : A single lexical representation, which is a subset of the lexical representations
277 : : allowed by [ISO 8601], is allowed for dateTime. This lexical representation is the
278 : : [ISO 8601] extended format CCYY-MM-DDThh:mm:ss where "CC" represents the century,
279 : : "YY" the year, "MM" the month and "DD" the day, preceded by an optional leading "-"
280 : : sign to indicate a negative number. If the sign is omitted, "+" is assumed. The letter
281 : : "T" is the date/time separator and "hh", "mm", "ss" represent hour, minute and second
282 : : respectively.
283 : : */
284 : :
285 : : /*
286 : : 3.2.7.2 Canonical representation
287 : : The canonical representation for dateTime is defined by prohibiting certain options
288 : : from the Lexical representation (par.3.2.7.1). Specifically, either the time zone must
289 : : be omitted or, if present, the time zone must be Coordinated Universal Time (UTC)
290 : : indicated by a "Z".
291 : : */
292 [ # # ]: 0 : DateTime aDateTime( DateTime::SYSTEM );
293 [ # # ]: 0 : ::rtl::OString aDateTimeString = makeDateTimeString(aDateTime);
294 [ # # ]: 0 : xmlChar *pString = static_cast<xmlChar*>(xmlMalloc(aDateTimeString.getLength()+1));
295 : 0 : strncpy((char*)pString, (char*)aDateTimeString.getStr(), aDateTimeString.getLength());
296 : 0 : pString[aDateTimeString.getLength()] = 0;
297 [ # # ][ # # ]: 0 : xmlXPathReturnString(ctxt, pString);
298 : 0 : }
299 : :
300 : 0 : static sal_Bool parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime)
301 : : {
302 : : // take apart a canonical literal xsd:dateTime string
303 : : //CCYY-MM-DDThh:mm:ss(Z)
304 : :
305 : 0 : ::rtl::OUString aDateTimeString = aString.trim();
306 : :
307 : : // check length
308 [ # # ][ # # ]: 0 : if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
[ # # ]
309 : 0 : return sal_False;
310 : :
311 : 0 : sal_Int32 nDateLength = 10;
312 : 0 : sal_Int32 nTimeLength = 8;
313 : :
314 [ # # ]: 0 : ::rtl::OUString aUTCString(RTL_CONSTASCII_USTRINGPARAM("Z"));
315 : :
316 : 0 : ::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength);
317 : 0 : ::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
318 : :
319 : 0 : sal_Int32 nIndex = 0;
320 : 0 : sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
321 : 0 : sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
322 : 0 : sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
323 : 0 : nIndex = 0;
324 : 0 : sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
325 : 0 : sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
326 : 0 : sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
327 : :
328 : 0 : Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
329 [ # # ]: 0 : Time tmpTime(nHour, nMinute, nSecond);
330 [ # # ]: 0 : DateTime tmpDateTime(tmpDate, tmpTime);
331 [ # # ]: 0 : if (aString.indexOf(aUTCString) < 0)
332 [ # # ]: 0 : tmpDateTime.ConvertToUTC();
333 : :
334 [ # # ]: 0 : aDateTime = tmpDateTime;
335 : :
336 : 0 : return sal_True;
337 : : }
338 : :
339 : :
340 : 0 : void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs)
341 : : {
342 : : // number of days from 1970-01-01 to supplied xsd:date(Time)
343 : :
344 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
345 [ # # ]: 0 : xmlChar* pString = xmlXPathPopString(ctxt);
346 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
347 [ # # ]: 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
348 : :
349 : 0 : DateTime aDateTime( DateTime::EMPTY );
350 [ # # ][ # # ]: 0 : if (parseDateTime(aString, aDateTime))
351 : : {
352 : 0 : Date aReferenceDate(1, 1, 1970);
353 [ # # ]: 0 : sal_Int32 nDays = aDateTime - aReferenceDate;
354 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, nDays);
355 : : }
356 : : else
357 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
358 : :
359 : :
360 : : }
361 : :
362 : :
363 : 0 : void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs)
364 : : {
365 : : // number of seconds from 1970-01-01T00:00:00Z to supplied xsd:date(Time)
366 : :
367 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
368 [ # # ]: 0 : xmlChar* pString = xmlXPathPopString(ctxt);
369 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
370 [ # # ]: 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
371 : :
372 : 0 : DateTime aDateTime( DateTime::EMPTY );
373 : :
374 [ # # ][ # # ]: 0 : if (parseDateTime(aString, aDateTime))
375 : : {
376 : 0 : Date aReferenceDate(1, 1, 1970);
377 [ # # ]: 0 : Time aReferenceTime(0, 0, 0);
378 [ # # ]: 0 : sal_Int32 nDays = aDateTime - aReferenceDate;
379 : 0 : sal_Int32 nSeconds = nDays * 24 * 60 * 60;
380 : 0 : nSeconds += aDateTime.GetHour() * 60 * 60;
381 : 0 : nSeconds += aDateTime.GetMin() * 60;
382 : 0 : nSeconds += aDateTime.GetSec();
383 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, nSeconds);
384 : : }
385 : : else
386 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
387 : :
388 : : }
389 : :
390 : 0 : static sal_Bool parseDuration(const xmlChar* aString, sal_Bool& bNegative, sal_Int32& nYears, sal_Int32& nMonth, sal_Int32& nDays,
391 : : sal_Int32& nHours, sal_Int32& nMinutes, sal_Int32& nSeconds)
392 : : {
393 : 0 : sal_Bool bTime = sal_False; // in part after T
394 : 0 : sal_Int32 nLength = strlen((char*)aString)+1;
395 : 0 : char *pString = (char*)rtl_allocateMemory(nLength);
396 : 0 : char *pString0 = pString;
397 : 0 : strncpy(pString, (char*)aString, nLength);
398 : :
399 [ # # ]: 0 : if (pString[0] == '-') {
400 : 0 : bNegative = sal_True;
401 : 0 : pString++;
402 : : }
403 : :
404 [ # # ]: 0 : if (pString[0] != 'P')
405 : 0 : return sal_False;
406 : 0 : pString++;
407 : 0 : char* pToken = pString;
408 [ # # ]: 0 : while(pToken[0] != 0)
409 : : {
410 [ # # # # : 0 : switch(pToken[0]) {
# # # ]
411 : : case 'Y':
412 : 0 : pToken[0] = 0;
413 : 0 : nYears = atoi(pString);
414 : 0 : pString = ++pToken;
415 : 0 : break;
416 : : case 'M':
417 : 0 : pToken[0] = 0;
418 [ # # ]: 0 : if (!bTime)
419 : 0 : nMonth = atoi(pString);
420 : : else
421 : 0 : nMinutes = atoi(pString);
422 : 0 : pString = ++pToken;
423 : 0 : break;
424 : : case 'D':
425 : 0 : pToken[0] = 0;
426 : 0 : nDays = atoi(pString);
427 : 0 : pString = ++pToken;
428 : 0 : break;
429 : : case 'H':
430 : 0 : pToken[0] = 0;
431 : 0 : nHours = atoi(pString);
432 : 0 : pString = ++pToken;
433 : 0 : break;
434 : : case 'S':
435 : 0 : pToken[0] = 0;
436 : 0 : nSeconds = atoi(pString);
437 : 0 : pString = ++pToken;
438 : 0 : break;
439 : : case 'T':
440 : 0 : bTime = sal_True;
441 : 0 : pString = ++pToken;
442 : 0 : break;
443 : : default:
444 : 0 : pToken++;
445 : : }
446 : : }
447 : 0 : rtl_freeMemory(pString0);
448 : 0 : return sal_True;
449 : : }
450 : :
451 : 0 : void xforms_secondsFuction(xmlXPathParserContextPtr ctxt, int nargs)
452 : : {
453 : : // convert a xsd:duration to seconds
454 : : // (-)PnYnMnDTnHnMnS
455 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
456 [ # # ]: 0 : xmlChar* pString = xmlXPathPopString(ctxt);
457 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
458 : :
459 : 0 : sal_Bool bNegative = sal_False;
460 : 0 : sal_Int32 nYears = 0;
461 : 0 : sal_Int32 nMonths = 0;
462 : 0 : sal_Int32 nDays = 0;
463 : 0 : sal_Int32 nHours = 0;
464 : 0 : sal_Int32 nMinutes = 0;
465 : 0 : sal_Int32 nSeconds = 0;
466 : :
467 [ # # ]: 0 : if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds))
468 : : {
469 : 0 : nSeconds += nMinutes*60;
470 : 0 : nSeconds += nHours*60*60;
471 : 0 : nSeconds += nDays*24*60*60;
472 : : // year and month are ignored according to spec
473 [ # # ]: 0 : if (bNegative)
474 : 0 : nSeconds = 0 - nSeconds;
475 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, nSeconds);
476 : : }
477 : : else
478 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
479 : : }
480 : :
481 : 0 : void xforms_monthsFuction(xmlXPathParserContextPtr ctxt, int nargs)
482 : : {
483 : : // convert a xsd:duration to seconds
484 : : // (-)PnYnMnDTnHnMnS
485 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
486 [ # # ]: 0 : xmlChar* pString = xmlXPathPopString(ctxt);
487 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
488 : :
489 : 0 : sal_Bool bNegative = sal_False;
490 : 0 : sal_Int32 nYears = 0;
491 : 0 : sal_Int32 nMonths = 0;
492 : 0 : sal_Int32 nDays = 0;
493 : 0 : sal_Int32 nHours = 0;
494 : 0 : sal_Int32 nMinutes = 0;
495 : 0 : sal_Int32 nSeconds = 0;
496 : :
497 [ # # ]: 0 : if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds))
498 : : {
499 : 0 : nMonths += nYears*12;
500 : : // Days, Houres, Minutes and seconds are ignored, see spec
501 [ # # ]: 0 : if (bNegative)
502 : 0 : nMonths = 0 - nMonths;
503 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, nMonths);
504 : : }
505 : : else
506 [ # # ][ # # ]: 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
507 : :
508 : : }
509 : :
510 : : // Node-set Functions
511 : 0 : void xforms_instanceFuction(xmlXPathParserContextPtr ctxt, int nargs)
512 : : {
513 [ # # ][ # # ]: 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
514 [ # # ]: 0 : xmlChar *pString = xmlXPathPopString(ctxt);
515 [ # # ][ # # ]: 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
516 [ # # ]: 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
517 : :
518 [ # # ]: 0 : Reference< XModel > aModel = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getModel();
519 [ # # ]: 0 : if (aModel.is())
520 : : {
521 [ # # ][ # # ]: 0 : Reference< XDocument > aInstance = aModel->getInstanceDocument(aString);
522 [ # # ]: 0 : if (aInstance.is())
523 : : {
524 : : try {
525 : : // xmlXPathObjectPtr xmlXPathNewNodeSet (xmlNodePtr val);
526 [ # # ]: 0 : Reference< XUnoTunnel > aTunnel(aInstance, UNO_QUERY_THROW);
527 [ # # ][ # # ]: 0 : xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) );
[ # # ][ # # ]
528 [ # # ]: 0 : xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode);
529 [ # # ][ # # ]: 0 : xmlXPathReturnNodeSet(ctxt, pObject->nodesetval);
530 [ # # # # ]: 0 : } catch (const RuntimeException&)
531 : : {
532 [ # # # # ]: 0 : xmlXPathReturnEmptyNodeSet(ctxt);
533 : : }
534 : : }
535 : : else
536 [ # # ][ # # ]: 0 : xmlXPathReturnEmptyNodeSet(ctxt);
537 : : }
538 : : else
539 [ # # ][ # # ]: 0 : xmlXPathReturnEmptyNodeSet(ctxt);
540 : :
541 : : }
542 : :
543 : : // Node-set Functions, XForms 1.1
544 : 0 : void xforms_currentFunction(xmlXPathParserContextPtr ctxt, int nargs)
545 : : {
546 [ # # ][ # # ]: 0 : if (nargs != 0) XP_ERROR(XPATH_INVALID_ARITY);
547 : :
548 [ # # ]: 0 : Reference< XNode > aNode = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getContextNode();
549 : :
550 [ # # ]: 0 : if (aNode.is())
551 : : {
552 : : try {
553 [ # # ]: 0 : Reference< XUnoTunnel > aTunnel(aNode, UNO_QUERY_THROW);
554 [ # # ][ # # ]: 0 : xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) );
[ # # ][ # # ]
555 [ # # ]: 0 : xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode);
556 [ # # ][ # # ]: 0 : xmlXPathReturnNodeSet(ctxt, pObject->nodesetval);
557 : : }
558 [ # # # # ]: 0 : catch (const RuntimeException&)
559 : : {
560 [ # # # # ]: 0 : xmlXPathReturnEmptyNodeSet(ctxt);
561 : : }
562 : : }
563 : : else
564 [ # # ][ # # ]: 0 : xmlXPathReturnEmptyNodeSet(ctxt);
565 : : }
566 : :
567 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|