xref: /haiku/src/kits/package/RepositoryInfo.cpp (revision 6953cef14ef864cccdbab6218585475cef7f8d68)
1 /*
2  * Copyright 2011-2018, 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 	// Field in the archive is named "url" for backward compatility reasons.
96 	// We can change this when everyone has updated to a version of Haiku
97 	// with support for reading the "identifier" field.
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 	result = data->AddString(kSummaryField, fSummary);
103 	if (result != 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 	if ((result = data->FindString(kIdentifierField, &fIdentifier)) != B_OK) {
286 		// Handle the "url" field as well (it is still the one we generate).
287 		// Later on when everyone is using this code we can switch the writing
288 		// side to use the "identifier" field with its correct name.
289 		if ((result = data->FindString(kURLField, &fIdentifier)) != B_OK)
290 			return result;
291 	}
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 	result = data->FindUInt8(kArchitectureField, (uint8*)&fArchitecture);
299 	if (result != B_OK)
300 		return result;
301 	if (fArchitecture == B_PACKAGE_ARCHITECTURE_ANY)
302 		return B_BAD_DATA;
303 
304 	// Old packages had no base-url field, the "url" field acted both as an
305 	// identifier and locator for the repository.
306 	data->FindString(kBaseURLField, &fBaseURL);
307 	if (fBaseURL.Length() == 0) {
308 		fBaseURL = fIdentifier;
309 		// In that case make sure the identifier is indeed an http URL
310 		// (in the new format, the protocol is not required to be http anymore)
311 		if (!fBaseURL.StartsWith("http"))
312 			return B_BAD_DATA;
313 	}
314 
315 	const char* licenseName;
316 	const char* licenseText;
317 	for (int i = 0;
318 		data->FindString(kLicenseNameField, i, &licenseName) == B_OK
319 			&& data->FindString(kLicenseTextField, i, &licenseText) == B_OK;
320 		++i) {
321 		if (!fLicenseNames.Add(licenseName) || !fLicenseTexts.Add(licenseText))
322 			return B_NO_MEMORY;
323 	}
324 
325 	return B_OK;
326 }
327 
328 
329 status_t
330 BRepositoryInfo::_SetTo(const BEntry& entry)
331 {
332 	BFile file(&entry, B_READ_ONLY);
333 	status_t result = file.InitCheck();
334 	if (result != B_OK)
335 		return result;
336 
337 	off_t size;
338 	if ((result = file.GetSize(&size)) != B_OK)
339 		return result;
340 
341 	BString configString;
342 	char* buffer = configString.LockBuffer(size);
343 	if (buffer == NULL)
344 		return B_NO_MEMORY;
345 
346 	if ((result = file.Read(buffer, size)) < size) {
347 		configString.UnlockBuffer(0);
348 		return (result >= 0) ? B_IO_ERROR : result;
349 	}
350 
351 	buffer[size] = '\0';
352 	configString.UnlockBuffer(size);
353 
354 	void* settingsHandle = parse_driver_settings_string(configString.String());
355 	if (settingsHandle == NULL)
356 		return B_BAD_DATA;
357 	CObjectDeleter<void, status_t> settingsHandleDeleter(settingsHandle,
358 		&unload_driver_settings);
359 
360 	const char* name = get_driver_parameter(settingsHandle, "name", NULL, NULL);
361 	const char* identifier = get_driver_parameter(settingsHandle, "identifier", NULL, NULL);
362 	// Also handle the old name if the new one isn't found
363 	if (identifier == NULL || *identifier == '\0')
364 		identifier = get_driver_parameter(settingsHandle, "url", NULL, NULL);
365 	const char* baseUrl = get_driver_parameter(settingsHandle, "baseurl", NULL, NULL);
366 	const char* vendor
367 		= get_driver_parameter(settingsHandle, "vendor", NULL, NULL);
368 	const char* summary
369 		= get_driver_parameter(settingsHandle, "summary", NULL, NULL);
370 	const char* priorityString
371 		= get_driver_parameter(settingsHandle, "priority", NULL, NULL);
372 	const char* architectureString
373 		= get_driver_parameter(settingsHandle, "architecture", NULL, NULL);
374 
375 	if (name == NULL || *name == '\0'
376 		|| identifier == NULL || *identifier == '\0'
377 		|| vendor == NULL || *vendor == '\0'
378 		|| summary == NULL || *summary == '\0'
379 		|| priorityString == NULL || *priorityString == '\0'
380 		|| architectureString == NULL || *architectureString == '\0') {
381 		return B_BAD_DATA;
382 	}
383 
384 	BPackageArchitecture architecture;
385 	if (BPackageInfo::GetArchitectureByName(architectureString, architecture)
386 			!= B_OK || architecture == B_PACKAGE_ARCHITECTURE_ANY) {
387 		return B_BAD_DATA;
388 	}
389 
390 	fName = name;
391 	fBaseURL = baseUrl;
392 	fIdentifier = identifier;
393 	fVendor = vendor;
394 	fSummary = summary;
395 	fPriority = atoi(priorityString);
396 	fArchitecture = architecture;
397 
398 	return B_OK;
399 }
400 
401 
402 }	// namespace BPackageKit
403