VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/UnattendedScript.cpp@ 79862

Last change on this file since 79862 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/* $Id: UnattendedScript.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * Classes for reading/parsing/saving scripts for unattended installation.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_MAIN_UNATTENDED
23#include "LoggingNew.h"
24#include "VirtualBoxBase.h"
25#include "AutoCaller.h"
26#include <VBox/com/ErrorInfo.h>
27
28#include "UnattendedScript.h"
29#include "UnattendedImpl.h"
30
31#include <iprt/errcore.h>
32
33#include <iprt/ctype.h>
34#include <iprt/file.h>
35#include <iprt/vfs.h>
36#include <iprt/getopt.h>
37#include <iprt/path.h>
38
39using namespace std;
40
41#ifdef VBOX_WITH_UNATTENDED
42
43
44/*********************************************************************************************************************************
45* UnattendedScriptTemplate Implementation *
46*********************************************************************************************************************************/
47
48UnattendedScriptTemplate::UnattendedScriptTemplate(Unattended *pUnattended, const char *pszDefaultTemplateFilename,
49 const char *pszDefaultFilename)
50 : BaseTextScript(pUnattended, pszDefaultTemplateFilename, pszDefaultFilename), mpUnattended(pUnattended)
51{
52}
53
54
55HRESULT UnattendedScriptTemplate::saveToString(Utf8Str &rStrDst)
56{
57 static const char s_szPrefix[] = "@@VBOX_";
58 static const char s_szPrefixInsert[] = "@@VBOX_INSERT_";
59 static const char s_szPrefixCond[] = "@@VBOX_COND_";
60 static const char s_szPrefixCondEnd[] = "@@VBOX_COND_END@@";
61
62 struct
63 {
64 bool fSavedOutputting;
65 } aConds[8];
66 unsigned cConds = 0;
67 bool fOutputting = true;
68 HRESULT hrc = E_FAIL;
69 size_t offTemplate = 0;
70 size_t cchTemplate = mStrScriptFullContent.length();
71 rStrDst.setNull();
72 for (;;)
73 {
74 /*
75 * Find the next placeholder and add any text before it to the output.
76 */
77 size_t offPlaceholder = mStrScriptFullContent.find(s_szPrefix, offTemplate);
78 size_t cchToCopy = offPlaceholder != RTCString::npos ? offPlaceholder - offTemplate : cchTemplate - offTemplate;
79 if (cchToCopy > 0)
80 {
81 if (fOutputting)
82 {
83 try
84 {
85 rStrDst.append(mStrScriptFullContent, offTemplate, cchToCopy);
86 }
87 catch (std::bad_alloc &)
88 {
89 hrc = E_OUTOFMEMORY;
90 break;
91 }
92 }
93 offTemplate += cchToCopy;
94 }
95
96 /*
97 * Process placeholder.
98 */
99 if (offPlaceholder != RTCString::npos)
100 {
101 /*
102 * First we must find the end of the placeholder string.
103 */
104 const char *pszPlaceholder = mStrScriptFullContent.c_str() + offPlaceholder;
105 size_t cchPlaceholder = sizeof(s_szPrefix) - 1;
106 char ch;
107 while ( offPlaceholder + cchPlaceholder < cchTemplate
108 && (ch = pszPlaceholder[cchPlaceholder]) != '\0'
109 && ( ch == '_'
110 || RT_C_IS_UPPER(ch)
111 || RT_C_IS_DIGIT(ch)) )
112 cchPlaceholder++;
113
114 if ( offPlaceholder + cchPlaceholder < cchTemplate
115 && pszPlaceholder[cchPlaceholder] == '@')
116 {
117 cchPlaceholder++;
118 if ( offPlaceholder + cchPlaceholder < cchTemplate
119 && pszPlaceholder[cchPlaceholder] == '@')
120 cchPlaceholder++;
121 }
122
123 if ( pszPlaceholder[cchPlaceholder - 1] != '@'
124 || pszPlaceholder[cchPlaceholder - 2] != '@'
125 || ( strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) != 0
126 && strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) != 0) )
127 {
128 hrc = mpSetError->setError(E_FAIL, mpSetError->tr("Malformed template placeholder '%.*s'"),
129 cchPlaceholder, pszPlaceholder);
130 break;
131 }
132
133 offTemplate += cchPlaceholder;
134
135 /*
136 * @@VBOX_INSERT_XXX@@:
137 */
138 if (strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) == 0)
139 {
140 /*
141 * Get the placeholder value and add it to the output.
142 */
143 RTCString strValue;
144 hrc = getReplacement(pszPlaceholder, cchPlaceholder, fOutputting, strValue);
145 if (SUCCEEDED(hrc))
146 {
147 if (fOutputting)
148 {
149 try
150 {
151 rStrDst.append(strValue);
152 }
153 catch (std::bad_alloc &)
154 {
155 hrc = E_OUTOFMEMORY;
156 break;
157 }
158 }
159 }
160 else
161 break;
162 }
163 /*
164 * @@VBOX_COND_END@@: Pop one item of the conditional stack.
165 */
166 else if ( cchPlaceholder == sizeof(s_szPrefixCondEnd) - 1U
167 && strncmp(pszPlaceholder, s_szPrefixCondEnd, sizeof(s_szPrefixCondEnd) - 1U) == 0)
168 {
169 if (cConds > 0)
170 {
171 cConds--;
172 fOutputting = aConds[cConds].fSavedOutputting;
173 }
174 else
175 {
176 hrc = mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
177 mpSetError->tr("%s without @@VBOX_COND_XXX@@ at offset %zu (%#zx)"),
178 s_szPrefixCondEnd, offPlaceholder, offPlaceholder);
179 break;
180 }
181 }
182 /*
183 * @@VBOX_COND_XXX@@: Push the previous outputting state and combine it with the
184 * one from the condition.
185 */
186 else
187 {
188 Assert(strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) == 0);
189 if (cConds + 1 < RT_ELEMENTS(aConds))
190 {
191 aConds[cConds].fSavedOutputting = fOutputting;
192 bool fNewOutputting = fOutputting;
193 hrc = getConditional(pszPlaceholder, cchPlaceholder, &fNewOutputting);
194 if (SUCCEEDED(hrc))
195 fOutputting = fOutputting && fNewOutputting;
196 else
197 break;
198 cConds++;
199 }
200 else
201 {
202 hrc = mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
203 mpSetError->tr("Too deep conditional nesting at offset %zu (%#zx)"),
204 offPlaceholder, offPlaceholder);
205 break;
206 }
207 }
208 }
209
210 /*
211 * Done?
212 */
213 if (offTemplate >= cchTemplate)
214 {
215 if (cConds == 0)
216 return S_OK;
217 if (cConds == 1)
218 hrc = mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, mpSetError->tr("Missing @@VBOX_COND_END@@"));
219 else
220 hrc = mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, mpSetError->tr("Missing %u @@VBOX_COND_END@@"), cConds);
221 break;
222 }
223 }
224
225 /* failed */
226 rStrDst.setNull();
227 return hrc;
228}
229
230HRESULT UnattendedScriptTemplate::getReplacement(const char *pachPlaceholder, size_t cchPlaceholder,
231 bool fOutputting, RTCString &rValue)
232{
233 /*
234 * Check for an escaping suffix. Drop the '@@'.
235 */
236 size_t const cchFullPlaceholder = cchPlaceholder;
237 enum
238 {
239 kValueEscaping_None,
240 kValueEscaping_Bourne,
241 kValueEscaping_XML_Element,
242 kValueEscaping_XML_Attribute_Double_Quotes
243 } enmEscaping;
244
245#define PLACEHOLDER_ENDS_WITH(a_szSuffix) \
246 ( cchPlaceholder > sizeof(a_szSuffix) - 1U \
247 && memcmp(&pachPlaceholder[cchPlaceholder - sizeof(a_szSuffix) + 1U], a_szSuffix, sizeof(a_szSuffix) - 1U) == 0)
248 if (PLACEHOLDER_ENDS_WITH("_SH@@"))
249 {
250 cchPlaceholder -= 3 + 2;
251 enmEscaping = kValueEscaping_Bourne;
252 }
253 else if (PLACEHOLDER_ENDS_WITH("_ELEMENT@@"))
254 {
255 cchPlaceholder -= 8 + 2;
256 enmEscaping = kValueEscaping_XML_Element;
257 }
258 else if (PLACEHOLDER_ENDS_WITH("_ATTRIB_DQ@@"))
259 {
260 cchPlaceholder -= 10 + 2;
261 enmEscaping = kValueEscaping_XML_Attribute_Double_Quotes;
262 }
263 else
264 {
265 Assert(PLACEHOLDER_ENDS_WITH("@@"));
266 cchPlaceholder -= 2;
267 enmEscaping = kValueEscaping_None;
268 }
269
270 /*
271 * Resolve and escape the value.
272 */
273 HRESULT hrc;
274 try
275 {
276 switch (enmEscaping)
277 {
278 case kValueEscaping_None:
279 hrc = getUnescapedReplacement(pachPlaceholder, cchPlaceholder, cchFullPlaceholder, fOutputting, rValue);
280 if (SUCCEEDED(hrc))
281 return hrc;
282 break;
283
284 case kValueEscaping_Bourne:
285 case kValueEscaping_XML_Element:
286 case kValueEscaping_XML_Attribute_Double_Quotes:
287 {
288 RTCString strUnescaped;
289 hrc = getUnescapedReplacement(pachPlaceholder, cchPlaceholder, cchFullPlaceholder, fOutputting, strUnescaped);
290 if (SUCCEEDED(hrc))
291 {
292 switch (enmEscaping)
293 {
294 case kValueEscaping_Bourne:
295 {
296 const char * const papszArgs[2] = { strUnescaped.c_str(), NULL };
297 char *pszEscaped = NULL;
298 int vrc = RTGetOptArgvToString(&pszEscaped, papszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
299 if (RT_SUCCESS(vrc))
300 {
301 try
302 {
303 rValue = pszEscaped;
304 RTStrFree(pszEscaped);
305 return S_OK;
306 }
307 catch (std::bad_alloc &)
308 {
309 hrc = E_OUTOFMEMORY;
310 }
311 RTStrFree(pszEscaped);
312 }
313 break;
314 }
315
316 case kValueEscaping_XML_Element:
317 rValue.printf("%RMes", strUnescaped.c_str());
318 return S_OK;
319
320 case kValueEscaping_XML_Attribute_Double_Quotes:
321 {
322 RTCString strTmp;
323 strTmp.printf("%RMas", strUnescaped.c_str());
324 rValue = RTCString(strTmp, 1, strTmp.length() - 2);
325 return S_OK;
326 }
327
328 default:
329 hrc = E_FAIL;
330 break;
331 }
332 }
333 break;
334 }
335
336 default:
337 AssertFailedStmt(hrc = E_FAIL);
338 break;
339 }
340 }
341 catch (std::bad_alloc &)
342 {
343 hrc = E_OUTOFMEMORY;
344 }
345 rValue.setNull();
346 return hrc;
347}
348
349HRESULT UnattendedScriptTemplate::getUnescapedReplacement(const char *pachPlaceholder, size_t cchPlaceholder,
350 size_t cchFullPlaceholder, bool fOutputting, RTCString &rValue)
351{
352 RT_NOREF(fOutputting);
353#define IS_PLACEHOLDER_MATCH(a_szMatch) \
354 ( cchPlaceholder == sizeof("@@VBOX_INSERT_" a_szMatch) - 1U \
355 && memcmp(pachPlaceholder, "@@VBOX_INSERT_" a_szMatch, sizeof("@@VBOX_INSERT_" a_szMatch) - 1U) == 0)
356
357 if (IS_PLACEHOLDER_MATCH("USER_LOGIN"))
358 rValue = mpUnattended->i_getUser();
359 else if (IS_PLACEHOLDER_MATCH("USER_PASSWORD"))
360 rValue = mpUnattended->i_getPassword();
361 else if (IS_PLACEHOLDER_MATCH("ROOT_PASSWORD"))
362 rValue = mpUnattended->i_getPassword();
363 else if (IS_PLACEHOLDER_MATCH("USER_FULL_NAME"))
364 rValue = mpUnattended->i_getFullUserName();
365 else if (IS_PLACEHOLDER_MATCH("PRODUCT_KEY"))
366 rValue = mpUnattended->i_getProductKey();
367 else if (IS_PLACEHOLDER_MATCH("POST_INSTALL_COMMAND"))
368 rValue = mpUnattended->i_getPostInstallCommand();
369 else if (IS_PLACEHOLDER_MATCH("IMAGE_INDEX"))
370 rValue.printf("%u", mpUnattended->i_getImageIndex());
371 else if (IS_PLACEHOLDER_MATCH("OS_ARCH"))
372 rValue = mpUnattended->i_isGuestOs64Bit() ? "amd64" : "x86";
373 else if (IS_PLACEHOLDER_MATCH("OS_ARCH2"))
374 rValue = mpUnattended->i_isGuestOs64Bit() ? "x86_64" : "x86";
375 else if (IS_PLACEHOLDER_MATCH("OS_ARCH3"))
376 rValue = mpUnattended->i_isGuestOs64Bit() ? "x86_64" : "i386";
377 else if (IS_PLACEHOLDER_MATCH("OS_ARCH4"))
378 rValue = mpUnattended->i_isGuestOs64Bit() ? "x86_64" : "i486";
379 else if (IS_PLACEHOLDER_MATCH("OS_ARCH6"))
380 rValue = mpUnattended->i_isGuestOs64Bit() ? "x86_64" : "i686";
381 else if (IS_PLACEHOLDER_MATCH("TIME_ZONE_UX"))
382 rValue = mpUnattended->i_getTimeZoneInfo()
383 ? mpUnattended->i_getTimeZoneInfo()->pszUnixName : mpUnattended->i_getTimeZone();
384 else if (IS_PLACEHOLDER_MATCH("TIME_ZONE_WIN_NAME"))
385 {
386 PCRTTIMEZONEINFO pInfo = mpUnattended->i_getTimeZoneInfo();
387 if (pInfo)
388 rValue = pInfo->pszWindowsName ? pInfo->pszWindowsName : "GMT";
389 else
390 rValue = mpUnattended->i_getTimeZone();
391 }
392 else if (IS_PLACEHOLDER_MATCH("TIME_ZONE_WIN_INDEX"))
393 {
394 PCRTTIMEZONEINFO pInfo = mpUnattended->i_getTimeZoneInfo();
395 if (pInfo)
396 rValue.printf("%u", pInfo->idxWindows ? pInfo->idxWindows : 85 /*GMT*/);
397 else
398 rValue = mpUnattended->i_getTimeZone();
399 }
400 else if (IS_PLACEHOLDER_MATCH("LOCALE"))
401 rValue = mpUnattended->i_getLocale();
402 else if (IS_PLACEHOLDER_MATCH("DASH_LOCALE"))
403 {
404 rValue = mpUnattended->i_getLocale();
405 Assert(rValue[2] == '_');
406 rValue.replace(2, 1, "-");
407 }
408 else if (IS_PLACEHOLDER_MATCH("LANGUAGE"))
409 rValue = mpUnattended->i_getLanguage();
410 else if (IS_PLACEHOLDER_MATCH("COUNTRY"))
411 rValue = mpUnattended->i_getCountry();
412 else if (IS_PLACEHOLDER_MATCH("HOSTNAME_FQDN"))
413 rValue = mpUnattended->i_getHostname();
414 else if (IS_PLACEHOLDER_MATCH("HOSTNAME_WITHOUT_DOMAIN"))
415 rValue.assign(mpUnattended->i_getHostname(), 0, mpUnattended->i_getHostname().find("."));
416 else if (IS_PLACEHOLDER_MATCH("HOSTNAME_WITHOUT_DOMAIN_MAX_15"))
417 rValue.assign(mpUnattended->i_getHostname(), 0, RT_MIN(mpUnattended->i_getHostname().find("."), 15));
418 else if (IS_PLACEHOLDER_MATCH("HOSTNAME_DOMAIN"))
419 rValue.assign(mpUnattended->i_getHostname(), mpUnattended->i_getHostname().find(".") + 1);
420 else
421 {
422 rValue.setNull();
423 return mpSetError->setErrorBoth(E_FAIL, VERR_NOT_FOUND, mpSetError->tr("Unknown template placeholder '%.*s'"),
424 cchFullPlaceholder, pachPlaceholder);
425 }
426 return S_OK;
427#undef IS_PLACEHOLDER_MATCH
428}
429
430HRESULT UnattendedScriptTemplate::getConditional(const char *pachPlaceholder, size_t cchPlaceholder, bool *pfOutputting)
431{
432#define IS_PLACEHOLDER_MATCH(a_szMatch) \
433 ( cchPlaceholder == sizeof("@@VBOX_COND_" a_szMatch "@@") - 1U \
434 && memcmp(pachPlaceholder, "@@VBOX_COND_" a_szMatch "@@", sizeof("@@VBOX_COND_" a_szMatch "@@") - 1U) == 0)
435
436 /* Install guest additions: */
437 if (IS_PLACEHOLDER_MATCH("IS_INSTALLING_ADDITIONS"))
438 *pfOutputting = mpUnattended->i_getInstallGuestAdditions();
439 else if (IS_PLACEHOLDER_MATCH("IS_NOT_INSTALLING_ADDITIONS"))
440 *pfOutputting = !mpUnattended->i_getInstallGuestAdditions();
441 /* User == Administrator: */
442 else if (IS_PLACEHOLDER_MATCH("IS_USER_LOGIN_ADMINISTRATOR"))
443 *pfOutputting = mpUnattended->i_getUser().compare("Administrator", RTCString::CaseInsensitive) == 0;
444 else if (IS_PLACEHOLDER_MATCH("IS_USER_LOGIN_NOT_ADMINISTRATOR"))
445 *pfOutputting = mpUnattended->i_getUser().compare("Administrator", RTCString::CaseInsensitive) != 0;
446 /* Install TXS: */
447 else if (IS_PLACEHOLDER_MATCH("IS_INSTALLING_TEST_EXEC_SERVICE"))
448 *pfOutputting = mpUnattended->i_getInstallTestExecService();
449 else if (IS_PLACEHOLDER_MATCH("IS_NOT_INSTALLING_TEST_EXEC_SERVICE"))
450 *pfOutputting = !mpUnattended->i_getInstallTestExecService();
451 /* Post install command: */
452 else if (IS_PLACEHOLDER_MATCH("HAS_POST_INSTALL_COMMAND"))
453 *pfOutputting = mpUnattended->i_getPostInstallCommand().isNotEmpty();
454 else if (IS_PLACEHOLDER_MATCH("HAS_NO_POST_INSTALL_COMMAND"))
455 *pfOutputting = !mpUnattended->i_getPostInstallCommand().isNotEmpty();
456 /* Product key: */
457 else if (IS_PLACEHOLDER_MATCH("HAS_PRODUCT_KEY"))
458 *pfOutputting = mpUnattended->i_getProductKey().isNotEmpty();
459 else if (IS_PLACEHOLDER_MATCH("HAS_NO_PRODUCT_KEY"))
460 *pfOutputting = !mpUnattended->i_getProductKey().isNotEmpty();
461 /* Minimal installation: */
462 else if (IS_PLACEHOLDER_MATCH("IS_MINIMAL_INSTALLATION"))
463 *pfOutputting = mpUnattended->i_isMinimalInstallation();
464 else if (IS_PLACEHOLDER_MATCH("IS_NOT_MINIMAL_INSTALLATION"))
465 *pfOutputting = !mpUnattended->i_isMinimalInstallation();
466 /* Is RTC using UTC (i.e. set to UTC time on startup): */
467 else if (IS_PLACEHOLDER_MATCH("IS_RTC_USING_UTC"))
468 *pfOutputting = mpUnattended->i_isRtcUsingUtc();
469 else if (IS_PLACEHOLDER_MATCH("IS_NOT_RTC_USING_UTC"))
470 *pfOutputting = !mpUnattended->i_isRtcUsingUtc();
471 else
472 return mpSetError->setErrorBoth(E_FAIL, VERR_NOT_FOUND, mpSetError->tr("Unknown conditional placeholder '%.*s'"),
473 cchPlaceholder, pachPlaceholder);
474 return S_OK;
475#undef IS_PLACEHOLDER_MATCH
476}
477
478#endif /* VBOX_WITH_UNATTENDED */
479#if 0 /* Keeping this a reference */
480
481
482/*********************************************************************************************************************************
483* UnattendedSUSEXMLScript Implementation *
484*********************************************************************************************************************************/
485
486HRESULT UnattendedSUSEXMLScript::parse()
487{
488 HRESULT hrc = UnattendedXMLScript::parse();
489 if (SUCCEEDED(hrc))
490 {
491 /*
492 * Check that we've got the right root element type.
493 */
494 const xml::ElementNode *pelmRoot = mDoc.getRootElement();
495 if ( pelmRoot
496 && strcmp(pelmRoot->getName(), "profile") == 0)
497 {
498 /*
499 * Work thought the sections.
500 */
501 try
502 {
503 LoopThruSections(pelmRoot);
504 hrc = S_OK;
505 }
506 catch (std::bad_alloc &)
507 {
508 hrc = E_OUTOFMEMORY;
509 }
510 }
511 else if (pelmRoot)
512 hrc = mpSetError->setError(E_FAIL, mpSetError->tr("XML document root element is '%s' instead of 'profile'"),
513 pelmRoot->getName());
514 else
515 hrc = mpSetError->setError(E_FAIL, mpSetError->tr("Missing XML root element"));
516 }
517 return hrc;
518}
519
520HRESULT UnattendedSUSEXMLScript::setFieldInElement(xml::ElementNode *pElement, const DataId enmDataId, const Utf8Str &rStrValue)
521{
522 /*
523 * Don't set empty values.
524 */
525 if (rStrValue.isEmpty())
526 {
527 Utf8Str strProbableValue;
528 try
529 {
530 strProbableValue = createProbableValue(enmDataId, pElement);
531 }
532 catch (std::bad_alloc &)
533 {
534 return E_OUTOFMEMORY;
535 }
536 return UnattendedXMLScript::setFieldInElement(pElement, enmDataId, strProbableValue);
537 }
538 return UnattendedXMLScript::setFieldInElement(pElement, enmDataId, rStrValue);
539}
540
541HRESULT UnattendedSUSEXMLScript::LoopThruSections(const xml::ElementNode *pelmRoot)
542{
543 xml::NodesLoop loopChildren(*pelmRoot);
544 const xml::ElementNode *pelmOuterLoop;
545 while ((pelmOuterLoop = loopChildren.forAllNodes()) != NULL)
546 {
547 const char *pcszElemName = pelmOuterLoop->getName();
548 if (!strcmp(pcszElemName, "users"))
549 {
550 xml::NodesLoop loopUsers(*pelmOuterLoop);
551 const xml::ElementNode *pelmUser;
552 while ((pelmUser = loopUsers.forAllNodes()) != NULL)
553 {
554 HRESULT hrc = HandleUserAccountsSection(pelmUser);
555 if (FAILED(hrc))
556 return hrc;
557 }
558 }
559 }
560 return S_OK;
561}
562
563HRESULT UnattendedSUSEXMLScript::HandleUserAccountsSection(const xml::ElementNode *pelmSection)
564{
565 xml::NodesLoop loopUser(*pelmSection);
566
567 const xml::ElementNode *pelmCur;
568 while ((pelmCur = loopUser.forAllNodes()) != NULL)
569 {
570 const char *pszValue = pelmCur->getValue();
571#ifdef LOG_ENABLED
572 if (!RTStrCmp(pelmCur->getName(), "uid"))
573 LogRelFunc(("UnattendedSUSEXMLScript::HandleUserAccountsSection profile/users/%s/%s = %s\n",
574 pelmSection->getName(), pelmCur->getName(), pszValue));
575#endif
576
577 if (!RTStrCmp(pszValue, "$homedir"))
578 mNodesForCorrectionMap.insert(make_pair(USERHOMEDIR_ID, pelmCur));
579
580 if (!RTStrCmp(pszValue, "$user"))
581 mNodesForCorrectionMap.insert(make_pair(USERNAME_ID, pelmCur));
582
583 if (!RTStrCmp(pszValue, "$password"))
584 mNodesForCorrectionMap.insert(make_pair(USERPASSWORD_ID, pelmCur));
585 }
586 return S_OK;
587}
588
589Utf8Str UnattendedSUSEXMLScript::createProbableValue(const DataId enmDataId, const xml::ElementNode *pCurElem)
590{
591 const xml::ElementNode *pElem = pCurElem;
592
593 switch (enmDataId)
594 {
595 case USERHOMEDIR_ID:
596// if ((pElem = pElem->findChildElement("home")))
597// {
598 return createProbableUserHomeDir(pElem);
599// }
600 break;
601 default:
602 break;
603 }
604
605 return Utf8Str::Empty;
606}
607
608Utf8Str UnattendedSUSEXMLScript::createProbableUserHomeDir(const xml::ElementNode *pCurElem)
609{
610 Utf8Str strCalcValue;
611 const xml::ElementNode *pElem = pCurElem->findNextSibilingElement("username");
612 if (pElem)
613 {
614 const char *pszValue = pElem->getValue();
615 strCalcValue = "/home/";
616 strCalcValue.append(pszValue);
617 }
618
619 return strCalcValue;
620}
621#endif /* just for reference */
622
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette