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