1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir *
3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir *
5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir *
7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir *
9*cdf0e10cSrcweir * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir *
11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir *
15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir *
21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir *
26*cdf0e10cSrcweir ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "precompiled_configmgr.hxx"
29*cdf0e10cSrcweir #include "sal/config.h"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "boost/noncopyable.hpp"
32*cdf0e10cSrcweir #include "com/sun/star/uno/Any.hxx"
33*cdf0e10cSrcweir #include "com/sun/star/uno/Reference.hxx"
34*cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp"
35*cdf0e10cSrcweir #include "com/sun/star/uno/Sequence.hxx"
36*cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp"
37*cdf0e10cSrcweir #include "osl/diagnose.h"
38*cdf0e10cSrcweir #include "osl/file.h"
39*cdf0e10cSrcweir #include "osl/file.hxx"
40*cdf0e10cSrcweir #include "rtl/string.h"
41*cdf0e10cSrcweir #include "rtl/string.hxx"
42*cdf0e10cSrcweir #include "rtl/textcvt.h"
43*cdf0e10cSrcweir #include "rtl/textenc.h"
44*cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
45*cdf0e10cSrcweir #include "rtl/ustring.h"
46*cdf0e10cSrcweir #include "rtl/ustring.hxx"
47*cdf0e10cSrcweir #include "sal/types.h"
48*cdf0e10cSrcweir #include "xmlreader/span.hxx"
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir #include "data.hxx"
51*cdf0e10cSrcweir #include "groupnode.hxx"
52*cdf0e10cSrcweir #include "localizedpropertynode.hxx"
53*cdf0e10cSrcweir #include "localizedvaluenode.hxx"
54*cdf0e10cSrcweir #include "modifications.hxx"
55*cdf0e10cSrcweir #include "node.hxx"
56*cdf0e10cSrcweir #include "nodemap.hxx"
57*cdf0e10cSrcweir #include "propertynode.hxx"
58*cdf0e10cSrcweir #include "type.hxx"
59*cdf0e10cSrcweir #include "writemodfile.hxx"
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir namespace configmgr {
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir class Components;
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir namespace {
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir namespace css = com::sun::star;
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir rtl::OString convertToUtf8(
70*cdf0e10cSrcweir     rtl::OUString const & text, sal_Int32 offset, sal_Int32 length)
71*cdf0e10cSrcweir {
72*cdf0e10cSrcweir     OSL_ASSERT(
73*cdf0e10cSrcweir         offset <= text.getLength() && text.getLength() - offset >= length);
74*cdf0e10cSrcweir     rtl::OString s;
75*cdf0e10cSrcweir     if (!rtl_convertUStringToString(
76*cdf0e10cSrcweir             &s.pData, text.pData->buffer + offset, length,
77*cdf0e10cSrcweir             RTL_TEXTENCODING_UTF8,
78*cdf0e10cSrcweir             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
79*cdf0e10cSrcweir              RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
80*cdf0e10cSrcweir     {
81*cdf0e10cSrcweir         throw css::uno::RuntimeException(
82*cdf0e10cSrcweir             rtl::OUString(
83*cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("cannot convert to UTF-8")),
84*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
85*cdf0e10cSrcweir     }
86*cdf0e10cSrcweir     return s;
87*cdf0e10cSrcweir }
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir struct TempFile: public boost::noncopyable {
90*cdf0e10cSrcweir     rtl::OUString url;
91*cdf0e10cSrcweir     oslFileHandle handle;
92*cdf0e10cSrcweir     bool closed;
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir     TempFile(): handle(0), closed(false) {}
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir     ~TempFile();
97*cdf0e10cSrcweir };
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir TempFile::~TempFile() {
100*cdf0e10cSrcweir     if (handle != 0) {
101*cdf0e10cSrcweir         if (!closed) {
102*cdf0e10cSrcweir             oslFileError e = osl_closeFile(handle);
103*cdf0e10cSrcweir             if (e != osl_File_E_None) {
104*cdf0e10cSrcweir                 OSL_TRACE(
105*cdf0e10cSrcweir                     "osl_closeFile failed with %ld", static_cast< long >(e));
106*cdf0e10cSrcweir             }
107*cdf0e10cSrcweir         }
108*cdf0e10cSrcweir         osl::FileBase::RC e = osl::File::remove(url);
109*cdf0e10cSrcweir         if (e != osl::FileBase::E_None) {
110*cdf0e10cSrcweir             OSL_TRACE("osl_removeFile failed with %ld", static_cast< long >(e));
111*cdf0e10cSrcweir         }
112*cdf0e10cSrcweir     }
113*cdf0e10cSrcweir }
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir void writeData(oslFileHandle handle, char const * begin, sal_Int32 length) {
116*cdf0e10cSrcweir     OSL_ASSERT(length >= 0);
117*cdf0e10cSrcweir     sal_uInt64 n;
118*cdf0e10cSrcweir     if ((osl_writeFile(handle, begin, static_cast< sal_uInt32 >(length), &n) !=
119*cdf0e10cSrcweir          osl_File_E_None) ||
120*cdf0e10cSrcweir         n != static_cast< sal_uInt32 >(length))
121*cdf0e10cSrcweir     {
122*cdf0e10cSrcweir         throw css::uno::RuntimeException(
123*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("write failure")),
124*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
125*cdf0e10cSrcweir     }
126*cdf0e10cSrcweir }
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir void writeData(oslFileHandle handle, rtl::OString const & text) {
129*cdf0e10cSrcweir     writeData(handle, text.getStr(), text.getLength());
130*cdf0e10cSrcweir }
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir void writeAttributeValue(oslFileHandle handle, rtl::OUString const & value) {
133*cdf0e10cSrcweir     sal_Int32 i = 0;
134*cdf0e10cSrcweir     sal_Int32 j = i;
135*cdf0e10cSrcweir     for (; j < value.getLength(); ++j) {
136*cdf0e10cSrcweir         OSL_ASSERT(
137*cdf0e10cSrcweir             value[j] == 0x0009 || value[j] == 0x000A || value[j] == 0x000D ||
138*cdf0e10cSrcweir             (value[j] >= 0x0020 && value[j] != 0xFFFE && value[j] != 0xFFFF));
139*cdf0e10cSrcweir         switch(value[j]) {
140*cdf0e10cSrcweir         case '\x09':
141*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
142*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#9;"));
143*cdf0e10cSrcweir             i = j + 1;
144*cdf0e10cSrcweir             break;
145*cdf0e10cSrcweir         case '\x0A':
146*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
147*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#xA;"));
148*cdf0e10cSrcweir             i = j + 1;
149*cdf0e10cSrcweir             break;
150*cdf0e10cSrcweir         case '\x0D':
151*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
152*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#xD;"));
153*cdf0e10cSrcweir             i = j + 1;
154*cdf0e10cSrcweir             break;
155*cdf0e10cSrcweir         case '"':
156*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
157*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&quot;"));
158*cdf0e10cSrcweir             i = j + 1;
159*cdf0e10cSrcweir             break;
160*cdf0e10cSrcweir         case '&':
161*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
162*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&amp;"));
163*cdf0e10cSrcweir             i = j + 1;
164*cdf0e10cSrcweir             break;
165*cdf0e10cSrcweir         case '<':
166*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
167*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&lt;"));
168*cdf0e10cSrcweir             i = j + 1;
169*cdf0e10cSrcweir             break;
170*cdf0e10cSrcweir         default:
171*cdf0e10cSrcweir             break;
172*cdf0e10cSrcweir         }
173*cdf0e10cSrcweir     }
174*cdf0e10cSrcweir     writeData(handle, convertToUtf8(value, i, j - i));
175*cdf0e10cSrcweir }
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Bool value) {
178*cdf0e10cSrcweir     if (value) {
179*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("true"));
180*cdf0e10cSrcweir     } else {
181*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("false"));
182*cdf0e10cSrcweir     }
183*cdf0e10cSrcweir }
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Int16 value) {
186*cdf0e10cSrcweir     writeData(handle, rtl::OString::valueOf(static_cast< sal_Int32 >(value)));
187*cdf0e10cSrcweir }
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Int32 value) {
190*cdf0e10cSrcweir     writeData(handle, rtl::OString::valueOf(value));
191*cdf0e10cSrcweir }
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Int64 value) {
194*cdf0e10cSrcweir     writeData(handle, rtl::OString::valueOf(value));
195*cdf0e10cSrcweir }
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, double value) {
198*cdf0e10cSrcweir     writeData(handle, rtl::OString::valueOf(value));
199*cdf0e10cSrcweir }
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, rtl::OUString const & value) {
202*cdf0e10cSrcweir     sal_Int32 i = 0;
203*cdf0e10cSrcweir     sal_Int32 j = i;
204*cdf0e10cSrcweir     for (; j < value.getLength(); ++j) {
205*cdf0e10cSrcweir         sal_Unicode c = value[j];
206*cdf0e10cSrcweir         if ((c < 0x0020 && c != 0x0009 && c != 0x000A && c != 0x000D) ||
207*cdf0e10cSrcweir             c == 0xFFFE || c == 0xFFFF)
208*cdf0e10cSrcweir         {
209*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
210*cdf0e10cSrcweir             writeData(
211*cdf0e10cSrcweir                 handle, RTL_CONSTASCII_STRINGPARAM("<unicode oor:scalar=\""));
212*cdf0e10cSrcweir             writeData(
213*cdf0e10cSrcweir                 handle, rtl::OString::valueOf(static_cast< sal_Int32 >(c)));
214*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("\"/>"));
215*cdf0e10cSrcweir             i = j + 1;
216*cdf0e10cSrcweir         } else if (c == '\x0D') {
217*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
218*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#xD;"));
219*cdf0e10cSrcweir             i = j + 1;
220*cdf0e10cSrcweir         } else if (c == '&') {
221*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
222*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&amp;"));
223*cdf0e10cSrcweir             i = j + 1;
224*cdf0e10cSrcweir         } else if (c == '<') {
225*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
226*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&lt;"));
227*cdf0e10cSrcweir             i = j + 1;
228*cdf0e10cSrcweir         } else if (c == '>') {
229*cdf0e10cSrcweir             // "MUST, for compatibility, be escaped [...] when it appears in the
230*cdf0e10cSrcweir             // string ']]>'":
231*cdf0e10cSrcweir             writeData(handle, convertToUtf8(value, i, j - i));
232*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("&gt;"));
233*cdf0e10cSrcweir             i = j + 1;
234*cdf0e10cSrcweir         }
235*cdf0e10cSrcweir     }
236*cdf0e10cSrcweir     writeData(handle, convertToUtf8(value, i, j - i));
237*cdf0e10cSrcweir }
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir void writeValueContent(
240*cdf0e10cSrcweir     oslFileHandle handle, css::uno::Sequence< sal_Int8 > const & value)
241*cdf0e10cSrcweir {
242*cdf0e10cSrcweir     for (sal_Int32 i = 0; i < value.getLength(); ++i) {
243*cdf0e10cSrcweir         static char const hexDigit[16] = {
244*cdf0e10cSrcweir             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
245*cdf0e10cSrcweir             'D', 'E', 'F' };
246*cdf0e10cSrcweir         writeData(handle, hexDigit + ((value[i] >> 4) & 0xF), 1);
247*cdf0e10cSrcweir         writeData(handle, hexDigit + (value[i] & 0xF), 1);
248*cdf0e10cSrcweir     }
249*cdf0e10cSrcweir }
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir template< typename T > void writeSingleValue(
252*cdf0e10cSrcweir     oslFileHandle handle, css::uno::Any const & value)
253*cdf0e10cSrcweir {
254*cdf0e10cSrcweir     writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
255*cdf0e10cSrcweir     T val = T();
256*cdf0e10cSrcweir     value >>= val;
257*cdf0e10cSrcweir     writeValueContent(handle, val);
258*cdf0e10cSrcweir     writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
259*cdf0e10cSrcweir }
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir template< typename T > void writeListValue(
262*cdf0e10cSrcweir     oslFileHandle handle, css::uno::Any const & value)
263*cdf0e10cSrcweir {
264*cdf0e10cSrcweir     writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
265*cdf0e10cSrcweir     css::uno::Sequence< T > val;
266*cdf0e10cSrcweir     value >>= val;
267*cdf0e10cSrcweir     for (sal_Int32 i = 0; i < val.getLength(); ++i) {
268*cdf0e10cSrcweir         if (i != 0) {
269*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM(" "));
270*cdf0e10cSrcweir         }
271*cdf0e10cSrcweir         writeValueContent(handle, val[i]);
272*cdf0e10cSrcweir     }
273*cdf0e10cSrcweir     writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
274*cdf0e10cSrcweir }
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir template< typename T > void writeItemListValue(
277*cdf0e10cSrcweir     oslFileHandle handle, css::uno::Any const & value)
278*cdf0e10cSrcweir {
279*cdf0e10cSrcweir     writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
280*cdf0e10cSrcweir     css::uno::Sequence< T > val;
281*cdf0e10cSrcweir     value >>= val;
282*cdf0e10cSrcweir     for (sal_Int32 i = 0; i < val.getLength(); ++i) {
283*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("<it>"));
284*cdf0e10cSrcweir         writeValueContent(handle, val[i]);
285*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("</it>"));
286*cdf0e10cSrcweir     }
287*cdf0e10cSrcweir     writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
288*cdf0e10cSrcweir }
289*cdf0e10cSrcweir 
290*cdf0e10cSrcweir void writeValue(oslFileHandle handle, Type type, css::uno::Any const & value) {
291*cdf0e10cSrcweir     switch (type) {
292*cdf0e10cSrcweir     case TYPE_BOOLEAN:
293*cdf0e10cSrcweir         writeSingleValue< sal_Bool >(handle, value);
294*cdf0e10cSrcweir         break;
295*cdf0e10cSrcweir     case TYPE_SHORT:
296*cdf0e10cSrcweir         writeSingleValue< sal_Int16 >(handle, value);
297*cdf0e10cSrcweir         break;
298*cdf0e10cSrcweir     case TYPE_INT:
299*cdf0e10cSrcweir         writeSingleValue< sal_Int32 >(handle, value);
300*cdf0e10cSrcweir         break;
301*cdf0e10cSrcweir     case TYPE_LONG:
302*cdf0e10cSrcweir         writeSingleValue< sal_Int64 >(handle, value);
303*cdf0e10cSrcweir         break;
304*cdf0e10cSrcweir     case TYPE_DOUBLE:
305*cdf0e10cSrcweir         writeSingleValue< double >(handle, value);
306*cdf0e10cSrcweir         break;
307*cdf0e10cSrcweir     case TYPE_STRING:
308*cdf0e10cSrcweir         writeSingleValue< rtl::OUString >(handle, value);
309*cdf0e10cSrcweir         break;
310*cdf0e10cSrcweir     case TYPE_HEXBINARY:
311*cdf0e10cSrcweir         writeSingleValue< css::uno::Sequence< sal_Int8 > >(handle, value);
312*cdf0e10cSrcweir         break;
313*cdf0e10cSrcweir     case TYPE_BOOLEAN_LIST:
314*cdf0e10cSrcweir         writeListValue< sal_Bool >(handle, value);
315*cdf0e10cSrcweir         break;
316*cdf0e10cSrcweir     case TYPE_SHORT_LIST:
317*cdf0e10cSrcweir         writeListValue< sal_Int16 >(handle, value);
318*cdf0e10cSrcweir         break;
319*cdf0e10cSrcweir     case TYPE_INT_LIST:
320*cdf0e10cSrcweir         writeListValue< sal_Int32 >(handle, value);
321*cdf0e10cSrcweir         break;
322*cdf0e10cSrcweir     case TYPE_LONG_LIST:
323*cdf0e10cSrcweir         writeListValue< sal_Int64 >(handle, value);
324*cdf0e10cSrcweir         break;
325*cdf0e10cSrcweir     case TYPE_DOUBLE_LIST:
326*cdf0e10cSrcweir         writeListValue< double >(handle, value);
327*cdf0e10cSrcweir         break;
328*cdf0e10cSrcweir     case TYPE_STRING_LIST:
329*cdf0e10cSrcweir         writeItemListValue< rtl::OUString >(handle, value);
330*cdf0e10cSrcweir         break;
331*cdf0e10cSrcweir     case TYPE_HEXBINARY_LIST:
332*cdf0e10cSrcweir         writeItemListValue< css::uno::Sequence< sal_Int8 > >(handle, value);
333*cdf0e10cSrcweir         break;
334*cdf0e10cSrcweir     default: // TYPE_ERROR, TYPE_NIL, TYPE_ANY
335*cdf0e10cSrcweir         OSL_ASSERT(false); // this cannot happen
336*cdf0e10cSrcweir     }
337*cdf0e10cSrcweir }
338*cdf0e10cSrcweir 
339*cdf0e10cSrcweir void writeNode(
340*cdf0e10cSrcweir     Components & components, oslFileHandle handle,
341*cdf0e10cSrcweir     rtl::Reference< Node > const & parent, rtl::OUString const & name,
342*cdf0e10cSrcweir     rtl::Reference< Node > const & node)
343*cdf0e10cSrcweir {
344*cdf0e10cSrcweir     static xmlreader::Span const typeNames[] = {
345*cdf0e10cSrcweir         xmlreader::Span(), xmlreader::Span(), xmlreader::Span(),
346*cdf0e10cSrcweir             // TYPE_ERROR, TYPE_NIL, TYPE_ANY
347*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:boolean")),
348*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:short")),
349*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:int")),
350*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:long")),
351*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:double")),
352*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:string")),
353*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:hexBinary")),
354*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:boolean-list")),
355*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:short-list")),
356*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:int-list")),
357*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:long-list")),
358*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:double-list")),
359*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:string-list")),
360*cdf0e10cSrcweir         xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:hexBinary-list")) };
361*cdf0e10cSrcweir     switch (node->kind()) {
362*cdf0e10cSrcweir     case Node::KIND_PROPERTY:
363*cdf0e10cSrcweir         {
364*cdf0e10cSrcweir             PropertyNode * prop = dynamic_cast< PropertyNode * >(node.get());
365*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
366*cdf0e10cSrcweir             writeAttributeValue(handle, name);
367*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\""));
368*cdf0e10cSrcweir             Type type = prop->getStaticType();
369*cdf0e10cSrcweir             Type dynType = getDynamicType(prop->getValue(components));
370*cdf0e10cSrcweir             OSL_ASSERT(dynType != TYPE_ERROR);
371*cdf0e10cSrcweir             if (type == TYPE_ANY) {
372*cdf0e10cSrcweir                 type = dynType;
373*cdf0e10cSrcweir                 if (type != TYPE_NIL) {
374*cdf0e10cSrcweir                     writeData(
375*cdf0e10cSrcweir                         handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
376*cdf0e10cSrcweir                     writeData(
377*cdf0e10cSrcweir                         handle, typeNames[type].begin, typeNames[type].length);
378*cdf0e10cSrcweir                     writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
379*cdf0e10cSrcweir                 }
380*cdf0e10cSrcweir             }
381*cdf0e10cSrcweir             writeData(handle, "><value");
382*cdf0e10cSrcweir             if (dynType == TYPE_NIL) {
383*cdf0e10cSrcweir                 writeData(
384*cdf0e10cSrcweir                     handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
385*cdf0e10cSrcweir             } else {
386*cdf0e10cSrcweir                 writeValue(handle, type, prop->getValue(components));
387*cdf0e10cSrcweir             }
388*cdf0e10cSrcweir             writeData(handle, "</prop>");
389*cdf0e10cSrcweir         }
390*cdf0e10cSrcweir         break;
391*cdf0e10cSrcweir     case Node::KIND_LOCALIZED_PROPERTY:
392*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
393*cdf0e10cSrcweir         writeAttributeValue(handle, name);
394*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\">"));
395*cdf0e10cSrcweir         for (NodeMap::iterator i(node->getMembers().begin());
396*cdf0e10cSrcweir              i != node->getMembers().end(); ++i)
397*cdf0e10cSrcweir         {
398*cdf0e10cSrcweir             writeNode(components, handle, node, i->first, i->second);
399*cdf0e10cSrcweir         }
400*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("</prop>"));
401*cdf0e10cSrcweir         break;
402*cdf0e10cSrcweir     case Node::KIND_LOCALIZED_VALUE:
403*cdf0e10cSrcweir         {
404*cdf0e10cSrcweir             writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
405*cdf0e10cSrcweir             if (name.getLength() != 0) {
406*cdf0e10cSrcweir                 writeData(handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
407*cdf0e10cSrcweir                 writeAttributeValue(handle, name);
408*cdf0e10cSrcweir                 writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
409*cdf0e10cSrcweir             }
410*cdf0e10cSrcweir             Type type = dynamic_cast< LocalizedPropertyNode * >(parent.get())->
411*cdf0e10cSrcweir                 getStaticType();
412*cdf0e10cSrcweir             css::uno::Any value(
413*cdf0e10cSrcweir                 dynamic_cast< LocalizedValueNode * >(node.get())->getValue());
414*cdf0e10cSrcweir             Type dynType = getDynamicType(value);
415*cdf0e10cSrcweir             OSL_ASSERT(dynType != TYPE_ERROR);
416*cdf0e10cSrcweir             if (type == TYPE_ANY) {
417*cdf0e10cSrcweir                 type = dynType;
418*cdf0e10cSrcweir                 if (type != TYPE_NIL) {
419*cdf0e10cSrcweir                     writeData(
420*cdf0e10cSrcweir                         handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
421*cdf0e10cSrcweir                     writeData(
422*cdf0e10cSrcweir                         handle, typeNames[type].begin, typeNames[type].length);
423*cdf0e10cSrcweir                     writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
424*cdf0e10cSrcweir                 }
425*cdf0e10cSrcweir             }
426*cdf0e10cSrcweir             if (dynType == TYPE_NIL) {
427*cdf0e10cSrcweir                 writeData(
428*cdf0e10cSrcweir                     handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
429*cdf0e10cSrcweir             } else {
430*cdf0e10cSrcweir                 writeValue(handle, type, value);
431*cdf0e10cSrcweir             }
432*cdf0e10cSrcweir         }
433*cdf0e10cSrcweir         break;
434*cdf0e10cSrcweir     case Node::KIND_GROUP:
435*cdf0e10cSrcweir     case Node::KIND_SET:
436*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
437*cdf0e10cSrcweir         writeAttributeValue(handle, name);
438*cdf0e10cSrcweir         if (node->getTemplateName().getLength() != 0) { // set member
439*cdf0e10cSrcweir             writeData(
440*cdf0e10cSrcweir                 handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"replace"));
441*cdf0e10cSrcweir         }
442*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
443*cdf0e10cSrcweir         for (NodeMap::iterator i(node->getMembers().begin());
444*cdf0e10cSrcweir              i != node->getMembers().end(); ++i)
445*cdf0e10cSrcweir         {
446*cdf0e10cSrcweir             writeNode(components, handle, node, i->first, i->second);
447*cdf0e10cSrcweir         }
448*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("</node>"));
449*cdf0e10cSrcweir         break;
450*cdf0e10cSrcweir     }
451*cdf0e10cSrcweir }
452*cdf0e10cSrcweir 
453*cdf0e10cSrcweir void writeModifications(
454*cdf0e10cSrcweir     Components & components, oslFileHandle handle,
455*cdf0e10cSrcweir     rtl::OUString const & parentPathRepresentation,
456*cdf0e10cSrcweir     rtl::Reference< Node > const & parent, rtl::OUString const & nodeName,
457*cdf0e10cSrcweir     rtl::Reference< Node > const & node,
458*cdf0e10cSrcweir     Modifications::Node const & modifications)
459*cdf0e10cSrcweir {
460*cdf0e10cSrcweir     // It is never necessary to write oor:finalized or oor:mandatory attributes,
461*cdf0e10cSrcweir     // as they cannot be set via the UNO API.
462*cdf0e10cSrcweir     if (modifications.children.empty()) {
463*cdf0e10cSrcweir         OSL_ASSERT(parent.is());
464*cdf0e10cSrcweir             // components themselves have no parent but must have children
465*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\""));
466*cdf0e10cSrcweir         writeAttributeValue(handle, parentPathRepresentation);
467*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
468*cdf0e10cSrcweir         if (node.is()) {
469*cdf0e10cSrcweir             writeNode(components, handle, parent, nodeName, node);
470*cdf0e10cSrcweir         } else {
471*cdf0e10cSrcweir             switch (parent->kind()) {
472*cdf0e10cSrcweir             case Node::KIND_LOCALIZED_PROPERTY:
473*cdf0e10cSrcweir                 writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
474*cdf0e10cSrcweir                 if (nodeName.getLength() != 0) {
475*cdf0e10cSrcweir                     writeData(
476*cdf0e10cSrcweir                         handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
477*cdf0e10cSrcweir                     writeAttributeValue(handle, nodeName);
478*cdf0e10cSrcweir                     writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
479*cdf0e10cSrcweir                 }
480*cdf0e10cSrcweir                 writeData(
481*cdf0e10cSrcweir                     handle, RTL_CONSTASCII_STRINGPARAM(" oor:op=\"remove\"/>"));
482*cdf0e10cSrcweir                 break;
483*cdf0e10cSrcweir             case Node::KIND_GROUP:
484*cdf0e10cSrcweir                 OSL_ASSERT(
485*cdf0e10cSrcweir                     dynamic_cast< GroupNode * >(parent.get())->isExtensible());
486*cdf0e10cSrcweir                 writeData(
487*cdf0e10cSrcweir                     handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
488*cdf0e10cSrcweir                 writeAttributeValue(handle, nodeName);
489*cdf0e10cSrcweir                 writeData(
490*cdf0e10cSrcweir                     handle,
491*cdf0e10cSrcweir                     RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
492*cdf0e10cSrcweir                 break;
493*cdf0e10cSrcweir             case Node::KIND_SET:
494*cdf0e10cSrcweir                 writeData(
495*cdf0e10cSrcweir                     handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
496*cdf0e10cSrcweir                 writeAttributeValue(handle, nodeName);
497*cdf0e10cSrcweir                 writeData(
498*cdf0e10cSrcweir                     handle,
499*cdf0e10cSrcweir                     RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
500*cdf0e10cSrcweir                 break;
501*cdf0e10cSrcweir             default:
502*cdf0e10cSrcweir                 OSL_ASSERT(false); // this cannot happen
503*cdf0e10cSrcweir                 break;
504*cdf0e10cSrcweir             }
505*cdf0e10cSrcweir         }
506*cdf0e10cSrcweir         writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>"));
507*cdf0e10cSrcweir     } else {
508*cdf0e10cSrcweir         OSL_ASSERT(node.is());
509*cdf0e10cSrcweir         rtl::OUString pathRep(
510*cdf0e10cSrcweir             parentPathRepresentation +
511*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
512*cdf0e10cSrcweir             Data::createSegment(node->getTemplateName(), nodeName));
513*cdf0e10cSrcweir         for (Modifications::Node::Children::const_iterator i(
514*cdf0e10cSrcweir                  modifications.children.begin());
515*cdf0e10cSrcweir              i != modifications.children.end(); ++i)
516*cdf0e10cSrcweir         {
517*cdf0e10cSrcweir             writeModifications(
518*cdf0e10cSrcweir                 components, handle, pathRep, node, i->first,
519*cdf0e10cSrcweir                 node->getMember(i->first), i->second);
520*cdf0e10cSrcweir         }
521*cdf0e10cSrcweir     }
522*cdf0e10cSrcweir }
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir }
525*cdf0e10cSrcweir 
526*cdf0e10cSrcweir void writeModFile(
527*cdf0e10cSrcweir     Components & components, rtl::OUString const & url, Data const & data)
528*cdf0e10cSrcweir {
529*cdf0e10cSrcweir     sal_Int32 i = url.lastIndexOf('/');
530*cdf0e10cSrcweir     OSL_ASSERT(i != -1);
531*cdf0e10cSrcweir     rtl::OUString dir(url.copy(0, i));
532*cdf0e10cSrcweir     switch (osl::Directory::createPath(dir)) {
533*cdf0e10cSrcweir     case osl::FileBase::E_None:
534*cdf0e10cSrcweir     case osl::FileBase::E_EXIST:
535*cdf0e10cSrcweir         break;
536*cdf0e10cSrcweir     case osl::FileBase::E_ACCES:
537*cdf0e10cSrcweir         OSL_TRACE(
538*cdf0e10cSrcweir             "cannot create registrymodifications.xcu path (E_ACCES); changes"
539*cdf0e10cSrcweir             " will be lost");
540*cdf0e10cSrcweir         return;
541*cdf0e10cSrcweir     default:
542*cdf0e10cSrcweir         throw css::uno::RuntimeException(
543*cdf0e10cSrcweir             (rtl::OUString(
544*cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("cannot create directory ")) +
545*cdf0e10cSrcweir              dir),
546*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
547*cdf0e10cSrcweir     }
548*cdf0e10cSrcweir     TempFile tmp;
549*cdf0e10cSrcweir     switch (osl::FileBase::createTempFile(&dir, &tmp.handle, &tmp.url)) {
550*cdf0e10cSrcweir     case osl::FileBase::E_None:
551*cdf0e10cSrcweir         break;
552*cdf0e10cSrcweir     case osl::FileBase::E_ACCES:
553*cdf0e10cSrcweir         OSL_TRACE(
554*cdf0e10cSrcweir             "cannot create temp registrymodifications.xcu (E_ACCES); changes"
555*cdf0e10cSrcweir             " will be lost");
556*cdf0e10cSrcweir         return;
557*cdf0e10cSrcweir     default:
558*cdf0e10cSrcweir         throw css::uno::RuntimeException(
559*cdf0e10cSrcweir             (rtl::OUString(
560*cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
561*cdf0e10cSrcweir                     "cannot create temporary file in ")) +
562*cdf0e10cSrcweir              dir),
563*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
564*cdf0e10cSrcweir     }
565*cdf0e10cSrcweir     writeData(
566*cdf0e10cSrcweir         tmp.handle,
567*cdf0e10cSrcweir         RTL_CONSTASCII_STRINGPARAM(
568*cdf0e10cSrcweir             "<?xml version=\"1.0\" encoding=\"UTF-8\"?><oor:items"
569*cdf0e10cSrcweir             " xmlns:oor=\"http://openoffice.org/2001/registry\""
570*cdf0e10cSrcweir             " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
571*cdf0e10cSrcweir             " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"));
572*cdf0e10cSrcweir     //TODO: Do not write back information about those removed items that did not
573*cdf0e10cSrcweir     // come from the .xcs/.xcu files, anyway (but had been added dynamically
574*cdf0e10cSrcweir     // instead):
575*cdf0e10cSrcweir     for (Modifications::Node::Children::const_iterator j(
576*cdf0e10cSrcweir              data.modifications.getRoot().children.begin());
577*cdf0e10cSrcweir          j != data.modifications.getRoot().children.end(); ++j)
578*cdf0e10cSrcweir     {
579*cdf0e10cSrcweir         writeModifications(
580*cdf0e10cSrcweir             components, tmp.handle, rtl::OUString(), rtl::Reference< Node >(),
581*cdf0e10cSrcweir             j->first, Data::findNode(Data::NO_LAYER, data.components, j->first),
582*cdf0e10cSrcweir             j->second);
583*cdf0e10cSrcweir     }
584*cdf0e10cSrcweir     writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("</oor:items>"));
585*cdf0e10cSrcweir     oslFileError e = osl_closeFile(tmp.handle);
586*cdf0e10cSrcweir     tmp.closed = true;
587*cdf0e10cSrcweir     if (e != osl_File_E_None) {
588*cdf0e10cSrcweir         throw css::uno::RuntimeException(
589*cdf0e10cSrcweir             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot close ")) +
590*cdf0e10cSrcweir              tmp.url),
591*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
592*cdf0e10cSrcweir     }
593*cdf0e10cSrcweir     if (osl::File::move(tmp.url, url) != osl::FileBase::E_None) {
594*cdf0e10cSrcweir         throw css::uno::RuntimeException(
595*cdf0e10cSrcweir             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot move ")) +
596*cdf0e10cSrcweir              tmp.url),
597*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
598*cdf0e10cSrcweir     }
599*cdf0e10cSrcweir     tmp.handle = 0;
600*cdf0e10cSrcweir }
601*cdf0e10cSrcweir 
602*cdf0e10cSrcweir }
603