1 /* 2 * Copyright 2002-2007, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold, bonefish@users.sf.net 7 */ 8 9 10 #include <new> 11 #include <set> 12 #include <stdlib.h> 13 #include <string> 14 15 #include <AppFileInfo.h> 16 #include <Bitmap.h> 17 #include <File.h> 18 #include <fs_attr.h> 19 #include <IconUtils.h> 20 #include <MimeType.h> 21 #include <RegistrarDefs.h> 22 #include <Resources.h> 23 #include <Roster.h> 24 #include <String.h> 25 26 using namespace std; 27 28 // attributes 29 static const char *kTypeAttribute = "BEOS:TYPE"; 30 static const char *kSignatureAttribute = "BEOS:APP_SIG"; 31 static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS"; 32 static const char *kSupportedTypesAttribute = "BEOS:FILE_TYPES"; 33 static const char *kVersionInfoAttribute = "BEOS:APP_VERSION"; 34 static const char *kMiniIconAttribute = "BEOS:M:"; 35 static const char *kLargeIconAttribute = "BEOS:L:"; 36 static const char *kIconAttribute = "BEOS:"; 37 static const char *kStandardIconType = "STD_ICON"; 38 static const char *kIconType = "ICON"; 39 static const char *kCatalogEntryAttribute = "SYS:NAME"; 40 41 // resource IDs 42 static const int32 kTypeResourceID = 2; 43 static const int32 kSignatureResourceID = 1; 44 static const int32 kAppFlagsResourceID = 1; 45 static const int32 kSupportedTypesResourceID = 1; 46 static const int32 kMiniIconResourceID = 101; 47 static const int32 kLargeIconResourceID = 101; 48 static const int32 kIconResourceID = 101; 49 static const int32 kVersionInfoResourceID = 1; 50 static const int32 kMiniIconForTypeResourceID = 0; 51 static const int32 kLargeIconForTypeResourceID = 0; 52 static const int32 kIconForTypeResourceID = 0; 53 static const int32 kCatalogEntryResourceID = 1; 54 55 // type codes 56 enum { 57 B_APP_FLAGS_TYPE = 'APPF', 58 B_VERSION_INFO_TYPE = 'APPV', 59 }; 60 61 // R5 also exports these (Tracker is using them): 62 // (maybe we better want to drop them silently and declare 63 // the above in a public Haiku header - and use that one in 64 // Tracker when compiled for Haiku) 65 extern const uint32 MINI_ICON_TYPE, LARGE_ICON_TYPE; 66 const uint32 MINI_ICON_TYPE = 'MICN'; 67 const uint32 LARGE_ICON_TYPE = 'ICON'; 68 69 // debugging 70 //#define DBG(x) x 71 #define DBG(x) 72 #define OUT printf 73 74 // constructor 75 /*! \brief Creates an uninitialized BAppFileInfo object. 76 */ 77 BAppFileInfo::BAppFileInfo() 78 : fResources(NULL), 79 fWhere(B_USE_BOTH_LOCATIONS) 80 { 81 } 82 83 // constructor 84 /*! \brief Creates an BAppFileInfo object and initializes it to the supplied 85 file. 86 87 The caller retains ownership of the supplied BFile object. It must not 88 be deleted during the life time of the BAppFileInfo. It is not deleted 89 when the BAppFileInfo is destroyed. 90 91 \param file The file the object shall be initialized to. 92 */ 93 BAppFileInfo::BAppFileInfo(BFile *file) 94 : fResources(NULL), 95 fWhere(B_USE_BOTH_LOCATIONS) 96 { 97 SetTo(file); 98 } 99 100 // destructor 101 /*! \brief Frees all resources associated with this object. 102 103 The BFile the object is set to is not deleted. 104 */ 105 BAppFileInfo::~BAppFileInfo() 106 { 107 delete fResources; 108 } 109 110 // SetTo 111 /*! \brief Initializes the BAppFileInfo to the supplied file. 112 113 The caller retains ownership of the supplied BFile object. It must not 114 be deleted during the life time of the BAppFileInfo. It is not deleted 115 when the BAppFileInfo is destroyed. 116 117 \param file The file the object shall be initialized to. 118 119 \return 120 - \c B_OK: Everything went fine. 121 - \c B_BAD_VALUE: \c NULL \a file or \a file is not properly initialized. 122 */ 123 status_t 124 BAppFileInfo::SetTo(BFile *file) 125 { 126 // unset the old file 127 BNodeInfo::SetTo(NULL); 128 if (fResources) { 129 delete fResources; 130 fResources = NULL; 131 } 132 133 // check param 134 status_t error = (file && file->InitCheck() == B_OK ? B_OK : B_BAD_VALUE); 135 136 info_location where = B_USE_BOTH_LOCATIONS; 137 138 // create resources 139 if (error == B_OK) { 140 fResources = new(nothrow) BResources(); 141 if (fResources) { 142 error = fResources->SetTo(file); 143 if (error != B_OK) { 144 // no resources - this is no critical error, we'll just use 145 // attributes only, then 146 where = B_USE_ATTRIBUTES; 147 error = B_OK; 148 } 149 } else 150 error = B_NO_MEMORY; 151 } 152 153 // set node info 154 if (error == B_OK) 155 error = BNodeInfo::SetTo(file); 156 157 if (error != B_OK || (where & B_USE_RESOURCES) == 0) { 158 delete fResources; 159 fResources = NULL; 160 } 161 162 // clean up on error 163 if (error != B_OK) { 164 if (InitCheck() == B_OK) 165 BNodeInfo::SetTo(NULL); 166 } 167 168 // set data location 169 if (error == B_OK) 170 SetInfoLocation(where); 171 172 // set error 173 fCStatus = error; 174 return error; 175 } 176 177 // GetType 178 /*! \brief Gets the file's MIME type. 179 180 \param type A pointer to a pre-allocated character buffer of size 181 \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the 182 file shall be written. 183 \return 184 - \c B_OK: Everything went fine. 185 - \c B_NO_INIT: The object is not properly initialized. 186 - \c B_BAD_VALUE: \c NULL \a type or the type string stored in the 187 attribute/resources is longer than \c B_MIME_TYPE_LENGTH. 188 - \c B_BAD_TYPE: The attribute/resources the type string is stored in have 189 the wrong type. 190 - \c B_ENTRY_NOT_FOUND: No type is set on the file. 191 - other error codes 192 */ 193 status_t 194 BAppFileInfo::GetType(char *type) const 195 { 196 // check param and initialization 197 status_t error = (type ? B_OK : B_BAD_VALUE); 198 if (error == B_OK && InitCheck() != B_OK) 199 error = B_NO_INIT; 200 // read the data 201 size_t read = 0; 202 if (error == B_OK) { 203 error = _ReadData(kTypeAttribute, kTypeResourceID, B_MIME_STRING_TYPE, 204 type, B_MIME_TYPE_LENGTH, read); 205 } 206 // check the read data -- null terminate the string 207 if (error == B_OK && type[read - 1] != '\0') { 208 if (read == B_MIME_TYPE_LENGTH) 209 error = B_ERROR; 210 else 211 type[read] = '\0'; 212 } 213 return error; 214 } 215 216 // SetType 217 /*! \brief Sets the file's MIME type. 218 219 If \a type is \c NULL the file's MIME type is unset. 220 221 \param type The MIME type to be assigned to the file. Must not be longer 222 than \c B_MIME_TYPE_LENGTH (including the terminating null). 223 May be \c NULL. 224 \return 225 - \c B_OK: Everything went fine. 226 - \c B_NO_INIT: The object is not properly initialized. 227 - \c B_BAD_VALUE: \a type is longer than \c B_MIME_TYPE_LENGTH. 228 - other error codes 229 */ 230 status_t 231 BAppFileInfo::SetType(const char *type) 232 { 233 // check initialization 234 status_t error = B_OK; 235 if (error == B_OK && InitCheck() != B_OK) 236 error = B_NO_INIT; 237 if (error == B_OK) { 238 if (type) { 239 // check param 240 size_t typeLen = strlen(type); 241 if (error == B_OK && typeLen >= B_MIME_TYPE_LENGTH) 242 error = B_BAD_VALUE; 243 // write the data 244 if (error == B_OK) { 245 error = _WriteData(kTypeAttribute, kTypeResourceID, 246 B_MIME_STRING_TYPE, type, typeLen + 1); 247 } 248 } else 249 error = _RemoveData(kTypeAttribute, B_MIME_STRING_TYPE); 250 } 251 return error; 252 } 253 254 // GetSignature 255 /*! \brief Gets the file's application signature. 256 257 \param signature A pointer to a pre-allocated character buffer of size 258 \c B_MIME_TYPE_LENGTH or larger into which the application 259 signature of the file shall be written. 260 \return 261 - \c B_OK: Everything went fine. 262 - \c B_NO_INIT: The object is not properly initialized. 263 - \c B_BAD_VALUE: \c NULL \a signature or the signature stored in the 264 attribute/resources is longer than \c B_MIME_TYPE_LENGTH. 265 - \c B_BAD_TYPE: The attribute/resources the signature is stored in have 266 the wrong type. 267 - \c B_ENTRY_NOT_FOUND: No signature is set on the file. 268 - other error codes 269 */ 270 status_t 271 BAppFileInfo::GetSignature(char *signature) const 272 { 273 // check param and initialization 274 status_t error = (signature ? B_OK : B_BAD_VALUE); 275 if (error == B_OK && InitCheck() != B_OK) 276 error = B_NO_INIT; 277 // read the data 278 size_t read = 0; 279 if (error == B_OK) { 280 error = _ReadData(kSignatureAttribute, kSignatureResourceID, 281 B_MIME_STRING_TYPE, signature, B_MIME_TYPE_LENGTH, 282 read); 283 } 284 // check the read data -- null terminate the string 285 if (error == B_OK && signature[read - 1] != '\0') { 286 if (read == B_MIME_TYPE_LENGTH) 287 error = B_ERROR; 288 else 289 signature[read] = '\0'; 290 } 291 return error; 292 } 293 294 // SetSignature 295 /*! \brief Sets the file's application signature. 296 297 If \a signature is \c NULL the file's application signature is unset. 298 299 \param signature The application signature to be assigned to the file. 300 Must not be longer than \c B_MIME_TYPE_LENGTH (including the 301 terminating null). May be \c NULL. 302 \return 303 - \c B_OK: Everything went fine. 304 - \c B_NO_INIT: The object is not properly initialized. 305 - \c B_BAD_VALUE: \a signature is longer than \c B_MIME_TYPE_LENGTH. 306 - other error codes 307 */ 308 status_t 309 BAppFileInfo::SetSignature(const char *signature) 310 { 311 // check initialization 312 status_t error = B_OK; 313 if (error == B_OK && InitCheck() != B_OK) 314 error = B_NO_INIT; 315 if (error == B_OK) { 316 if (signature) { 317 // check param 318 size_t signatureLen = strlen(signature); 319 if (error == B_OK && signatureLen >= B_MIME_TYPE_LENGTH) 320 error = B_BAD_VALUE; 321 // write the data 322 if (error == B_OK) { 323 error = _WriteData(kSignatureAttribute, kSignatureResourceID, 324 B_MIME_STRING_TYPE, signature, 325 signatureLen + 1); 326 } 327 } else 328 error = _RemoveData(kSignatureAttribute, B_MIME_STRING_TYPE); 329 } 330 return error; 331 } 332 333 334 // GetCatalogEntry 335 /*! \brief Gets the file's catalog entry. (localization) 336 337 \param catalogEntry A pointer to a pre-allocated character buffer of size 338 \c B_MIME_TYPE_LENGTH * 3 or larger into which the catalog entry 339 of the file shall be written. 340 \return 341 - \c B_OK: Everything went fine. 342 - \c B_NO_INIT: The object is not properly initialized. 343 - \c B_BAD_VALUE: \c NULL \a catalogEntry or the entry stored in the 344 attribute/resources is longer than \c B_MIME_TYPE_LENGTH * 3. 345 - \c B_BAD_TYPE: The attribute/resources the entry is stored in have 346 the wrong type. 347 - \c B_ENTRY_NOT_FOUND: No catalog entry is set on the file. 348 - other error codes 349 */ 350 status_t 351 BAppFileInfo::GetCatalogEntry(char *catalogEntry) const 352 { 353 if (catalogEntry == NULL) 354 return B_BAD_VALUE; 355 356 if (InitCheck() != B_OK) 357 return B_NO_INIT; 358 359 size_t read = 0; 360 status_t error = _ReadData(kCatalogEntryAttribute, kCatalogEntryResourceID, 361 B_STRING_TYPE, catalogEntry, B_MIME_TYPE_LENGTH * 3, read); 362 363 if (error != B_OK) 364 return error; 365 366 if (read >= B_MIME_TYPE_LENGTH * 3) 367 return B_ERROR; 368 369 catalogEntry[read] = '\0'; 370 371 return B_OK; 372 } 373 374 375 // SetCatalogEntry 376 /*! \brief Sets the file's catalog entry. (localization) 377 378 If \a catalogEntry is \c NULL the file's catalog entry is unset. 379 380 \param catalogEntry The catalog entry to be assigned to the file. 381 Of the form "x-vnd.Haiku-app:context:name". 382 Must not be longer than \c B_MIME_TYPE_LENGTH * 3 383 (including the terminating null). May be \c NULL. 384 \return 385 - \c B_OK: Everything went fine. 386 - \c B_NO_INIT: The object is not properly initialized. 387 - \c B_BAD_VALUE: \a catalogEntry is longer than \c B_MIME_TYPE_LENGTH * 3. 388 - other error codes 389 */ 390 status_t 391 BAppFileInfo::SetCatalogEntry(const char *catalogEntry) 392 { 393 if (InitCheck() != B_OK) 394 return B_NO_INIT; 395 396 if (catalogEntry == NULL) 397 return _RemoveData(kCatalogEntryAttribute, B_STRING_TYPE); 398 399 size_t nameLength = strlen(catalogEntry); 400 if (nameLength > B_MIME_TYPE_LENGTH * 3) 401 return B_BAD_VALUE; 402 403 return _WriteData(kCatalogEntryAttribute, kCatalogEntryResourceID, 404 B_STRING_TYPE, catalogEntry, nameLength + 1); 405 } 406 407 408 // GetAppFlags 409 /*! \brief Gets the file's application flags. 410 411 \param flags A pointer to a pre-allocated uint32 into which the application 412 flags of the file shall be written. 413 \return 414 - \c B_OK: Everything went fine. 415 - \c B_NO_INIT: The object is not properly initialized. 416 - \c B_BAD_VALUE: \c NULL \a flags. 417 - \c B_BAD_TYPE: The attribute/resources the flags are stored in have 418 the wrong type. 419 - \c B_ENTRY_NOT_FOUND: No application flags are set on the file. 420 - other error codes 421 */ 422 status_t 423 BAppFileInfo::GetAppFlags(uint32 *flags) const 424 { 425 // check param and initialization 426 status_t error = (flags ? B_OK : B_BAD_VALUE); 427 if (error == B_OK && InitCheck() != B_OK) 428 error = B_NO_INIT; 429 // read the data 430 size_t read = 0; 431 if (error == B_OK) { 432 error = _ReadData(kAppFlagsAttribute, kAppFlagsResourceID, 433 B_APP_FLAGS_TYPE, flags, sizeof(uint32), 434 read); 435 } 436 // check the read data 437 if (error == B_OK && read != sizeof(uint32)) 438 error = B_ERROR; 439 return error; 440 } 441 442 // SetAppFlags 443 /*! \brief Sets the file's application flags. 444 \param flags The application flags to be assigned to the file. 445 \return 446 - \c B_OK: Everything went fine. 447 - \c B_NO_INIT: The object is not properly initialized. 448 - other error codes 449 */ 450 status_t 451 BAppFileInfo::SetAppFlags(uint32 flags) 452 { 453 // check initialization 454 status_t error = B_OK; 455 if (error == B_OK && InitCheck() != B_OK) 456 error = B_NO_INIT; 457 if (error == B_OK) { 458 // write the data 459 error = _WriteData(kAppFlagsAttribute, kAppFlagsResourceID, 460 B_APP_FLAGS_TYPE, &flags, sizeof(uint32)); 461 } 462 return error; 463 } 464 465 // RemoveAppFlags 466 /*! \brief Removes the file's application flags. 467 \return 468 - \c B_OK: Everything went fine. 469 - \c B_NO_INIT: The object is not properly initialized. 470 - other error codes 471 */ 472 status_t 473 BAppFileInfo::RemoveAppFlags() 474 { 475 // check initialization 476 status_t error = B_OK; 477 if (error == B_OK && InitCheck() != B_OK) 478 error = B_NO_INIT; 479 if (error == B_OK) { 480 // remove the data 481 error = _RemoveData(kAppFlagsAttribute, B_APP_FLAGS_TYPE); 482 } 483 return error; 484 } 485 486 // GetSupportedTypes 487 /*! \brief Gets the MIME types supported by the application. 488 489 The supported MIME types are added to a field "types" of type 490 \c B_STRING_TYPE in \a types. 491 492 \param types A pointer to a pre-allocated BMessage into which the 493 MIME types supported by the appplication shall be written. 494 \return 495 - \c B_OK: Everything went fine. 496 - \c B_NO_INIT: The object is not properly initialized. 497 - \c B_BAD_VALUE: \c NULL \a types. 498 - \c B_BAD_TYPE: The attribute/resources the supported types are stored in 499 have the wrong type. 500 - \c B_ENTRY_NOT_FOUND: No supported types are set on the file. 501 - other error codes 502 */ 503 status_t 504 BAppFileInfo::GetSupportedTypes(BMessage *types) const 505 { 506 // check param and initialization 507 status_t error = (types ? B_OK : B_BAD_VALUE); 508 if (error == B_OK && InitCheck() != B_OK) 509 error = B_NO_INIT; 510 // read the data 511 size_t read = 0; 512 void *buffer = NULL; 513 if (error == B_OK) { 514 error = _ReadData(kSupportedTypesAttribute, kSupportedTypesResourceID, 515 B_MESSAGE_TYPE, NULL, 0, read, &buffer); 516 } 517 // unflatten the buffer 518 if (error == B_OK) 519 error = types->Unflatten((const char*)buffer); 520 // clean up 521 free(buffer); 522 return error; 523 } 524 525 // SetSupportedTypes 526 /*! \brief Sets the MIME types supported by the application. 527 528 If \a types is \c NULL the application's supported types are unset. 529 530 The supported MIME types must be stored in a field "types" of type 531 \c B_STRING_TYPE in \a types. 532 533 The method informs the registrar about this news. 534 For each supported type the result of BMimeType::GetSupportingApps() will 535 afterwards include the signature of this application. That is, the 536 application file needs to have a signature set. 537 538 \a syncAll specifies whether the not longer supported types shall be 539 updated as well, i.e. whether this application shall be remove from the 540 lists of supporting applications. 541 542 \param types The supported types to be assigned to the file. 543 May be \c NULL. 544 \param syncAll \c true to also synchronize the not longer supported 545 types, \c false otherwise. 546 \return 547 - \c B_OK: Everything went fine. 548 - \c B_NO_INIT: The object is not properly initialized. 549 - other error codes 550 */ 551 status_t 552 BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll) 553 { 554 // check initialization 555 status_t error = B_OK; 556 if (error == B_OK && InitCheck() != B_OK) 557 error = B_NO_INIT; 558 BMimeType mimeType; 559 if (error == B_OK) 560 error = GetMetaMime(&mimeType); 561 if (error == B_OK || error == B_ENTRY_NOT_FOUND) { 562 error = B_OK; 563 if (types) { 564 // check param -- supported types must be valid 565 const char *type; 566 for (int32 i = 0; 567 error == B_OK && types->FindString("types", i, &type) == B_OK; 568 i++) { 569 if (!BMimeType::IsValid(type)) 570 error = B_BAD_VALUE; 571 } 572 // get flattened size 573 ssize_t size = 0; 574 if (error == B_OK) { 575 size = types->FlattenedSize(); 576 if (size < 0) 577 error = size; 578 } 579 // allocate a buffer for the flattened data 580 char *buffer = NULL; 581 if (error == B_OK) { 582 buffer = new(nothrow) char[size]; 583 if (!buffer) 584 error = B_NO_MEMORY; 585 } 586 // flatten the message 587 if (error == B_OK) 588 error = types->Flatten(buffer, size); 589 // write the data 590 if (error == B_OK) { 591 error = _WriteData(kSupportedTypesAttribute, 592 kSupportedTypesResourceID, B_MESSAGE_TYPE, 593 buffer, size); 594 } 595 // clean up 596 delete[] buffer; 597 } else 598 error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE); 599 // update the MIME database, if the app signature is installed 600 if (error == B_OK && mimeType.IsInstalled()) 601 error = mimeType.SetSupportedTypes(types, syncAll); 602 } 603 return error; 604 } 605 606 // SetSupportedTypes 607 /*! \brief Sets the MIME types supported by the application. 608 609 This method is a short-hand for SetSupportedTypes(types, false). 610 \see SetSupportedType(const BMessage*, bool) for detailed information. 611 612 \param types The supported types to be assigned to the file. 613 May be \c NULL. 614 \return 615 - \c B_OK: Everything went fine. 616 - \c B_NO_INIT: The object is not properly initialized. 617 - other error codes 618 */ 619 status_t 620 BAppFileInfo::SetSupportedTypes(const BMessage *types) 621 { 622 return SetSupportedTypes(types, false); 623 } 624 625 // IsSupportedType 626 /*! \brief Returns whether the application supports the supplied MIME type. 627 628 If the application supports the wildcard type "application/octet-stream" 629 any this method returns \c true for any MIME type. 630 631 \param type The MIME type in question. 632 \return \c true, if \a type is a valid MIME type and it is supported by 633 the application, \c false otherwise. 634 */ 635 bool 636 BAppFileInfo::IsSupportedType(const char *type) const 637 { 638 status_t error = (type ? B_OK : B_BAD_VALUE); 639 // get the supported types 640 BMessage types; 641 if (error == B_OK) 642 error = GetSupportedTypes(&types); 643 // turn type into a BMimeType 644 BMimeType mimeType; 645 if (error == B_OK) 646 error = mimeType.SetTo(type); 647 // iterate through the supported types 648 bool found = false; 649 if (error == B_OK) { 650 const char *supportedType; 651 for (int32 i = 0; 652 !found && types.FindString("types", i, &supportedType) == B_OK; 653 i++) { 654 found = !strcmp(supportedType, "application/octet-stream") 655 || BMimeType(supportedType).Contains(&mimeType); 656 } 657 } 658 return found; 659 } 660 661 // Supports 662 /*! \brief Returns whether the application supports the supplied MIME type 663 explicitly. 664 665 Unlike IsSupportedType(), this method returns \c true, only if the type 666 is explicitly supported, regardless of whether it supports 667 "application/octet-stream". 668 669 \param type The MIME type in question. 670 \return \c true, if \a type is a valid MIME type and it is explicitly 671 supported by the application, \c false otherwise. 672 */ 673 bool 674 BAppFileInfo::Supports(BMimeType *type) const 675 { 676 status_t error = (type && type->InitCheck() == B_OK ? B_OK : B_BAD_VALUE); 677 // get the supported types 678 BMessage types; 679 if (error == B_OK) 680 error = GetSupportedTypes(&types); 681 // iterate through the supported types 682 bool found = false; 683 if (error == B_OK) { 684 const char *supportedType; 685 for (int32 i = 0; 686 !found && types.FindString("types", i, &supportedType) == B_OK; 687 i++) { 688 found = BMimeType(supportedType).Contains(type); 689 } 690 } 691 return found; 692 } 693 694 // GetIcon 695 /*! \brief Gets the file's icon. 696 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 697 to store the requested icon (16x16 for the mini and 32x32 for the 698 large icon). 699 \param which Specifies the size of the icon to be retrieved: 700 \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon. 701 \return 702 - \c B_OK: Everything went fine. 703 - \c B_NO_INIT: The object is not properly initialized. 704 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a which or bitmap 705 dimensions (\a icon) and icon size (\a which) do not match. 706 - other error codes 707 */ 708 status_t 709 BAppFileInfo::GetIcon(BBitmap *icon, icon_size which) const 710 { 711 return GetIconForType(NULL, icon, which); 712 } 713 714 // GetIcon 715 /*! \brief Gets the file's icon. 716 \param data The pointer in which the flat icon data will be returned. 717 \param size The pointer in which the size of the data found will be returned. 718 \return 719 - \c B_OK: Everything went fine. 720 - \c B_NO_INIT: The object is not properly initialized. 721 - \c B_BAD_VALUE: \c NULL \a data or \c NULL size. 722 - other error codes 723 */ 724 status_t 725 BAppFileInfo::GetIcon(uint8** data, size_t* size) const 726 { 727 return GetIconForType(NULL, data, size); 728 } 729 730 // SetIcon 731 /*! \brief Sets the file's icon. 732 733 If \a icon is \c NULL the file's icon is unset. 734 735 \param icon A pointer to the BBitmap containing the icon to be set. 736 May be \c NULL. 737 \param which Specifies the size of the icon to be set: \c B_MINI_ICON 738 for the mini and \c B_LARGE_ICON for the large icon. 739 \return 740 - \c B_OK: Everything went fine. 741 - \c B_NO_INIT: The object is not properly initialized. 742 - \c B_BAD_VALUE: Unknown icon size \a which or bitmap dimensions (\a icon) 743 and icon size (\a which) do not match. 744 - other error codes 745 */ 746 status_t 747 BAppFileInfo::SetIcon(const BBitmap *icon, icon_size which) 748 { 749 return SetIconForType(NULL, icon, which); 750 } 751 752 // SetIcon 753 /*! \brief Sets the file's icon. 754 755 If \a icon is \c NULL the file's icon is unset. 756 757 \param data A pointer to the data buffer containing the vector icon 758 to be set. May be \c NULL. 759 \param size Specifies the size of buffer pointed to by \a data. 760 \return 761 - \c B_OK: Everything went fine. 762 - \c B_NO_INIT: The object is not properly initialized. 763 - \c B_BAD_VALUE: \c NULL data. 764 - other error codes 765 */ 766 status_t 767 BAppFileInfo::SetIcon(const uint8* data, size_t size) 768 { 769 return SetIconForType(NULL, data, size); 770 } 771 772 // GetVersionInfo 773 /*! \brief Gets the file's version info. 774 \param info A pointer to a pre-allocated version_info structure into which 775 the version info should be written. 776 \param kind Specifies the kind of the version info to be retrieved: 777 \c B_APP_VERSION_KIND for the application's version info and 778 \c B_SYSTEM_VERSION_KIND for the suite's info the application 779 belongs to. 780 \return 781 - \c B_OK: Everything went fine. 782 - \c B_NO_INIT: The object is not properly initialized. 783 - \c B_BAD_VALUE: \c NULL \a info. 784 - other error codes 785 */ 786 status_t 787 BAppFileInfo::GetVersionInfo(version_info *info, version_kind kind) const 788 { 789 // check params and initialization 790 if (!info) 791 return B_BAD_VALUE; 792 793 int32 index = 0; 794 switch (kind) { 795 case B_APP_VERSION_KIND: 796 index = 0; 797 break; 798 case B_SYSTEM_VERSION_KIND: 799 index = 1; 800 break; 801 default: 802 return B_BAD_VALUE; 803 } 804 805 if (InitCheck() != B_OK) 806 return B_NO_INIT; 807 808 // read the data 809 size_t read = 0; 810 version_info infos[2]; 811 status_t error = _ReadData(kVersionInfoAttribute, kVersionInfoResourceID, 812 B_VERSION_INFO_TYPE, infos, 2 * sizeof(version_info), read); 813 if (error != B_OK) 814 return error; 815 816 // check the read data 817 if (read == sizeof(version_info)) { 818 // only the app version info is there -- return a cleared system info 819 if (index == 0) 820 *info = infos[index]; 821 else if (index == 1) 822 memset(info, 0, sizeof(version_info)); 823 } else if (read == 2 * sizeof(version_info)) { 824 *info = infos[index]; 825 } else 826 return B_ERROR; 827 828 // return result 829 return B_OK; 830 } 831 832 // SetVersionInfo 833 /*! \brief Sets the file's version info. 834 835 If \a info is \c NULL the file's version info is unset. 836 837 \param info The version info to be set. May be \c NULL. 838 \param kind Specifies kind of version info to be set: 839 \c B_APP_VERSION_KIND for the application's version info and 840 \c B_SYSTEM_VERSION_KIND for the suite's info the application 841 belongs to. 842 \return 843 - \c B_OK: Everything went fine. 844 - \c B_NO_INIT: The object is not properly initialized. 845 - other error codes 846 */ 847 status_t 848 BAppFileInfo::SetVersionInfo(const version_info *info, version_kind kind) 849 { 850 // check initialization 851 status_t error = B_OK; 852 if (error == B_OK && InitCheck() != B_OK) 853 error = B_NO_INIT; 854 if (error == B_OK) { 855 if (info) { 856 // check param 857 int32 index = 0; 858 if (error == B_OK) { 859 switch (kind) { 860 case B_APP_VERSION_KIND: 861 index = 0; 862 break; 863 case B_SYSTEM_VERSION_KIND: 864 index = 1; 865 break; 866 default: 867 error = B_BAD_VALUE; 868 break; 869 } 870 } 871 // read both infos 872 version_info infos[2]; 873 if (error == B_OK) { 874 size_t read; 875 if (_ReadData(kVersionInfoAttribute, kVersionInfoResourceID, 876 B_VERSION_INFO_TYPE, infos, 2 * sizeof(version_info), 877 read) == B_OK) { 878 // clear the part that hasn't been read 879 if (read < sizeof(infos)) 880 memset((char*)infos + read, 0, sizeof(infos) - read); 881 } else { 882 // failed to read -- clear 883 memset(infos, 0, sizeof(infos)); 884 } 885 } 886 infos[index] = *info; 887 // write the data 888 if (error == B_OK) { 889 error = _WriteData(kVersionInfoAttribute, 890 kVersionInfoResourceID, 891 B_VERSION_INFO_TYPE, infos, 892 2 * sizeof(version_info)); 893 } 894 } else 895 error = _RemoveData(kVersionInfoAttribute, B_VERSION_INFO_TYPE); 896 } 897 return error; 898 } 899 900 // GetIconForType 901 /*! \brief Gets the icon the application provides for a given MIME type. 902 903 If \a type is \c NULL, the application's icon is retrieved. 904 905 \param type The MIME type in question. May be \c NULL. 906 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 907 to store the requested icon (16x16 for the mini and 32x32 for the 908 large icon). 909 \param which Specifies the size of the icon to be retrieved: 910 \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon. 911 \return 912 - \c B_OK: Everything went fine. 913 - \c B_NO_INIT: The object is not properly initialized. 914 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size 915 \a which or bitmap dimensions (\a icon) and icon size (\a which) do 916 not match. 917 - other error codes 918 */ 919 status_t 920 BAppFileInfo::GetIconForType(const char* type, BBitmap* icon, 921 icon_size size) const 922 { 923 if (InitCheck() != B_OK) 924 return B_NO_INIT; 925 926 if (!icon || icon->InitCheck() != B_OK) 927 return B_BAD_VALUE; 928 929 // TODO: for consistency with attribute based icon reading, we 930 // could also prefer B_CMAP8 icons here if the provided bitmap 931 // is in that format. Right now, an existing B_CMAP8 icon resource 932 // would be ignored as soon as a vector icon is present. On the other 933 // hand, maybe this still results in a more consistent user interface, 934 // since Tracker/Deskbar would surely show the vector icon. 935 936 // try vector icon first 937 BString vectorAttributeName(kIconAttribute); 938 939 // check type param 940 if (type) { 941 if (BMimeType::IsValid(type)) 942 vectorAttributeName += type; 943 else 944 return B_BAD_VALUE; 945 } else { 946 vectorAttributeName += kIconType; 947 } 948 const char* attribute = vectorAttributeName.String(); 949 950 size_t bytesRead; 951 void* allocatedBuffer; 952 status_t error = _ReadData(attribute, -1, B_VECTOR_ICON_TYPE, NULL, 0, 953 bytesRead, &allocatedBuffer); 954 if (error == B_OK) { 955 error = BIconUtils::GetVectorIcon((uint8*)allocatedBuffer, 956 bytesRead, icon); 957 free(allocatedBuffer); 958 return error; 959 } 960 961 // no vector icon if we got this far, 962 // align size argument just in case 963 if (size < B_LARGE_ICON) 964 size = B_MINI_ICON; 965 else 966 size = B_LARGE_ICON; 967 968 error = B_OK; 969 // set some icon size related variables 970 BString attributeString; 971 BRect bounds; 972 uint32 attrType = 0; 973 size_t attrSize = 0; 974 switch (size) { 975 case B_MINI_ICON: 976 attributeString = kMiniIconAttribute; 977 bounds.Set(0, 0, 15, 15); 978 attrType = B_MINI_ICON_TYPE; 979 attrSize = 16 * 16; 980 break; 981 case B_LARGE_ICON: 982 attributeString = kLargeIconAttribute; 983 bounds.Set(0, 0, 31, 31); 984 attrType = B_LARGE_ICON_TYPE; 985 attrSize = 32 * 32; 986 break; 987 default: 988 return B_BAD_VALUE; 989 } 990 // check type param 991 if (type) { 992 if (BMimeType::IsValid(type)) 993 attributeString += type; 994 else 995 return B_BAD_VALUE; 996 } else 997 attributeString += kStandardIconType; 998 999 attribute = attributeString.String(); 1000 1001 // check parameters 1002 // currently, scaling B_CMAP8 icons is not supported 1003 if (icon->ColorSpace() == B_CMAP8 && icon->Bounds() != bounds) 1004 return B_BAD_VALUE; 1005 1006 // read the data 1007 if (error == B_OK) { 1008 bool tempBuffer = (icon->ColorSpace() != B_CMAP8 1009 || icon->Bounds() != bounds); 1010 uint8* buffer = NULL; 1011 size_t read; 1012 if (tempBuffer) { 1013 // other color space or bitmap size than stored in attribute 1014 buffer = new(nothrow) uint8[attrSize]; 1015 if (!buffer) { 1016 error = B_NO_MEMORY; 1017 } else { 1018 error = _ReadData(attribute, -1, attrType, buffer, attrSize, 1019 read); 1020 } 1021 } else { 1022 error = _ReadData(attribute, -1, attrType, icon->Bits(), attrSize, 1023 read); 1024 } 1025 if (error == B_OK && read != attrSize) 1026 error = B_ERROR; 1027 if (tempBuffer) { 1028 // other color space than stored in attribute 1029 if (error == B_OK) { 1030 error = BIconUtils::ConvertFromCMAP8(buffer, 1031 (uint32)size, 1032 (uint32)size, 1033 (uint32)size, 1034 icon); 1035 } 1036 delete[] buffer; 1037 } 1038 } 1039 return error; 1040 } 1041 1042 // GetIconForType 1043 /*! \brief Gets the icon the application provides for a given MIME type. 1044 1045 If \a type is \c NULL, the application's icon is retrieved. 1046 1047 \param type The MIME type in question. May be \c NULL. 1048 \param data A pointer in which the icon data will be returned. When you 1049 are done with the data, you should use free() to deallocate it. 1050 \param size A pointer in which the size of the retrieved data is returned. 1051 \return 1052 - \c B_OK: Everything went fine. 1053 - \c B_NO_INIT: The object is not properly initialized. 1054 - \c B_BAD_VALUE: \c NULL \a data and/or \a size. Or the supplied 1055 \a type is not a valid MIME type. 1056 - other error codes 1057 */ 1058 status_t 1059 BAppFileInfo::GetIconForType(const char *type, uint8** data, 1060 size_t* size) const 1061 { 1062 if (InitCheck() != B_OK) 1063 return B_NO_INIT; 1064 1065 if (!data || !size) 1066 return B_BAD_VALUE; 1067 1068 // get vector icon 1069 BString attributeName(kIconAttribute); 1070 1071 // check type param 1072 if (type) { 1073 if (BMimeType::IsValid(type)) 1074 attributeName += type; 1075 else 1076 return B_BAD_VALUE; 1077 } else { 1078 attributeName += kIconType; 1079 } 1080 1081 void* allocatedBuffer = NULL; 1082 status_t ret = _ReadData(attributeName.String(), -1, 1083 B_VECTOR_ICON_TYPE, NULL, 0, *size, &allocatedBuffer); 1084 1085 if (ret < B_OK) 1086 return ret; 1087 1088 *data = (uint8*)allocatedBuffer; 1089 return B_OK; 1090 } 1091 1092 // SetIconForType 1093 /*! \brief Sets the icon the application provides for a given MIME type. 1094 1095 If \a type is \c NULL, the application's icon is set. 1096 If \a icon is \c NULL the icon is unset. 1097 1098 If the file has a signature, then the icon is also set on the MIME type. 1099 If the type for the signature has not been installed yet, it is installed 1100 before. 1101 1102 \param type The MIME type in question. May be \c NULL. 1103 \param icon A pointer to the BBitmap containing the icon to be set. 1104 May be \c NULL. 1105 \param which Specifies the size of the icon to be set: \c B_MINI_ICON 1106 for the mini and \c B_LARGE_ICON for the large icon. 1107 \return 1108 - \c B_OK: Everything went fine. 1109 - \c B_NO_INIT: The object is not properly initialized. 1110 - \c B_BAD_VALUE: Either the icon size \a which is unkown, bitmap dimensions (\a icon) 1111 and icon size (\a which) do not match, or the provided \a type is 1112 not a valid MIME type. 1113 - other error codes 1114 */ 1115 status_t 1116 BAppFileInfo::SetIconForType(const char *type, const BBitmap *icon, 1117 icon_size which) 1118 { 1119 status_t error = B_OK; 1120 // set some icon size related variables 1121 BString attributeString; 1122 BRect bounds; 1123 uint32 attrType = 0; 1124 size_t attrSize = 0; 1125 int32 resourceID = 0; 1126 switch (which) { 1127 case B_MINI_ICON: 1128 attributeString = kMiniIconAttribute; 1129 bounds.Set(0, 0, 15, 15); 1130 attrType = B_MINI_ICON_TYPE; 1131 attrSize = 16 * 16; 1132 resourceID = (type ? kMiniIconForTypeResourceID 1133 : kMiniIconResourceID); 1134 break; 1135 case B_LARGE_ICON: 1136 attributeString = kLargeIconAttribute; 1137 bounds.Set(0, 0, 31, 31); 1138 attrType = B_LARGE_ICON_TYPE; 1139 attrSize = 32 * 32; 1140 resourceID = (type ? kLargeIconForTypeResourceID 1141 : kLargeIconResourceID); 1142 break; 1143 default: 1144 error = B_BAD_VALUE; 1145 break; 1146 } 1147 // check type param 1148 if (error == B_OK) { 1149 if (type) { 1150 if (BMimeType::IsValid(type)) 1151 attributeString += type; 1152 else 1153 error = B_BAD_VALUE; 1154 } else 1155 attributeString += kStandardIconType; 1156 } 1157 const char *attribute = attributeString.String(); 1158 // check parameter and initialization 1159 if (error == B_OK && icon 1160 && (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 1161 error = B_BAD_VALUE; 1162 } 1163 if (error == B_OK && InitCheck() != B_OK) 1164 error = B_NO_INIT; 1165 // write/remove the attribute 1166 if (error == B_OK) { 1167 if (icon) { 1168 bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); 1169 if (otherColorSpace) { 1170 BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8); 1171 error = bitmap.InitCheck(); 1172 if (error == B_OK) 1173 error = bitmap.ImportBits(icon); 1174 if (error == B_OK) { 1175 error = _WriteData(attribute, resourceID, attrType, 1176 bitmap.Bits(), attrSize, true); 1177 } 1178 } else { 1179 error = _WriteData(attribute, resourceID, attrType, 1180 icon->Bits(), attrSize, true); 1181 } 1182 } else // no icon given => remove 1183 error = _RemoveData(attribute, attrType); 1184 } 1185 // set the attribute on the MIME type, if the file has a signature 1186 BMimeType mimeType; 1187 if (error == B_OK && GetMetaMime(&mimeType) == B_OK) { 1188 if (!mimeType.IsInstalled()) 1189 error = mimeType.Install(); 1190 if (error == B_OK) 1191 error = mimeType.SetIconForType(type, icon, which); 1192 } 1193 return error; 1194 } 1195 1196 // SetIconForType 1197 /*! \brief Sets the icon the application provides for a given MIME type. 1198 1199 If \a type is \c NULL, the application's icon is set. 1200 If \a data is \c NULL the icon is unset. 1201 1202 If the file has a signature, then the icon is also set on the MIME type. 1203 If the type for the signature has not been installed yet, it is installed 1204 before. 1205 1206 \param type The MIME type in question. May be \c NULL. 1207 \param data A pointer to the data containing the icon to be set. 1208 May be \c NULL. 1209 \param size Specifies the size of buffer provided in \a data. 1210 \return 1211 - \c B_OK: Everything went fine. 1212 - \c B_NO_INIT: The object is not properly initialized. 1213 - \c B_BAD_VALUE: The provided \a type is not a valid MIME type. 1214 - other error codes 1215 */ 1216 status_t 1217 BAppFileInfo::SetIconForType(const char* type, const uint8* data, 1218 size_t size) 1219 { 1220 if (InitCheck() != B_OK) 1221 return B_NO_INIT; 1222 1223 // set some icon related variables 1224 BString attributeString = kIconAttribute; 1225 int32 resourceID = type ? kIconForTypeResourceID : kIconResourceID; 1226 uint32 attrType = B_VECTOR_ICON_TYPE; 1227 1228 // check type param 1229 if (type) { 1230 if (BMimeType::IsValid(type)) 1231 attributeString += type; 1232 else 1233 return B_BAD_VALUE; 1234 } else 1235 attributeString += kIconType; 1236 1237 const char *attribute = attributeString.String(); 1238 1239 status_t error; 1240 // write/remove the attribute 1241 if (data) 1242 error = _WriteData(attribute, resourceID, attrType, data, size, true); 1243 else // no icon given => remove 1244 error = _RemoveData(attribute, attrType); 1245 1246 // set the attribute on the MIME type, if the file has a signature 1247 BMimeType mimeType; 1248 if (error == B_OK && GetMetaMime(&mimeType) == B_OK) { 1249 if (!mimeType.IsInstalled()) 1250 error = mimeType.Install(); 1251 if (error == B_OK) 1252 error = mimeType.SetIconForType(type, data, size); 1253 } 1254 return error; 1255 } 1256 1257 // SetInfoLocation 1258 /*! \brief Specifies the location where the meta data shall be stored. 1259 1260 The options for \a location are: 1261 - \c B_USE_ATTRIBUTES: Store the data in the attributes. 1262 - \c B_USE_RESOURCES: Store the data in the resources. 1263 - \c B_USE_BOTH_LOCATIONS: Store the data in attributes and resources. 1264 1265 \param location The location where the meta data shall be stored. 1266 */ 1267 void 1268 BAppFileInfo::SetInfoLocation(info_location location) 1269 { 1270 // if the resources failed to initialize, we must not use them 1271 if (fResources == NULL) 1272 location = info_location(location & ~B_USE_RESOURCES); 1273 1274 fWhere = location; 1275 } 1276 1277 // IsUsingAttributes 1278 /*! \brief Returns whether the object stores the meta data (also) in the 1279 file's attributes. 1280 \return \c true, if the meta data are (also) stored in the file's 1281 attributes, \c false otherwise. 1282 */ 1283 bool 1284 BAppFileInfo::IsUsingAttributes() const 1285 { 1286 return (fWhere & B_USE_ATTRIBUTES) != 0; 1287 } 1288 1289 // IsUsingResources 1290 /*! \brief Returns whether the object stores the meta data (also) in the 1291 file's resources. 1292 \return \c true, if the meta data are (also) stored in the file's 1293 resources, \c false otherwise. 1294 */ 1295 bool 1296 BAppFileInfo::IsUsingResources() const 1297 { 1298 return (fWhere & B_USE_RESOURCES) != 0; 1299 } 1300 1301 // FBC 1302 void BAppFileInfo::_ReservedAppFileInfo1() {} 1303 void BAppFileInfo::_ReservedAppFileInfo2() {} 1304 void BAppFileInfo::_ReservedAppFileInfo3() {} 1305 1306 // = 1307 /*! \brief Privatized assignment operator to prevent usage. 1308 */ 1309 BAppFileInfo & 1310 BAppFileInfo::operator=(const BAppFileInfo &) 1311 { 1312 return *this; 1313 } 1314 1315 // copy constructor 1316 /*! \brief Privatized copy constructor to prevent usage. 1317 */ 1318 BAppFileInfo::BAppFileInfo(const BAppFileInfo &) 1319 { 1320 } 1321 1322 // GetMetaMime 1323 /*! \brief Initializes a BMimeType to the file's signature. 1324 1325 The parameter \a meta is not checked. 1326 1327 \param meta A pointer to a pre-allocated BMimeType that shall be 1328 initialized to the file's signature. 1329 \return 1330 - \c B_OK: Everything went fine. 1331 - \c B_BAD_VALUE: \c NULL \a meta 1332 - \c B_ENTRY_NOT_FOUND: The file has not signature or the signature is 1333 ( not installed in the MIME database.) 1334 no valid MIME string. 1335 - other error codes 1336 */ 1337 status_t 1338 BAppFileInfo::GetMetaMime(BMimeType *meta) const 1339 { 1340 char signature[B_MIME_TYPE_LENGTH]; 1341 status_t error = GetSignature(signature); 1342 if (error == B_OK) 1343 error = meta->SetTo(signature); 1344 else if (error == B_BAD_VALUE) 1345 error = B_ENTRY_NOT_FOUND; 1346 if (error == B_OK && !meta->IsValid()) 1347 error = B_BAD_VALUE; 1348 return error; 1349 } 1350 1351 // _ReadData 1352 /*! \brief Reads data from an attribute or resource. 1353 1354 The data are read from the location specified by \a fWhere. 1355 1356 The object must be properly initialized. The parameters are NOT checked. 1357 1358 \param name The name of the attribute/resource to be read. 1359 \param id The resource ID of the resource to be read. Is ignored, when 1360 < 0. 1361 \param type The type of the attribute/resource to be read. 1362 \param buffer A pre-allocated buffer for the data to be read. 1363 \param bufferSize The size of the supplied buffer. 1364 \param bytesRead A reference parameter, set to the number of bytes 1365 actually read. 1366 \param allocatedBuffer If not \c NULL, the method allocates a buffer 1367 large enough too store the whole data and writes a pointer to it 1368 into this variable. If \c NULL, the supplied buffer is used. 1369 \return 1370 - \c B_OK: Everything went fine. 1371 - error code 1372 */ 1373 status_t 1374 BAppFileInfo::_ReadData(const char *name, int32 id, type_code type, 1375 void *buffer, size_t bufferSize, 1376 size_t &bytesRead, void **allocatedBuffer) const 1377 { 1378 status_t error = B_OK; 1379 1380 if (allocatedBuffer) 1381 buffer = NULL; 1382 1383 bool foundData = false; 1384 1385 if (IsUsingAttributes()) { 1386 // get an attribute info 1387 attr_info info; 1388 if (error == B_OK) 1389 error = fNode->GetAttrInfo(name, &info); 1390 1391 // check type and size, allocate a buffer, if required 1392 if (error == B_OK && info.type != type) 1393 error = B_BAD_VALUE; 1394 if (error == B_OK && allocatedBuffer) { 1395 buffer = malloc(info.size); 1396 if (!buffer) 1397 error = B_NO_MEMORY; 1398 bufferSize = info.size; 1399 } 1400 if (error == B_OK && bufferSize < info.size) 1401 error = B_BAD_VALUE; 1402 1403 // read the data 1404 if (error == B_OK) { 1405 ssize_t read = fNode->ReadAttr(name, type, 0, buffer, info.size); 1406 if (read < 0) 1407 error = read; 1408 else if (read != info.size) 1409 error = B_ERROR; 1410 else 1411 bytesRead = read; 1412 } 1413 1414 foundData = (error == B_OK); 1415 1416 // free the allocated buffer on error 1417 if (!foundData && allocatedBuffer && buffer) { 1418 free(buffer); 1419 buffer = NULL; 1420 } 1421 } 1422 1423 if (!foundData && IsUsingResources()) { 1424 // get a resource info 1425 error = B_OK; 1426 int32 idFound; 1427 size_t sizeFound; 1428 if (error == B_OK) { 1429 if (!fResources->GetResourceInfo(type, name, &idFound, &sizeFound)) 1430 error = B_ENTRY_NOT_FOUND; 1431 } 1432 1433 // check id and size, allocate a buffer, if required 1434 if (error == B_OK && id >= 0 && idFound != id) 1435 error = B_ENTRY_NOT_FOUND; 1436 if (error == B_OK && allocatedBuffer) { 1437 buffer = malloc(sizeFound); 1438 if (!buffer) 1439 error = B_NO_MEMORY; 1440 bufferSize = sizeFound; 1441 } 1442 if (error == B_OK && bufferSize < sizeFound) 1443 error = B_BAD_VALUE; 1444 1445 // load resource 1446 const void *resourceData = NULL; 1447 if (error == B_OK) { 1448 resourceData = fResources->LoadResource(type, name, &bytesRead); 1449 if (resourceData && sizeFound == bytesRead) 1450 memcpy(buffer, resourceData, bytesRead); 1451 else 1452 error = B_ERROR; 1453 } 1454 } else if (!foundData) 1455 error = B_BAD_VALUE; 1456 1457 // return the allocated buffer, or free it on error 1458 if (allocatedBuffer) { 1459 if (error == B_OK) 1460 *allocatedBuffer = buffer; 1461 else 1462 free(buffer); 1463 } 1464 1465 return error; 1466 } 1467 1468 // _WriteData 1469 /*! \brief Writes data to an attribute or resource. 1470 1471 The data are written to the location(s) specified by \a fWhere. 1472 1473 The object must be properly initialized. The parameters are NOT checked. 1474 1475 \param name The name of the attribute/resource to be written. 1476 \param id The resource ID of the resource to be written. 1477 \param type The type of the attribute/resource to be written. 1478 \param buffer A buffer containing the data to be written. 1479 \param bufferSize The size of the supplied buffer. 1480 \param findID If set to \c true use the ID that is already assigned to the 1481 \a name / \a type pair or take the first unused ID >= \a id. 1482 If \c false, \a id is used. 1483 If \a id is already in use and . 1484 \return 1485 - \c B_OK: Everything went fine. 1486 - error code 1487 */ 1488 status_t 1489 BAppFileInfo::_WriteData(const char *name, int32 id, type_code type, 1490 const void *buffer, size_t bufferSize, bool findID) 1491 { 1492 if (!IsUsingAttributes() && !IsUsingResources()) 1493 return B_NO_INIT; 1494 1495 status_t error = B_OK; 1496 1497 // write to attribute 1498 if (IsUsingAttributes()) { 1499 ssize_t written = fNode->WriteAttr(name, type, 0, buffer, bufferSize); 1500 if (written < 0) 1501 error = written; 1502 else if (written != (ssize_t)bufferSize) 1503 error = B_ERROR; 1504 } 1505 // write to resource 1506 if (IsUsingResources() && error == B_OK) { 1507 if (findID) { 1508 // get the resource info 1509 int32 idFound; 1510 size_t sizeFound; 1511 if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound)) 1512 id = idFound; 1513 else { 1514 // type-name pair doesn't exist yet -- find unused ID 1515 while (fResources->HasResource(type, id)) 1516 id++; 1517 } 1518 } 1519 error = fResources->AddResource(type, id, buffer, bufferSize, name); 1520 } 1521 return error; 1522 } 1523 1524 // _RemoveData 1525 /*! \brief Removes an attribute or resource. 1526 1527 The removal location is specified by \a fWhere. 1528 1529 The object must be properly initialized. The parameters are NOT checked. 1530 1531 \param name The name of the attribute/resource to be remove. 1532 \param type The type of the attribute/resource to be removed. 1533 \return 1534 - \c B_OK: Everything went fine. 1535 - error code 1536 */ 1537 status_t 1538 BAppFileInfo::_RemoveData(const char *name, type_code type) 1539 { 1540 if (!IsUsingAttributes() && !IsUsingResources()) 1541 return B_NO_INIT; 1542 1543 status_t error = B_OK; 1544 1545 // remove the attribute 1546 if (IsUsingAttributes()) { 1547 error = fNode->RemoveAttr(name); 1548 // It's no error, if there has been no attribute. 1549 if (error == B_ENTRY_NOT_FOUND) 1550 error = B_OK; 1551 } 1552 // remove the resource 1553 if (IsUsingResources() && error == B_OK) { 1554 // get a resource info 1555 int32 idFound; 1556 size_t sizeFound; 1557 if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound)) 1558 error = fResources->RemoveResource(type, idFound); 1559 } 1560 return error; 1561 } 1562 1563