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