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