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