1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //--------------------------------------------------------------------- 5 /*! 6 \file Database.cpp 7 Database class implementation 8 */ 9 10 #include <Application.h> 11 #include <Bitmap.h> 12 #include <DataIO.h> 13 #include <Directory.h> 14 #include <Entry.h> 15 #include <Locker.h> 16 #include <Message.h> 17 #include <mime/database_access.h> 18 #include <mime/database_support.h> 19 #include <MimeType.h> 20 #include <Node.h> 21 #include <Path.h> 22 #include <String.h> 23 #include <storage_support.h> 24 #include <TypeConstants.h> 25 26 #include <fs_attr.h> // For struct attr_info 27 #include <iostream> 28 #include <new> // For new(nothrow) 29 #include <stdio.h> 30 #include <string> 31 32 #include "mime/Database.h" 33 34 //#define DBG(x) x 35 #define DBG(x) 36 #define OUT printf 37 38 // icon types 39 enum { 40 B_MINI_ICON_TYPE = 'MICN', 41 B_LARGE_ICON_TYPE = 'ICON', 42 }; 43 44 namespace BPrivate { 45 namespace Storage { 46 namespace Mime { 47 48 /*! 49 \class Database 50 \brief Mime::Database is the master of the MIME data base. 51 52 All write and non-atomic read accesses are carried out by this class. 53 54 \note No error checking (other than checks for NULL pointers) is performed 55 by this class on the mime type strings passed to it. It's assumed 56 that this sort of checking has been done beforehand. 57 */ 58 59 // constructor 60 /*! \brief Creates and initializes a Mime::Database object. 61 */ 62 Database::Database() 63 : fStatus(B_NO_INIT) 64 { 65 // Do some really minor error checking 66 BEntry entry(kDatabaseDir.c_str()); 67 fStatus = entry.Exists() ? B_OK : B_BAD_VALUE; 68 } 69 70 // destructor 71 /*! \brief Frees all resources associated with this object. 72 */ 73 Database::~Database() 74 { 75 } 76 77 // InitCheck 78 /*! \brief Returns the initialization status of the object. 79 \return 80 - B_OK: success 81 - "error code": failure 82 */ 83 status_t 84 Database::InitCheck() const 85 { 86 return fStatus; 87 } 88 89 // Install 90 /*! \brief Installs the given type in the database 91 \note The R5 version of this call returned an unreliable result if the 92 MIME type was already installed. Ours simply returns B_OK. 93 \param type Pointer to a NULL-terminated string containing the MIME type of interest 94 \param decsription Pointer to a NULL-terminated string containing the new long description 95 \return 96 - B_OK: success 97 - B_FILE_EXISTS: the type is already installed 98 - "error code": failure 99 */ 100 status_t 101 Database::Install(const char *type) 102 { 103 BEntry entry; 104 status_t err = (type ? B_OK : B_BAD_VALUE); 105 if (!err) 106 err = entry.SetTo(type_to_filename(type).c_str()); 107 if (!err) { 108 if (entry.Exists()) 109 err = B_FILE_EXISTS; 110 else { 111 bool didCreate = false; 112 BNode node; 113 err = open_or_create_type(type, &node, &didCreate); 114 if (!err && didCreate) { 115 fInstalledTypes.AddType(type); 116 err = SendInstallNotification(type); 117 } 118 } 119 } 120 return err; 121 } 122 123 // Delete 124 /*! \brief Removes the given type from the database 125 \param type Pointer to a NULL-terminated string containing the MIME type of interest 126 \return 127 - B_OK: success 128 - "error code": failure 129 */ 130 status_t 131 Database::Delete(const char *type) 132 { 133 BEntry entry; 134 status_t err = (type ? B_OK : B_BAD_VALUE); 135 // Open the type 136 if (!err) 137 err = entry.SetTo(type_to_filename(type).c_str()); 138 // Remove it 139 if (!err) 140 err = entry.Remove(); 141 // Notify the installed types database 142 if (!err) 143 fInstalledTypes.RemoveType(type); 144 // Notify the supporting apps database 145 if (!err) 146 err = fSupportingApps.DeleteSupportedTypes(type, true); 147 // Notify the monitor service 148 if (!err) 149 err = SendDeleteNotification(type); 150 return err; 151 } 152 153 // SetAppHint 154 /*! \brief Sets the application hint for the given MIME type 155 \param type Pointer to a NULL-terminated string containing the MIME type of interest 156 \param decsription Pointer to an entry_ref containing the location of an application 157 that should be used when launching an application with this signature. 158 */ 159 status_t 160 Database::SetAppHint(const char *type, const entry_ref *ref) 161 { 162 DBG(OUT("Database::SetAppHint()\n")); 163 BPath path; 164 bool didCreate = false; 165 status_t err = (type && ref) ? B_OK : B_BAD_VALUE; 166 if (!err) 167 err = path.SetTo(ref); 168 if (!err) 169 err = write_mime_attr(type, kAppHintAttr, path.Path(), strlen(path.Path())+1, 170 kAppHintType, &didCreate); 171 if (!err && didCreate) 172 err = SendInstallNotification(type); 173 if (!err) 174 err = SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_MODIFIED); 175 return err; 176 } 177 178 // SetAttrInfo 179 /*! \brief Stores a BMessage describing the format of attributes typically associated with 180 files of the given MIME type 181 182 See BMimeType::SetAttrInfo() for description of the expected message format. 183 184 The \c BMessage::what value is ignored. 185 186 \param info Pointer to a pre-allocated and properly formatted BMessage containing 187 information about the file attributes typically associated with the 188 MIME type. 189 \return 190 - \c B_OK: Success 191 - "error code": Failure 192 */ 193 status_t 194 Database::SetAttrInfo(const char *type, const BMessage *info) 195 { 196 DBG(OUT("Database::SetAttrInfo()\n")); 197 bool didCreate = false; 198 status_t err = (type && info) ? B_OK : B_BAD_VALUE; 199 if (!err) 200 err = write_mime_attr_message(type, kAttrInfoAttr, info, &didCreate); 201 if (!err && didCreate) 202 err = SendInstallNotification(type); 203 if (!err) 204 err = SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_MODIFIED); 205 return err; 206 } 207 208 // SetShortDescription 209 /*! \brief Sets the short description for the given MIME type 210 \param type Pointer to a NULL-terminated string containing the MIME type of interest 211 \param decsription Pointer to a NULL-terminated string containing the new short description 212 */ 213 status_t 214 Database::SetShortDescription(const char *type, const char *description) 215 { 216 DBG(OUT("Database::SetShortDescription()\n")); 217 bool didCreate = false; 218 status_t err = (type && description && strlen(description) < B_MIME_TYPE_LENGTH) ? B_OK : B_BAD_VALUE; 219 if (!err) 220 err = write_mime_attr(type, kShortDescriptionAttr, description, strlen(description)+1, 221 kShortDescriptionType, &didCreate); 222 if (!err) 223 err = SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_MODIFIED); 224 return err; 225 } 226 227 // SetLongDescription 228 /*! \brief Sets the long description for the given MIME type 229 \param type Pointer to a NULL-terminated string containing the MIME type of interest 230 \param decsription Pointer to a NULL-terminated string containing the new long description 231 */ 232 status_t 233 Database::SetLongDescription(const char *type, const char *description) 234 { 235 DBG(OUT("Database::SetLongDescription()\n")); 236 bool didCreate = false; 237 status_t err = (type && description && strlen(description) < B_MIME_TYPE_LENGTH) ? B_OK : B_BAD_VALUE; 238 if (!err) 239 err = write_mime_attr(type, kLongDescriptionAttr, description, strlen(description)+1, 240 kLongDescriptionType, &didCreate); 241 if (!err && didCreate) 242 err = SendInstallNotification(type); 243 if (!err) 244 err = SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_MODIFIED); 245 return err; 246 } 247 248 // SetFileExtensions 249 //! Sets the list of filename extensions associated with the MIME type 250 /*! The list of extensions is given in a pre-allocated BMessage pointed to by 251 the \c extensions parameter. Please see BMimeType::SetFileExtensions() 252 for a description of the expected message format. 253 254 \param extensions Pointer to a pre-allocated, properly formatted BMessage containing 255 the new list of file extensions to associate with this MIME type. 256 \return 257 - \c B_OK: Success 258 - "error code": Failure 259 */ 260 status_t 261 Database::SetFileExtensions(const char *type, const BMessage *extensions) 262 { 263 DBG(OUT("Database::SetFileExtensions()\n")); 264 bool didCreate = false; 265 status_t err = (type && extensions) ? B_OK : B_BAD_VALUE; 266 if (!err) 267 err = write_mime_attr_message(type, kFileExtensionsAttr, extensions, &didCreate); 268 if (!err && didCreate) 269 err = SendInstallNotification(type); 270 if (!err) 271 err = SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_MODIFIED); 272 return err; 273 } 274 275 //! Sets the icon for the given mime type 276 /*! This is the version I would have used if I could have gotten a BBitmap 277 to the registrar somehow. Since R5::BBitmap::Instantiate is causing a 278 violent crash, I've copied most of the icon color conversion code into 279 Mime::get_icon_data() so BMimeType::SetIcon() can get at it. 280 281 Once we have a sufficiently complete OBOS::BBitmap implementation, we 282 ought to be able to use this version of SetIcon() again. At that point, 283 I'll add some real documentation. 284 */ 285 status_t 286 Database::SetIcon(const char *type, const void *data, size_t dataSize, icon_size which) 287 { 288 return SetIconForType(type, NULL, data, dataSize, which); 289 } 290 291 // SetIconForType 292 /*! \brief Sets the large or mini icon used by an application of this type for 293 files of the given type. 294 295 The type of the \c BMimeType object is not required to actually be a subtype of 296 \c "application/"; that is the intended use however, and application-specific 297 icons are not expected to be present for non-application types. 298 299 The bitmap data pointed to by \c data must be of the proper size (\c 32x32 300 for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and the proper color 301 space (B_CMAP8). 302 303 \param type The MIME type 304 \param fileType The MIME type whose custom icon you wish to set. 305 \param data Pointer to an array of bitmap data of proper dimensions and color depth 306 \param dataSize The length of the array pointed to by \c data 307 \param size The size icon you're expecting (\c B_LARGE_ICON or \c B_MINI_ICON) 308 \return 309 - \c B_OK: Success 310 - "error code": Failure 311 312 */ 313 status_t 314 Database::SetIconForType(const char *type, const char *fileType, const void *data, 315 size_t dataSize, icon_size which) 316 { 317 ssize_t err = (type && data) ? B_OK : B_BAD_VALUE; 318 319 std::string attr; 320 int32 attrType = 0; 321 size_t attrSize = 0; 322 323 // Figure out what kind of data we *should* have 324 if (!err) { 325 switch (which) { 326 case B_MINI_ICON: 327 attrType = kMiniIconType; 328 attrSize = 16 * 16; 329 break; 330 case B_LARGE_ICON: 331 attrType = kLargeIconType; 332 attrSize = 32 * 32; 333 break; 334 default: 335 err = B_BAD_VALUE; 336 break; 337 } 338 } 339 340 // Construct our attribute name 341 if (fileType) { 342 attr = (which == B_MINI_ICON 343 ? kMiniIconAttrPrefix 344 : kLargeIconAttrPrefix) 345 + BPrivate::Storage::to_lower(fileType); 346 } else 347 attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr; 348 349 // Double check the data we've been given 350 if (!err) 351 err = dataSize == attrSize ? B_OK : B_BAD_VALUE; 352 353 // Write the icon data 354 BNode node; 355 bool didCreate = false; 356 if (!err) 357 err = open_or_create_type(type, &node, &didCreate); 358 if (!err && didCreate) 359 err = SendInstallNotification(type); 360 if (!err) 361 err = node.WriteAttr(attr.c_str(), attrType, 0, data, attrSize); 362 if (err >= 0) 363 err = err == (ssize_t)attrSize ? B_OK : B_FILE_ERROR; 364 if (!err) { 365 if (fileType) 366 err = SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType, (which == B_LARGE_ICON), B_META_MIME_MODIFIED); 367 else 368 err = SendMonitorUpdate(B_ICON_CHANGED, type, (which == B_LARGE_ICON), B_META_MIME_MODIFIED); 369 } 370 return err; 371 372 } 373 374 // SetPreferredApp 375 /*! \brief Sets the signature of the preferred application for the given app verb 376 377 Currently, the only supported app verb is \c B_OPEN 378 \param type Pointer to a NULL-terminated string containing the MIME type of interest 379 \param signature Pointer to a NULL-terminated string containing the MIME signature 380 of the new preferred application 381 \param verb \c app_verb action for which the new preferred application is applicable 382 */ 383 status_t 384 Database::SetPreferredApp(const char *type, const char *signature, app_verb verb = B_OPEN) 385 { 386 DBG(OUT("Database::SetPreferredApp()\n")); 387 bool didCreate = false; 388 status_t err = (type && signature && strlen(signature) < B_MIME_TYPE_LENGTH) ? B_OK : B_BAD_VALUE; 389 if (!err) 390 err = write_mime_attr(type, kPreferredAppAttr, signature, strlen(signature)+1, 391 kPreferredAppType, &didCreate); 392 if (!err && didCreate) 393 err = SendInstallNotification(type); 394 if (!err) 395 err = SendMonitorUpdate(B_PREFERRED_APP_CHANGED, type, B_META_MIME_MODIFIED); 396 return err; 397 } 398 399 // SetSnifferRule 400 /*! \brief Sets the mime sniffer rule for the given mime type 401 */ 402 status_t 403 Database::SetSnifferRule(const char *type, const char *rule) 404 { 405 DBG(OUT("Database::SetSnifferRule()\n")); 406 bool didCreate = false; 407 status_t err = (type && rule) ? B_OK : B_BAD_VALUE; 408 if (!err) 409 err = write_mime_attr(type, kSnifferRuleAttr, rule, strlen(rule)+1, 410 kSnifferRuleType, &didCreate); 411 if (!err) 412 err = fSnifferRules.SetSnifferRule(type, rule); 413 if (!err && didCreate) 414 err = SendInstallNotification(type); 415 if (!err) 416 err = SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type, B_META_MIME_MODIFIED); 417 return err; 418 } 419 420 // SetSupportedTypes 421 /*! \brief Sets the list of MIME types supported by the MIME type and 422 syncs the internal supporting apps database either partially or 423 completely. 424 425 Please see BMimeType::SetSupportedTypes() for details. 426 \param type The mime type of interest 427 \param types The supported types to be assigned to the file. 428 \param syncAll \c true to also synchronize the previously supported 429 types, \c false otherwise. 430 \return 431 - \c B_OK: success 432 - other error codes: failure 433 */ 434 status_t 435 Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSync) 436 { 437 DBG(OUT("Database::SetSupportedTypes()\n")); 438 bool didCreate = false; 439 status_t err = (type && types) ? B_OK : B_BAD_VALUE; 440 // Install the types 441 if (!err) { 442 const char *supportedType; 443 for (int32 i = 0; 444 err == B_OK 445 && types->FindString("types", i, &supportedType) == B_OK; 446 i++) { 447 if (!is_installed(supportedType)) 448 err = Install(supportedType); 449 } 450 } 451 // Write the attr 452 if (!err) 453 err = write_mime_attr_message(type, kSupportedTypesAttr, types, &didCreate); 454 // Notify the monitor if we created the type when we opened it 455 if (!err && didCreate) 456 err = SendInstallNotification(type); 457 // Update the supporting apps map 458 if (!err) 459 err = fSupportingApps.SetSupportedTypes(type, types, fullSync); 460 // Notify the monitor 461 if (!err) 462 err = SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type, B_META_MIME_MODIFIED); 463 return err; 464 } 465 466 // GetInstalledSupertypes 467 /*! \brief Fetches a BMessage listing all the MIME supertypes currently 468 installed in the MIME database. 469 470 The types are copied into the \c "super_types" field of the passed-in \c BMessage. 471 The \c BMessage must be pre-allocated. 472 473 \param super_types Pointer to a pre-allocated \c BMessage into which the 474 MIME supertypes will be copied. 475 \return 476 - \c B_OK: Success 477 - "error code": Failure 478 */ 479 status_t 480 Database::GetInstalledSupertypes(BMessage *supertypes) 481 { 482 return fInstalledTypes.GetInstalledSupertypes(supertypes); 483 } 484 485 // GetInstalledTypes 486 /*! \brief Fetches a BMessage listing all the MIME types currently installed 487 in the MIME database. 488 489 The types are copied into the \c "types" field of the passed-in \c BMessage. 490 The \c BMessage must be pre-allocated. 491 492 \param types Pointer to a pre-allocated \c BMessage into which the 493 MIME types will be copied. 494 \return 495 - \c B_OK: Success 496 - "error code": Failure 497 */ 498 status_t 499 Database::GetInstalledTypes(BMessage *types) 500 { 501 return fInstalledTypes.GetInstalledTypes(types); 502 } 503 504 // GetInstalledTypes 505 /*! \brief Fetches a BMessage listing all the MIME subtypes of the given 506 supertype currently installed in the MIME database. 507 508 The types are copied into the \c "types" field of the passed-in \c BMessage. 509 The \c BMessage must be pre-allocated. 510 511 \param super_type Pointer to a string containing the MIME supertype whose 512 subtypes you wish to retrieve. 513 \param subtypes Pointer to a pre-allocated \c BMessage into which the appropriate 514 MIME subtypes will be copied. 515 \return 516 - \c B_OK: Success 517 - "error code": Failure 518 */ 519 status_t 520 Database::GetInstalledTypes(const char *supertype, BMessage *subtypes) 521 { 522 return fInstalledTypes.GetInstalledTypes(supertype, subtypes); 523 } 524 525 // GetSupportingApps 526 /*! \brief Fetches a \c BMessage containing a list of MIME signatures of 527 applications that are able to handle files of this MIME type. 528 529 Please see BMimeType::GetSupportingApps() for more details. 530 */ 531 status_t 532 Database::GetSupportingApps(const char *type, BMessage *signatures) 533 { 534 return fSupportingApps.GetSupportingApps(type, signatures); 535 } 536 537 // GetAssociatedTypes 538 /*! \brief Returns a list of mime types associated with the given file extension 539 540 Please see BMimeType::GetAssociatedTypes() for more details. 541 */ 542 status_t 543 Database::GetAssociatedTypes(const char *extension, BMessage *types) 544 { 545 return B_ERROR; 546 } 547 548 // GuessMimeType 549 /*! \brief Guesses a MIME type for the entry referred to by the given 550 \c entry_ref. 551 552 This version of GuessMimeType() combines the features of the other 553 versions, plus adds a few tricks of its own: 554 - If the entry is a meta mime entry (i.e. has a \c "META:TYPE" attribute), 555 the type returned is \c "application/x-vnd.be-meta-mime". 556 - If the entry is a directory, the type returned is 557 \c "application/x-vnd.be-directory". 558 - If the entry is a symlink, the type returned is 559 \c "application/x-vnd.be-symlink". 560 - If the entry is a regular file, the file data is sniffed and, the 561 type returned is the mime type with the matching rule of highest 562 priority. 563 - If sniffing fails, the filename is checked for known extensions. 564 - If the extension check fails, the type returned is 565 \c "application/octet-stream". 566 567 \param ref Pointer to the entry_ref referring to the entry. 568 \param type Pointer to a pre-allocated BString which is set to the 569 resulting MIME type. 570 \return 571 - \c B_OK: success (even if the guess returned is "application/octet-stream") 572 - other error code: failure 573 */ 574 status_t 575 Database::GuessMimeType(const entry_ref *file, BString *result) 576 { 577 status_t err = file && result ? B_OK : B_BAD_VALUE; 578 579 BNode node; 580 struct stat statData; 581 if (!err) 582 err = node.SetTo(file); 583 if (!err) { 584 attr_info info; 585 if (node.GetAttrInfo(kTypeAttr, &info) == B_OK) { 586 // Check for a META:TYPE attribute 587 result->SetTo(kMetaMimeType); 588 BPath path(file); 589 } else { 590 // See if we have a directory, a symlink, or a vanilla file 591 err = node.GetStat(&statData); 592 if (!err) { 593 if (S_ISDIR(statData.st_mode)) { 594 // Directory 595 result->SetTo(kDirectoryType); 596 } else if (S_ISLNK(statData.st_mode)) { 597 // Symlink 598 result->SetTo(kSymlinkType); 599 } else if (S_ISREG(statData.st_mode)) { 600 // Vanilla file: sniff first 601 err = fSnifferRules.GuessMimeType(file, result); 602 // If that fails, check extensions 603 if (err == kMimeGuessFailureError) 604 err = fAssociatedTypes.GuessMimeType(file, result); 605 // If that fails, return the generic file type 606 if (err == kMimeGuessFailureError) { 607 result->SetTo(kGenericFileType); 608 err = B_OK; 609 } 610 } 611 } 612 } 613 } 614 return err; 615 } 616 617 // GuessMimeType 618 /*! \brief Guesses a MIME type for the supplied chunk of data. 619 620 See \c SnifferRules::GuessMimeType(BPositionIO*, BString*) 621 for more details. 622 623 \param buffer Pointer to the data buffer. 624 \param length Size of the buffer in bytes. 625 \param type Pointer to a pre-allocated BString which is set to the 626 resulting MIME type. 627 \return 628 - \c B_OK: success 629 - error code: failure 630 */ 631 status_t 632 Database::GuessMimeType(const void *buffer, int32 length, BString *result) 633 { 634 status_t err = buffer && result ? B_OK : B_BAD_VALUE; 635 if (!err) 636 err = fSnifferRules.GuessMimeType(buffer, length, result); 637 if (err == kMimeGuessFailureError) { 638 result->SetTo(kGenericFileType); 639 err = B_OK; 640 } 641 return err; 642 } 643 644 // GuessMimeType 645 /*! \brief Guesses a MIME type for the given filename. 646 647 Only the filename itself is taken into consideration (in particular its 648 name extension), not the entry or corresponding data it refers to (in fact, 649 an entry with that name need not exist at all. 650 651 \param filename The filename. 652 \param type Pointer to a pre-allocated BString which is set to the 653 resulting MIME type. 654 \return 655 - \c B_OK: success 656 - error code: failure 657 */ 658 status_t 659 Database::GuessMimeType(const char *filename, BString *result) 660 { 661 status_t err = filename && result ? B_OK : B_BAD_VALUE; 662 if (!err) 663 err = fAssociatedTypes.GuessMimeType(filename, result); 664 if (err == kMimeGuessFailureError) { 665 result->SetTo(kGenericFileType); 666 err = B_OK; 667 } 668 return err; 669 } 670 671 // StartWatching 672 //! Subscribes the given BMessenger to the MIME monitor service 673 /*! Notification messages will be sent with a \c BMessage::what value 674 of \c B_META_MIME_CHANGED. Notification messages have the following 675 fields: 676 677 <table> 678 <tr> 679 <td> Name </td> 680 <td> Type </td> 681 <td> Description </td> 682 </tr> 683 <tr> 684 <td> \c be:type </td> 685 <td> \c B_STRING_TYPE </td> 686 <td> The MIME type that was changed </td> 687 </tr> 688 <tr> 689 <td> \c be:which </td> 690 <td> \c B_INT32_TYPE </td> 691 <td> Bitmask describing which attributes were changed (see below) </td> 692 </tr> 693 <tr> 694 <td> \c be:extra_type </td> 695 <td> \c B_STRING_TYPE </td> 696 <td> Additional MIME type string (applicable to B_ICON_FOR_TYPE_CHANGED notifications only)</td> 697 </tr> 698 <tr> 699 <td> \c be:large_icon </td> 700 <td> \c B_BOOL_TYPE </td> 701 <td> \c true if the large icon was changed, \c false if the small icon 702 was changed (applicable to B_ICON_[FOR_TYPE_]CHANGED updates only) </td> 703 </tr> 704 </table> 705 706 The \c be:which field of the message describes which attributes were updated, and 707 may be the bitwise \c OR of any of the following values: 708 709 <table> 710 <tr> 711 <td> Value </td> 712 <td> Triggered By </td> 713 </tr> 714 <tr> 715 <td> \c B_ICON_CHANGED </td> 716 <td> \c BMimeType::SetIcon() </td> 717 </tr> 718 <tr> 719 <td> \c B_PREFERRED_APP_CHANGED </td> 720 <td> \c BMimeType::SetPreferredApp() </td> 721 </tr> 722 <tr> 723 <td> \c B_ATTR_INFO_CHANGED </td> 724 <td> \c BMimeType::SetAttrInfo() </td> 725 </tr> 726 <tr> 727 <td> \c B_FILE_EXTENSIONS_CHANGED </td> 728 <td> \c BMimeType::SetFileExtensions() </td> 729 </tr> 730 <tr> 731 <td> \c B_SHORT_DESCRIPTION_CHANGED </td> 732 <td> \c BMimeType::SetShortDescription() </td> 733 </tr> 734 <tr> 735 <td> \c B_LONG_DESCRIPTION_CHANGED </td> 736 <td> \c BMimeType::SetLongDescription() </td> 737 </tr> 738 <tr> 739 <td> \c B_ICON_FOR_TYPE_CHANGED </td> 740 <td> \c BMimeType::SetIconForType() </td> 741 </tr> 742 <tr> 743 <td> \c B_APP_HINT_CHANGED </td> 744 <td> \c BMimeType::SetAppHint() </td> 745 </tr> 746 </table> 747 748 \param target The \c BMessenger to subscribe to the MIME monitor service 749 */ 750 status_t 751 Database::StartWatching(BMessenger target) 752 { 753 DBG(OUT("Database::StartWatching()\n")); 754 status_t err = target.IsValid() ? B_OK : B_BAD_VALUE; 755 if (!err) 756 fMonitorMessengers.insert(target); 757 return err; 758 } 759 760 // StartWatching 761 //! Unsubscribes the given BMessenger from the MIME monitor service 762 /*! \param target The \c BMessenger to unsubscribe 763 */ 764 status_t 765 Database::StopWatching(BMessenger target) 766 { 767 DBG(OUT("Database::StopWatching()\n")); 768 status_t err = target.IsValid() ? B_OK : B_BAD_VALUE; 769 if (!err) 770 err = fMonitorMessengers.find(target) != fMonitorMessengers.end() ? B_OK : B_ENTRY_NOT_FOUND; 771 if (!err) 772 fMonitorMessengers.erase(target); 773 return err; 774 } 775 776 // DeleteAppHint 777 //! Deletes the app hint attribute for the given type 778 /*! A \c B_APP_HINT_CHANGED notification is sent to the mime monitor service. 779 \param type The mime type of interest 780 \return 781 - B_OK: success 782 - B_ENTRY_NOT_FOUND: no such attribute existed 783 - "error code": failure 784 */ 785 status_t 786 Database::DeleteAppHint(const char *type) 787 { 788 status_t err = delete_attribute(type, kAppHintAttr); 789 if (!err) 790 err = SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_DELETED); 791 return err; 792 } 793 794 // DeleteAttrInfo 795 //! Deletes the attribute info attribute for the given type 796 /*! A \c B_ATTR_INFO_CHANGED notification is sent to the mime monitor service. 797 \param type The mime type of interest 798 \return 799 - B_OK: success 800 - B_ENTRY_NOT_FOUND: no such attribute existed 801 - "error code": failure 802 */ 803 status_t 804 Database::DeleteAttrInfo(const char *type) 805 { 806 status_t err = delete_attribute(type, kAttrInfoAttr); 807 if (!err) 808 err = SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_DELETED); 809 return err; 810 } 811 812 // DeleteShortDescription 813 //! Deletes the short description attribute for the given type 814 /*! A \c B_SHORT_DESCRIPTION_CHANGED notification is sent to the mime monitor service. 815 \param type The mime type of interest 816 \return 817 - B_OK: success 818 - B_ENTRY_NOT_FOUND: no such attribute existed 819 - "error code": failure 820 */ 821 status_t 822 Database::DeleteShortDescription(const char *type) 823 { 824 status_t err = delete_attribute(type, kShortDescriptionAttr); 825 if (!err) 826 err = SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED); 827 return err; 828 } 829 830 // DeleteLongDescription 831 //! Deletes the long description attribute for the given type 832 /*! A \c B_LONG_DESCRIPTION_CHANGED notification is sent to the mime monitor service. 833 \param type The mime type of interest 834 \return 835 - B_OK: success 836 - B_ENTRY_NOT_FOUND: no such attribute existed 837 - "error code": failure 838 */ 839 status_t 840 Database::DeleteLongDescription(const char *type) 841 { 842 status_t err = delete_attribute(type, kLongDescriptionAttr); 843 if (!err) 844 err = SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED); 845 return err; 846 } 847 848 // DeleteFileExtensions 849 //! Deletes the associated file extensions attribute for the given type 850 /*! A \c B_FILE_EXTENSIONS_CHANGED notification is sent to the mime monitor service. 851 \param type The mime type of interest 852 \return 853 - B_OK: success 854 - B_ENTRY_NOT_FOUND: no such attribute existed 855 - "error code": failure 856 */ 857 status_t 858 Database::DeleteFileExtensions(const char *type) 859 { 860 status_t err = delete_attribute(type, kFileExtensionsAttr); 861 if (!err) 862 err = SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_DELETED); 863 return err; 864 } 865 866 // DeleteIcon 867 //! Deletes the icon of the given size for the given type 868 /*! A \c B_ICON_CHANGED notification is sent to the mime monitor service. 869 \param type The mime type of interest 870 \param which The icon size of interest 871 \return 872 - B_OK: success 873 - B_ENTRY_NOT_FOUND: no such attribute existed 874 - "error code": failure 875 */ 876 status_t 877 Database::DeleteIcon(const char *type, icon_size which) 878 { 879 const char *attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr; 880 status_t err = delete_attribute(type, attr); 881 if (!err) 882 err = SendMonitorUpdate(B_ICON_CHANGED, type, which, B_META_MIME_DELETED); 883 return err; 884 } 885 886 // DeleteIconForType 887 /*! \brief Deletes the icon of the given size associated with the given file type for the given 888 application signature. 889 890 (If this function seems confusing, please see BMimeType::GetIconForType() for a 891 better description of what the *IconForType() functions are used for.) 892 893 A \c B_ICON_FOR_TYPE_CHANGED notification is sent to the mime monitor service. 894 \param type The mime type of the application whose custom icon you are deleting. 895 \param which The mime type for which you no longer wish \c type to have a custom icon. 896 \param which The icon size of interest 897 \return 898 - B_OK: success 899 - B_ENTRY_NOT_FOUND: no such attribute existed 900 - "error code": failure 901 */ 902 status_t 903 Database::DeleteIconForType(const char *type, const char *fileType, icon_size which) 904 { 905 std::string attr; 906 status_t err = fileType ? B_OK : B_BAD_VALUE; 907 if (!err) { 908 attr = (which == B_MINI_ICON ? kMiniIconAttrPrefix : kLargeIconAttrPrefix) + BPrivate::Storage::to_lower(fileType); 909 err = delete_attribute(type, attr.c_str()); 910 } 911 if (!err) 912 err = SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType, 913 which == B_LARGE_ICON, B_META_MIME_DELETED); 914 return err; 915 } 916 917 // DeletePreferredApp 918 //! Deletes the preferred app for the given app verb for the given type 919 /*! A \c B_PREFERRED_APP_CHANGED notification is sent to the mime monitor service. 920 \param type The mime type of interest 921 \param which The app verb of interest 922 \return 923 - B_OK: success 924 - B_ENTRY_NOT_FOUND: no such attribute existed 925 - "error code": failure 926 */ 927 status_t 928 Database::DeletePreferredApp(const char *type, app_verb verb = B_OPEN) 929 { 930 status_t err; 931 switch (verb) { 932 case B_OPEN: 933 err = delete_attribute(type, kPreferredAppAttr); 934 break; 935 936 default: 937 err = B_BAD_VALUE; 938 break; 939 } 940 /*! \todo The R5 monitor makes no note of which app_verb value was updated. If 941 additional app_verb values besides \c B_OPEN are someday added, the format 942 of the MIME monitor messages will need to be augmented. 943 */ 944 if (!err) 945 err = SendMonitorUpdate(B_PREFERRED_APP_CHANGED, type, B_META_MIME_DELETED); 946 return err; 947 } 948 949 // DeleteSnifferRule 950 //! Deletes the sniffer rule for the given type 951 /*! A \c B_SNIFFER_RULE_CHANGED notification is sent to the mime monitor service, 952 and the corresponding rule is removed from the internal database of sniffer 953 rules. 954 \param type The mime type of interest 955 \return 956 - B_OK: success 957 - B_ENTRY_NOT_FOUND: no such attribute existed 958 - "error code": failure 959 */ 960 status_t 961 Database::DeleteSnifferRule(const char *type) 962 { 963 status_t err = delete_attribute(type, kSnifferRuleAttr); 964 if (!err) 965 err = fSnifferRules.DeleteSnifferRule(type); 966 if (!err) 967 err = SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type, B_META_MIME_DELETED); 968 return err; 969 } 970 971 // DeleteSupportedTypes 972 //! Deletes the supported types list for the given type 973 /*! A \c B_SUPPORTED_TYPES_CHANGED notification is sent to the mime monitor service. 974 If \c fullSync is \c true, the given type is removed from the internal list 975 of supporting applictions for each previously supported type. If \c fullSync 976 is \c false, the said removal will occur the next time SetSupportedTypes() or 977 DeleteSupportedTypes() is called with a \c true \c fullSync paramter, or 978 \c Delete() is called for the given type. 979 \param type The mime type of interest 980 \param fullSync Whether or not to remove the type as a supporting app for 981 all previously supported types 982 \return 983 - B_OK: success 984 - B_ENTRY_NOT_FOUND: no such attribute existed 985 - "error code": failure 986 */ 987 status_t 988 Database::DeleteSupportedTypes(const char *type, bool fullSync) 989 { 990 status_t err = delete_attribute(type, kSupportedTypesAttr); 991 // Update the supporting apps database. If fullSync is specified, 992 // do so even if the supported types attribute didn't exist, as 993 // stranded types *may* exist in the database due to previous 994 // calls to {Set,Delete}SupportedTypes() with fullSync == false. 995 if (!err) 996 err = fSupportingApps.DeleteSupportedTypes(type, fullSync); 997 else if (fullSync && err == B_ENTRY_NOT_FOUND) 998 fSupportingApps.DeleteSupportedTypes(type, fullSync); 999 // Send a monitor notification 1000 if (!err) 1001 err = SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type, B_META_MIME_DELETED); 1002 return err; 1003 } 1004 1005 // SendInstallNotification 1006 //! \brief Sends a \c B_MIME_TYPE_CREATED notification to the mime monitor service 1007 status_t 1008 Database::SendInstallNotification(const char *type) 1009 { 1010 // fInstalledTypes.AddType(type); 1011 status_t err = SendMonitorUpdate(B_MIME_TYPE_CREATED, type, B_META_MIME_MODIFIED); 1012 return err; 1013 } 1014 1015 // SendDeleteNotification 1016 //! \brief Sends a \c B_MIME_TYPE_DELETED notification to the mime monitor service 1017 status_t 1018 //! \brief Sends a \c B_MIME_TYPE_DELETED notification to the mime monitor service 1019 Database::SendDeleteNotification(const char *type) 1020 { 1021 // Tell the backend first 1022 // fInstalledTypes.RemoveType(type); 1023 status_t err = SendMonitorUpdate(B_MIME_TYPE_DELETED, type, B_META_MIME_MODIFIED); 1024 return err; 1025 } 1026 1027 // SendMonitorUpdate 1028 /*! \brief Sends an update notification to all BMessengers that have 1029 subscribed to the MIME Monitor service 1030 \param type The MIME type that was updated 1031 \param which Bitmask describing which attribute was updated 1032 \param extraType The MIME type to which the change is applies 1033 \param largeIcon \true if the the large icon was updated, \false if the 1034 small icon was updated 1035 */ 1036 status_t 1037 Database::SendMonitorUpdate(int32 which, const char *type, const char *extraType, bool largeIcon, int32 action) { 1038 BMessage msg(B_META_MIME_CHANGED); 1039 status_t err; 1040 1041 err = msg.AddInt32("be:which", which); 1042 if (!err) 1043 err = msg.AddString("be:type", type); 1044 if (!err) 1045 err = msg.AddString("be:extra_type", extraType); 1046 if (!err) 1047 err = msg.AddBool("be:large_icon", largeIcon); 1048 if (!err) 1049 err = msg.AddInt32("be:action", action); 1050 if (!err) 1051 err = SendMonitorUpdate(msg); 1052 return err; 1053 } 1054 1055 // SendMonitorUpdate 1056 /*! \brief Sends an update notification to all BMessengers that have 1057 subscribed to the MIME Monitor service 1058 \param type The MIME type that was updated 1059 \param which Bitmask describing which attribute was updated 1060 \param extraType The MIME type to which the change is applies 1061 */ 1062 status_t 1063 Database::SendMonitorUpdate(int32 which, const char *type, const char *extraType, int32 action) { 1064 BMessage msg(B_META_MIME_CHANGED); 1065 status_t err; 1066 1067 err = msg.AddInt32("be:which", which); 1068 if (!err) 1069 err = msg.AddString("be:type", type); 1070 if (!err) 1071 err = msg.AddString("be:extra_type", extraType); 1072 if (!err) 1073 err = msg.AddInt32("be:action", action); 1074 if (!err) 1075 err = SendMonitorUpdate(msg); 1076 return err; 1077 } 1078 1079 // SendMonitorUpdate 1080 /*! \brief Sends an update notification to all BMessengers that have 1081 subscribed to the MIME Monitor service 1082 \param type The MIME type that was updated 1083 \param which Bitmask describing which attribute was updated 1084 \param largeIcon \true if the the large icon was updated, \false if the 1085 small icon was updated 1086 */ 1087 status_t 1088 Database::SendMonitorUpdate(int32 which, const char *type, bool largeIcon, int32 action) { 1089 BMessage msg(B_META_MIME_CHANGED); 1090 status_t err; 1091 1092 err = msg.AddInt32("be:which", which); 1093 if (!err) 1094 err = msg.AddString("be:type", type); 1095 if (!err) 1096 err = msg.AddBool("be:large_icon", largeIcon); 1097 if (!err) 1098 err = msg.AddInt32("be:action", action); 1099 if (!err) 1100 err = SendMonitorUpdate(msg); 1101 return err; 1102 } 1103 1104 // SendMonitorUpdate 1105 /*! \brief Sends an update notification to all BMessengers that have 1106 subscribed to the MIME Monitor service 1107 \param type The MIME type that was updated 1108 \param which Bitmask describing which attribute was updated 1109 */ 1110 status_t 1111 Database::SendMonitorUpdate(int32 which, const char *type, int32 action) { 1112 BMessage msg(B_META_MIME_CHANGED); 1113 status_t err; 1114 1115 err = msg.AddInt32("be:which", which); 1116 if (!err) 1117 err = msg.AddString("be:type", type); 1118 if (!err) 1119 err = msg.AddInt32("be:action", action); 1120 if (!err) 1121 err = SendMonitorUpdate(msg); 1122 return err; 1123 } 1124 1125 // SendMonitorUpdate 1126 /*! \brief Sends an update notification to all BMessengers that have subscribed to 1127 the MIME Monitor service 1128 \param BMessage A preformatted MIME monitor message to be sent to all subscribers 1129 */ 1130 status_t 1131 Database::SendMonitorUpdate(BMessage &msg) { 1132 // DBG(OUT("Database::SendMonitorUpdate(BMessage&)\n")); 1133 status_t err; 1134 std::set<BMessenger>::const_iterator i; 1135 for (i = fMonitorMessengers.begin(); i != fMonitorMessengers.end(); i++) { 1136 status_t err = (*i).SendMessage(&msg, (BHandler*)NULL); 1137 if (err) 1138 DBG(OUT("Database::SendMonitorUpdate(BMessage&): BMessenger::SendMessage failed, 0x%lx\n", err)); 1139 } 1140 // DBG(OUT("Database::SendMonitorUpdate(BMessage&) done\n")); 1141 err = B_OK; 1142 return err; 1143 } 1144 1145 } // namespace Mime 1146 } // namespace Storage 1147 } // namespace BPrivate 1148 1149