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 26namespace BPackageKit { 27 28 29const uint8 BRepositoryInfo::kDefaultPriority = 50; 30 31const char* const BRepositoryInfo::kNameField = "name"; 32const char* const BRepositoryInfo::kURLField = "url"; 33const char* const BRepositoryInfo::kIdentifierField = "identifier"; 34const char* const BRepositoryInfo::kBaseURLField = "baseUrl"; 35const char* const BRepositoryInfo::kVendorField = "vendor"; 36const char* const BRepositoryInfo::kSummaryField = "summary"; 37const char* const BRepositoryInfo::kPriorityField = "priority"; 38const char* const BRepositoryInfo::kArchitectureField = "architecture"; 39const char* const BRepositoryInfo::kLicenseNameField = "licenseName"; 40const char* const BRepositoryInfo::kLicenseTextField = "licenseText"; 41 42 43BRepositoryInfo::BRepositoryInfo() 44 : 45 fInitStatus(B_NO_INIT), 46 fPriority(kDefaultPriority), 47 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT) 48{ 49} 50 51 52BRepositoryInfo::BRepositoryInfo(BMessage* data) 53 : 54 inherited(data), 55 fLicenseTexts(5) 56{ 57 fInitStatus = _SetTo(data); 58} 59 60 61BRepositoryInfo::BRepositoryInfo(const BEntry& entry) 62{ 63 fInitStatus = _SetTo(entry); 64} 65 66 67BRepositoryInfo::~BRepositoryInfo() 68{ 69} 70 71 72/*static*/ BRepositoryInfo* 73BRepositoryInfo::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 82status_t 83BRepositoryInfo::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 124status_t 125BRepositoryInfo::InitCheck() const 126{ 127 return fInitStatus; 128} 129 130 131status_t 132BRepositoryInfo::SetTo(const BMessage* data) 133{ 134 return fInitStatus = _SetTo(data); 135} 136 137 138status_t 139BRepositoryInfo::SetTo(const BEntry& entry) 140{ 141 return fInitStatus = _SetTo(entry); 142} 143 144 145const BString& 146BRepositoryInfo::Name() const 147{ 148 return fName; 149} 150 151 152const BString& 153BRepositoryInfo::BaseURL() const 154{ 155 return fBaseURL; 156} 157 158 159const BString& 160BRepositoryInfo::Identifier() const 161{ 162 return fIdentifier; 163} 164 165 166const BString& 167BRepositoryInfo::Vendor() const 168{ 169 return fVendor; 170} 171 172 173const BString& 174BRepositoryInfo::Summary() const 175{ 176 return fSummary; 177} 178 179 180uint8 181BRepositoryInfo::Priority() const 182{ 183 return fPriority; 184} 185 186 187BPackageArchitecture 188BRepositoryInfo::Architecture() const 189{ 190 return fArchitecture; 191} 192 193 194const BStringList& 195BRepositoryInfo::LicenseNames() const 196{ 197 return fLicenseNames; 198} 199 200 201const BStringList& 202BRepositoryInfo::LicenseTexts() const 203{ 204 return fLicenseTexts; 205} 206 207 208void 209BRepositoryInfo::SetName(const BString& name) 210{ 211 fName = name; 212} 213 214 215void 216BRepositoryInfo::SetIdentifier(const BString& identifier) 217{ 218 fIdentifier = identifier; 219} 220 221 222void 223BRepositoryInfo::SetBaseURL(const BString& url) 224{ 225 fBaseURL = url; 226} 227 228 229void 230BRepositoryInfo::SetVendor(const BString& vendor) 231{ 232 fVendor = vendor; 233} 234 235 236void 237BRepositoryInfo::SetSummary(const BString& summary) 238{ 239 fSummary = summary; 240} 241 242 243void 244BRepositoryInfo::SetPriority(uint8 priority) 245{ 246 fPriority = priority; 247} 248 249 250void 251BRepositoryInfo::SetArchitecture(BPackageArchitecture architecture) 252{ 253 fArchitecture = architecture; 254} 255 256 257status_t 258BRepositoryInfo::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 268void 269BRepositoryInfo::ClearLicenses() 270{ 271 fLicenseNames.MakeEmpty(); 272 fLicenseTexts.MakeEmpty(); 273} 274 275 276status_t 277BRepositoryInfo::_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 336status_t 337BRepositoryInfo::_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