VirtualBox

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

Last change on this file since 33696 was 33656, checked in by vboxsync, 14 years ago

*: rebrand Sun (L)GPL disclaimers

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