xref: /haiku/src/kits/package/RepositoryInfo.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
1 /*
2  * Copyright 2011-2020, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Oliver Tappe <zooey@hirschkaefer.de>
7  *		Andrew Lindesay <apl@lindesay.co.nz>
8  */
9 
10 
11 #include <package/RepositoryInfo.h>
12 
13 #include <stdlib.h>
14 
15 #include <new>
16 
17 #include <driver_settings.h>
18 #include <File.h>
19 #include <Message.h>
20 
21 #include <AutoDeleter.h>
22 #include <AutoDeleterDrivers.h>
23 #include <package/PackageInfo.h>
24 
25 
26 namespace BPackageKit {
27 
28 
29 const uint8 BRepositoryInfo::kDefaultPriority	= 50;
30 
31 const char* const BRepositoryInfo::kNameField			= "name";
32 const char* const BRepositoryInfo::kURLField			= "url";
33 const char* const BRepositoryInfo::kIdentifierField		= "identifier";
34 const char* const BRepositoryInfo::kBaseURLField		= "baseUrl";
35 const char* const BRepositoryInfo::kVendorField			= "vendor";
36 const char* const BRepositoryInfo::kSummaryField		= "summary";
37 const char* const BRepositoryInfo::kPriorityField		= "priority";
38 const char* const BRepositoryInfo::kArchitectureField	= "architecture";
39 const char* const BRepositoryInfo::kLicenseNameField	= "licenseName";
40 const char* const BRepositoryInfo::kLicenseTextField	= "licenseText";
41 
42 
43 BRepositoryInfo::BRepositoryInfo()
44 	:
45 	fInitStatus(B_NO_INIT),
46 	fPriority(kDefaultPriority),
47 	fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT)
48 {
49 }
50 
51 
52 BRepositoryInfo::BRepositoryInfo(BMessage* data)
53 	:
54 	inherited(data),
55 	fLicenseTexts(5)
56 {
57 	fInitStatus = _SetTo(data);
58 }
59 
60 
61 BRepositoryInfo::BRepositoryInfo(const BEntry& entry)
62 {
63 	fInitStatus = _SetTo(entry);
64 }
65 
66 
67 BRepositoryInfo::~BRepositoryInfo()
68 {
69 }
70 
71 
72 /*static*/ BRepositoryInfo*
73 BRepositoryInfo::Instantiate(BMessage* data)
74 {
75 	if (validate_instantiation(data, "BPackageKit::BRepositoryInfo"))
76 		return new (std::nothrow) BRepositoryInfo(data);
77 
78 	return NULL;
79 }
80 
81 
82 status_t
83 BRepositoryInfo::Archive(BMessage* data, bool deep) const
84 {
85 	status_t result = inherited::Archive(data, deep);
86 	if (result != B_OK)
87 		return result;
88 
89 	if (!fBaseURL.IsEmpty()) {
90 		if ((result = data->AddString(kBaseURLField, fBaseURL)) != B_OK)
91 			return result;
92 	}
93 
94 	if ((result = data->AddString(kNameField, fName)) != B_OK)
95 		return result;
96 	if ((result = data->AddString(kIdentifierField, fIdentifier)) != B_OK)
97 		return result;
98 	// "url" is an older, deprecated key for "identifier"
99 	if ((result = data->AddString(kURLField, fIdentifier)) != B_OK)
100 		return result;
101 	if ((result = data->AddString(kVendorField, fVendor)) != B_OK)
102 		return result;
103 	if ((result = data->AddString(kSummaryField, fSummary)) != B_OK)
104 		return result;
105 	if ((result = data->AddUInt8(kPriorityField, fPriority)) != B_OK)
106 		return result;
107 	if ((result = data->AddUInt8(kArchitectureField, fArchitecture)) != B_OK)
108 		return result;
109 	for (int i = 0; i < fLicenseNames.CountStrings(); ++i) {
110 		result = data->AddString(kLicenseNameField, fLicenseNames.StringAt(i));
111 		if (result != B_OK)
112 			return result;
113 	}
114 	for (int i = 0; i < fLicenseTexts.CountStrings(); ++i) {
115 		result = data->AddString(kLicenseTextField, fLicenseTexts.StringAt(i));
116 		if (result != B_OK)
117 			return result;
118 	}
119 
120 	return B_OK;
121 }
122 
123 
124 status_t
125 BRepositoryInfo::InitCheck() const
126 {
127 	return fInitStatus;
128 }
129 
130 
131 status_t
132 BRepositoryInfo::SetTo(const BMessage* data)
133 {
134 	return fInitStatus = _SetTo(data);
135 }
136 
137 
138 status_t
139 BRepositoryInfo::SetTo(const BEntry& entry)
140 {
141 	return fInitStatus = _SetTo(entry);
142 }
143 
144 
145 const BString&
146 BRepositoryInfo::Name() const
147 {
148 	return fName;
149 }
150 
151 
152 const BString&
153 BRepositoryInfo::BaseURL() const
154 {
155 	return fBaseURL;
156 }
157 
158 
159 const BString&
160 BRepositoryInfo::Identifier() const
161 {
162 	return fIdentifier;
163 }
164 
165 
166 const BString&
167 BRepositoryInfo::Vendor() const
168 {
169 	return fVendor;
170 }
171 
172 
173 const BString&
174 BRepositoryInfo::Summary() const
175 {
176 	return fSummary;
177 }
178 
179 
180 uint8
181 BRepositoryInfo::Priority() const
182 {
183 	return fPriority;
184 }
185 
186 
187 BPackageArchitecture
188 BRepositoryInfo::Architecture() const
189 {
190 	return fArchitecture;
191 }
192 
193 
194 const BStringList&
195 BRepositoryInfo::LicenseNames() const
196 {
197 	return fLicenseNames;
198 }
199 
200 
201 const BStringList&
202 BRepositoryInfo::LicenseTexts() const
203 {
204 	return fLicenseTexts;
205 }
206 
207 
208 void
209 BRepositoryInfo::SetName(const BString& name)
210 {
211 	fName = name;
212 }
213 
214 
215 void
216 BRepositoryInfo::SetIdentifier(const BString& identifier)
217 {
218 	fIdentifier = identifier;
219 }
220 
221 
222 void
223 BRepositoryInfo::SetBaseURL(const BString& url)
224 {
225 	fBaseURL = url;
226 }
227 
228 
229 void
230 BRepositoryInfo::SetVendor(const BString& vendor)
231 {
232 	fVendor = vendor;
233 }
234 
235 
236 void
237 BRepositoryInfo::SetSummary(const BString& summary)
238 {
239 	fSummary = summary;
240 }
241 
242 
243 void
244 BRepositoryInfo::SetPriority(uint8 priority)
245 {
246 	fPriority = priority;
247 }
248 
249 
250 void
251 BRepositoryInfo::SetArchitecture(BPackageArchitecture architecture)
252 {
253 	fArchitecture = architecture;
254 }
255 
256 
257 status_t
258 BRepositoryInfo::AddLicense(const BString& licenseName,
259 	const BString& licenseText)
260 {
261 	if (!fLicenseNames.Add(licenseName) || !fLicenseTexts.Add(licenseText))
262 		return B_NO_MEMORY;
263 
264 	return B_OK;
265 }
266 
267 
268 void
269 BRepositoryInfo::ClearLicenses()
270 {
271 	fLicenseNames.MakeEmpty();
272 	fLicenseTexts.MakeEmpty();
273 }
274 
275 
276 status_t
277 BRepositoryInfo::_SetTo(const BMessage* data)
278 {
279 	if (data == NULL)
280 		return B_BAD_VALUE;
281 
282 	status_t result;
283 	if ((result = data->FindString(kNameField, &fName)) != B_OK)
284 		return result;
285 	result = data->FindString(kIdentifierField, &fIdentifier);
286 	if (result == B_NAME_NOT_FOUND) {
287 		result = data->FindString(kURLField, &fIdentifier);
288 			// this is a legacy key for the identifier.
289 	}
290 	if (result != B_OK)
291 		return result;
292 	if ((result = data->FindString(kVendorField, &fVendor)) != B_OK)
293 		return result;
294 	if ((result = data->FindString(kSummaryField, &fSummary)) != B_OK)
295 		return result;
296 	if ((result = data->FindUInt8(kPriorityField, &fPriority)) != B_OK)
297 		return result;
298 	if ((result = data->FindUInt8(
299 			kArchitectureField, (uint8*)&fArchitecture)) != B_OK) {
300 		return result;
301 	}
302 	if (fArchitecture == B_PACKAGE_ARCHITECTURE_ANY)
303 		return B_BAD_DATA;
304 
305 	// this field is optional because earlier versions did not support this
306 	// field.
307 	status_t baseUrlResult = data->FindString(kBaseURLField, &fBaseURL);
308 	switch (baseUrlResult) {
309 		case B_NAME_NOT_FOUND:
310 			// This is a temporary measure because older versions of the file
311 			// format would take the "url" (identifier) field for the "base-url"
312 			// Once this transitional period is over this can be removed.
313 			if (fIdentifier.StartsWith("http"))
314 				fBaseURL = fIdentifier;
315 			break;
316 		case B_OK:
317 			break;
318 		default:
319 			return baseUrlResult;
320 	}
321 
322 	const char* licenseName;
323 	const char* licenseText;
324 	for (int i = 0;
325 		data->FindString(kLicenseNameField, i, &licenseName) == B_OK
326 			&& data->FindString(kLicenseTextField, i, &licenseText) == B_OK;
327 		++i) {
328 		if (!fLicenseNames.Add(licenseName) || !fLicenseTexts.Add(licenseText))
329 			return B_NO_MEMORY;
330 	}
331 
332 	return B_OK;
333 }
334 
335 
336 status_t
337 BRepositoryInfo::_SetTo(const BEntry& entry)
338 {
339 	BFile file(&entry, B_READ_ONLY);
340 	status_t result = file.InitCheck();
341 	if (result != B_OK)
342 		return result;
343 
344 	off_t size;
345 	if ((result = file.GetSize(&size)) != B_OK)
346 		return result;
347 
348 	BString configString;
349 	char* buffer = configString.LockBuffer(size);
350 	if (buffer == NULL)
351 		return B_NO_MEMORY;
352 
353 	if ((result = file.Read(buffer, size)) < size) {
354 		configString.UnlockBuffer(0);
355 		return (result >= 0) ? B_IO_ERROR : result;
356 	}
357 
358 	buffer[size] = '\0';
359 	configString.UnlockBuffer(size);
360 
361 	DriverSettingsUnloader settingsHandle(
362 		parse_driver_settings_string(configString.String()));
363 	if (!settingsHandle.IsSet())
364 		return B_BAD_DATA;
365 
366 	const char* name = get_driver_parameter(settingsHandle.Get(), "name", NULL,
367 		NULL);
368 	const char* identifier = get_driver_parameter(settingsHandle.Get(),
369 		"identifier", NULL, NULL);
370 	// Also handle the old name if the new one isn't found
371 	if (identifier == NULL || *identifier == '\0')
372 		identifier = get_driver_parameter(settingsHandle.Get(),
373 			"url", NULL, NULL);
374 	const char* baseUrl = get_driver_parameter(settingsHandle.Get(),
375 		"baseurl", NULL, NULL);
376 	const char* vendor = get_driver_parameter(settingsHandle.Get(),
377 		"vendor", NULL, NULL);
378 	const char* summary = get_driver_parameter(settingsHandle.Get(),
379 		"summary", NULL, NULL);
380 	const char* priorityString = get_driver_parameter(settingsHandle.Get(),
381 		"priority", NULL, NULL);
382 	const char* architectureString = get_driver_parameter(settingsHandle.Get(),
383 		"architecture", NULL, NULL);
384 
385 	if (name == NULL || *name == '\0'
386 		|| identifier == NULL || *identifier == '\0'
387 		|| vendor == NULL || *vendor == '\0'
388 		|| summary == NULL || *summary == '\0'
389 		|| priorityString == NULL || *priorityString == '\0'
390 		|| architectureString == NULL || *architectureString == '\0') {
391 		return B_BAD_DATA;
392 	}
393 
394 	BPackageArchitecture architecture;
395 	if (BPackageInfo::GetArchitectureByName(architectureString, architecture)
396 			!= B_OK || architecture == B_PACKAGE_ARCHITECTURE_ANY) {
397 		return B_BAD_DATA;
398 	}
399 
400 	fName = name;
401 	fBaseURL = baseUrl;
402 	fIdentifier = identifier;
403 	fVendor = vendor;
404 	fSummary = summary;
405 	fPriority = atoi(priorityString);
406 	fArchitecture = architecture;
407 
408 	return B_OK;
409 }
410 
411 
412 }	// namespace BPackageKit
413