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