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::__anon041c28b50111::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("	"));
139 i = j + 1;
140 break;
141 case '\x0A':
142 writeData(handle, convertToUtf8(value, i, j - i));
143 writeData(handle, RTL_CONSTASCII_STRINGPARAM("
"));
144 i = j + 1;
145 break;
146 case '\x0D':
147 writeData(handle, convertToUtf8(value, i, j - i));
148 writeData(handle, RTL_CONSTASCII_STRINGPARAM("
"));
149 i = j + 1;
150 break;
151 case '"':
152 writeData(handle, convertToUtf8(value, i, j - i));
153 writeData(handle, RTL_CONSTASCII_STRINGPARAM("""));
154 i = j + 1;
155 break;
156 case '&':
157 writeData(handle, convertToUtf8(value, i, j - i));
158 writeData(handle, RTL_CONSTASCII_STRINGPARAM("&"));
159 i = j + 1;
160 break;
161 case '<':
162 writeData(handle, convertToUtf8(value, i, j - i));
163 writeData(handle, RTL_CONSTASCII_STRINGPARAM("<"));
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("
"));
215 i = j + 1;
216 } else if (c == '&') {
217 writeData(handle, convertToUtf8(value, i, j - i));
218 writeData(handle, RTL_CONSTASCII_STRINGPARAM("&"));
219 i = j + 1;
220 } else if (c == '<') {
221 writeData(handle, convertToUtf8(value, i, j - i));
222 writeData(handle, RTL_CONSTASCII_STRINGPARAM("<"));
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(">"));
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 /** Parent paths whose children should disappear */
457 const char *historyPath = "/org.openoffice.Office.Histories/Histories";
458 const char *commonHistoryPath = "/org.openoffice.Office.Common/History";
459 // It is never necessary to write oor:finalized or oor:mandatory attributes,
460 // as they cannot be set via the UNO API.
461 if (modifications.children.empty()) {
462 OSL_ASSERT(parent.is());
463 // components themselves have no parent but must have children
464 if (node.is() ||
465 ((parentPathRepresentation.compareToAscii(historyPath, strlen(historyPath)) != 0) &&
466 (parentPathRepresentation.compareToAscii(commonHistoryPath, strlen(commonHistoryPath)) != 0))) {
467 writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\""));
468 writeAttributeValue(handle, parentPathRepresentation);
469 writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
470 if (node.is()) {
471 writeNode(components, handle, parent, nodeName, node);
472 } else {
473 switch (parent->kind()) {
474 case Node::KIND_LOCALIZED_PROPERTY:
475 writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
476 if (nodeName.getLength() != 0) {
477 writeData(
478 handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
479 writeAttributeValue(handle, nodeName);
480 writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
481 }
482 writeData(
483 handle, RTL_CONSTASCII_STRINGPARAM(" oor:op=\"remove\"/>"));
484 break;
485 case Node::KIND_GROUP:
486 OSL_ASSERT(
487 dynamic_cast< GroupNode * >(parent.get())->isExtensible());
488 writeData(
489 handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
490 writeAttributeValue(handle, nodeName);
491 writeData(
492 handle,
493 RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
494 break;
495 case Node::KIND_SET:
496 writeData(
497 handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
498 writeAttributeValue(handle, nodeName);
499 writeData(
500 handle,
501 RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
502 break;
503 default:
504 OSL_ASSERT(false); // this cannot happen
505 break;
506 }
507 }
508 writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>"));
509 } // else: the element disappears
510 } else {
511 OSL_ASSERT(node.is());
512 rtl::OUString pathRep(
513 parentPathRepresentation +
514 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
515 Data::createSegment(node->getTemplateName(), nodeName));
516 for (Modifications::Node::Children::const_iterator i(
517 modifications.children.begin());
518 i != modifications.children.end(); ++i)
519 {
520 writeModifications(
521 components, handle, pathRep, node, i->first,
522 node->getMember(i->first), i->second);
523 }
524 }
525 }
526
527 }
528
writeModFile(Components & components,rtl::OUString const & url,Data const & data)529 void writeModFile(
530 Components & components, rtl::OUString const & url, Data const & data)
531 {
532 sal_Int32 i = url.lastIndexOf('/');
533 OSL_ASSERT(i != -1);
534 rtl::OUString dir(url.copy(0, i));
535 switch (osl::Directory::createPath(dir)) {
536 case osl::FileBase::E_None:
537 case osl::FileBase::E_EXIST:
538 break;
539 case osl::FileBase::E_ACCES:
540 OSL_TRACE(
541 "cannot create registrymodifications.xcu path (E_ACCES); changes"
542 " will be lost");
543 return;
544 default:
545 throw css::uno::RuntimeException(
546 (rtl::OUString(
547 RTL_CONSTASCII_USTRINGPARAM("cannot create directory ")) +
548 dir),
549 css::uno::Reference< css::uno::XInterface >());
550 }
551 TempFile tmp;
552 switch (osl::FileBase::createTempFile(&dir, &tmp.handle, &tmp.url)) {
553 case osl::FileBase::E_None:
554 break;
555 case osl::FileBase::E_ACCES:
556 OSL_TRACE(
557 "cannot create temp registrymodifications.xcu (E_ACCES); changes"
558 " will be lost");
559 return;
560 default:
561 throw css::uno::RuntimeException(
562 (rtl::OUString(
563 RTL_CONSTASCII_USTRINGPARAM(
564 "cannot create temporary file in ")) +
565 dir),
566 css::uno::Reference< css::uno::XInterface >());
567 }
568 writeData(
569 tmp.handle,
570 RTL_CONSTASCII_STRINGPARAM(
571 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><oor:items"
572 " xmlns:oor=\"http://openoffice.org/2001/registry\""
573 " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
574 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"));
575 //TODO: Do not write back information about those removed items that did not
576 // come from the .xcs/.xcu files, anyway (but had been added dynamically
577 // instead):
578 for (Modifications::Node::Children::const_iterator j(
579 data.modifications.getRoot().children.begin());
580 j != data.modifications.getRoot().children.end(); ++j)
581 {
582 writeModifications(
583 components, tmp.handle, rtl::OUString(), rtl::Reference< Node >(),
584 j->first, Data::findNode(Data::NO_LAYER, data.components, j->first),
585 j->second);
586 }
587 writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("</oor:items>"));
588 oslFileError e = osl_closeFile(tmp.handle);
589 tmp.closed = true;
590 if (e != osl_File_E_None) {
591 throw css::uno::RuntimeException(
592 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot close ")) +
593 tmp.url),
594 css::uno::Reference< css::uno::XInterface >());
595 }
596 if (osl::File::move(tmp.url, url) != osl::FileBase::E_None) {
597 throw css::uno::RuntimeException(
598 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot move ")) +
599 tmp.url),
600 css::uno::Reference< css::uno::XInterface >());
601 }
602 tmp.handle = 0;
603 }
604
605 }
606