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