VirtualBox

source: vbox/trunk/src/VBox/Main/ExtPackUtil.cpp@ 33623

Last change on this file since 33623 was 33623, checked in by vboxsync, 15 years ago

ExtPack: More code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1/* $Id: ExtPackUtil.cpp 33623 2010-10-29 16:16:06Z vboxsync $ */
2/** @file
3 * VirtualBox Main - Extension Pack Utilities and definitions, VBoxC, VBoxSVC, ++.
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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#include "ExtPackUtil.h"
23
24#include <iprt/ctype.h>
25#include <iprt/dir.h>
26#include <iprt/file.h>
27#include <iprt/param.h>
28#include <iprt/path.h>
29#include <iprt/string.h>
30#include <iprt/cpp/xml.h>
31
32#include <VBox/log.h>
33
34
35/**
36 * Reads the extension pack description.
37 *
38 * @returns NULL on success, pointer to an error message on failure (caller
39 * deletes it).
40 * @param a_pszDir The directory containing the description file.
41 * @param a_pExtPackDesc Where to store the description file.
42 * @param a_pObjInfo Where to store the object info for the file (unix
43 * attribs). Optional.
44 */
45iprt::MiniString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo)
46{
47 /*
48 * Clear the description.
49 */
50 a_pExtPackDesc->strName.setNull();
51 a_pExtPackDesc->strDescription.setNull();
52 a_pExtPackDesc->strVersion.setNull();
53 a_pExtPackDesc->uRevision = 0;
54 a_pExtPackDesc->strMainModule.setNull();
55
56 /*
57 * Validate, open and parse the XML file.
58 */
59 char szFilePath[RTPATH_MAX];
60 int vrc = RTPathJoin(szFilePath, sizeof(szFilePath), a_pszDir, VBOX_EXTPACK_DESCRIPTION_NAME);
61 if (RT_FAILURE(vrc))
62 return new iprt::MiniString("No VirtualBoxExtensionPack element");
63
64 RTFSOBJINFO ObjInfo;
65 vrc = RTPathQueryInfoEx(szFilePath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
66 if (RT_FAILURE(vrc))
67 return &(new iprt::MiniString())->printf("RTPathQueryInfoEx failed with %Rrc", vrc);
68 if (a_pObjInfo)
69 *a_pObjInfo = ObjInfo;
70 if (!RTFS_IS_FILE(ObjInfo.Attr.fMode))
71 {
72 if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
73 return new iprt::MiniString("The XML file is symlinked, that is not allowed");
74 return &(new iprt::MiniString)->printf("The XML file is not a file (fMode=%#x)", ObjInfo.Attr.fMode);
75 }
76
77 xml::Document Doc;
78 xml::XmlFileParser Parser;
79 try
80 {
81 Parser.read(szFilePath, Doc);
82 }
83 catch (xml::XmlError Err)
84 {
85 return new iprt::MiniString(Err.what());
86 }
87 xml::ElementNode *pRoot = Doc.getRootElement();
88
89 /*
90 * Get the main element and check its version.
91 */
92 const xml::ElementNode *pVBoxExtPackElm = pRoot->findChildElement(NULL, "VirtualBoxExtensionPack");
93 if (!pVBoxExtPackElm)
94 return new iprt::MiniString("No VirtualBoxExtensionPack element");
95
96 iprt::MiniString strFormatVersion;
97 if (!pVBoxExtPackElm->getAttributeValue("version", strFormatVersion))
98 return new iprt::MiniString("Missing format version");
99 if (!strFormatVersion.equals("1.0"))
100 return &(new iprt::MiniString("Unsupported format version: "))->append(strFormatVersion);
101
102 /*
103 * Read and validate the name.
104 */
105 const xml::ElementNode *pNameElm = pVBoxExtPackElm->findChildElement("Name");
106 if (!pNameElm)
107 return new iprt::MiniString("The 'Name' element is missing");
108 const char *pszName = pNameElm->getValue();
109 if (!VBoxExtPackIsValidName(pszName))
110 return &(new iprt::MiniString("Invalid name: "))->append(pszName);
111
112 const xml::ElementNode *pDescElm = pVBoxExtPackElm->findChildElement("Description");
113 if (!pDescElm)
114 return new iprt::MiniString("The 'Description' element is missing");
115 const char *pszDesc = pDescElm->getValue();
116 if (!pszDesc || *pszDesc == '\0')
117 return new iprt::MiniString("The 'Description' element is empty");
118 if (strpbrk(pszDesc, "\n\r\t\v\b") != NULL)
119 return new iprt::MiniString("The 'Description' must not contain control characters");
120
121 const xml::ElementNode *pVersionElm = pVBoxExtPackElm->findChildElement("Version");
122 if (!pVersionElm)
123 return new iprt::MiniString("The 'Version' element is missing");
124 const char *pszVersion = pVersionElm->getValue();
125 if (!pszVersion || *pszVersion == '\0')
126 return new iprt::MiniString("The 'Version' element is empty");
127 if (!VBoxExtPackIsValidVersionString(pszVersion))
128 return &(new iprt::MiniString("Invalid version string: "))->append(pszVersion);
129
130 uint32_t uRevision;
131 if (!pVersionElm->getAttributeValue("revision", uRevision))
132 uRevision = 0;
133
134 const xml::ElementNode *pMainModuleElm = pVBoxExtPackElm->findChildElement("MainModule");
135 if (!pMainModuleElm)
136 return new iprt::MiniString("The 'MainModule' element is missing");
137 const char *pszMainModule = pMainModuleElm->getValue();
138 if (!pszMainModule || *pszMainModule == '\0')
139 return new iprt::MiniString("The 'MainModule' element is empty");
140 if (!VBoxExtPackIsValidMainModuleString(pszVersion))
141 return &(new iprt::MiniString("Invalid main module string: "))->append(pszMainModule);
142
143 /*
144 * Everything seems fine, fill in the return values and return successfully.
145 */
146 a_pExtPackDesc->strName = pszName;
147 a_pExtPackDesc->strDescription = pszDesc;
148 a_pExtPackDesc->strVersion = pszVersion;
149 a_pExtPackDesc->uRevision = uRevision;
150 a_pExtPackDesc->strMainModule = pszMainModule;
151
152 return NULL;
153}
154
155
156/**
157 * Validates the extension pack name.
158 *
159 * @returns true if valid, false if not.
160 * @param pszName The name to validate.
161 */
162bool VBoxExtPackIsValidName(const char *pszName)
163{
164 /* This must match the code in the extension manager. */
165 if (!pszName || *pszName == '\0')
166 return false;
167 while (RT_C_IS_ALNUM(*pszName) || *pszName == ' ')
168 pszName++;
169 return *pszName == '\0';
170}
171
172/**
173 * Validates the extension pack version string.
174 *
175 * @returns true if valid, false if not.
176 * @param pszVersion The version string to validate.
177 */
178bool VBoxExtPackIsValidVersionString(const char *pszVersion)
179{
180 if (!pszVersion || *pszVersion == '\0')
181 return false;
182
183 /* 1.x.y.z... */
184 if (!RT_C_IS_DIGIT(*pszVersion))
185 return false;
186 for (;;)
187 {
188 while (RT_C_IS_DIGIT(*pszVersion))
189 pszVersion++;
190 if (*pszVersion != '.')
191 break;
192 }
193
194 /* upper case string + numbers indicating the build type */
195 if (*pszVersion == '-' || *pszVersion == '_')
196 {
197 do
198 pszVersion++;
199 while ( RT_C_IS_DIGIT(*pszVersion)
200 || RT_C_IS_UPPER(*pszVersion)
201 || *pszVersion == '-'
202 || *pszVersion == '_');
203 }
204
205 /* revision or nothing */
206 if (*pszVersion != '\0')
207 {
208 if (*pszVersion != 'r')
209 return false;
210 do
211 pszVersion++;
212 while (RT_C_IS_DIGIT(*pszVersion));
213 }
214
215 return *pszVersion == '\0';
216}
217
218/**
219 * Validates the extension pack main module string.
220 *
221 * @returns true if valid, false if not.
222 * @param pszMainModule The main module string to validate.
223 */
224bool VBoxExtPackIsValidMainModuleString(const char *pszMainModule)
225{
226 if (!pszMainModule || *pszMainModule == '\0')
227 return false;
228
229 /* Restricted charset, no extensions (dots). */
230 while ( RT_C_IS_ALNUM(*pszMainModule)
231 || *pszMainModule == '-'
232 || *pszMainModule == '_')
233 pszMainModule++;
234
235 return *pszMainModule == '\0';
236}
237
Note: See TracBrowser for help on using the repository browser.

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