1/* 2 * Copyright 2002-2006 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel D��rfler, axeld@pinc-software.de 7 * Tyler Dauwalder 8 * Ingo Weinhold, bonefish@users.sf.net 9 */ 10 11 12#include "MimeType.h" 13 14#include <Bitmap.h> 15#include <mime/database_support.h> 16#include <mime/DatabaseLocation.h> 17#include <sniffer/Rule.h> 18#include <sniffer/Parser.h> 19 20#include <RegistrarDefs.h> 21#include <RosterPrivate.h> 22 23#include <ctype.h> 24#include <new> 25#include <stdio.h> 26#include <strings.h> 27 28 29using namespace BPrivate; 30 31// Private helper functions 32static bool isValidMimeChar(const char ch); 33 34using namespace BPrivate::Storage::Mime; 35using namespace std; 36 37const char* B_PEF_APP_MIME_TYPE = "application/x-be-executable"; 38const char* B_PE_APP_MIME_TYPE = "application/x-vnd.Be-peexecutable"; 39const char* B_ELF_APP_MIME_TYPE = "application/x-vnd.Be-elfexecutable"; 40const char* B_RESOURCE_MIME_TYPE = "application/x-be-resource"; 41const char* B_FILE_MIME_TYPE = "application/octet-stream"; 42// Might be defined platform depended, but ELF will certainly be the common 43// format for all platforms anyway. 44const char* B_APP_MIME_TYPE = B_ELF_APP_MIME_TYPE; 45 46 47static bool 48isValidMimeChar(const char ch) 49{ 50 // Handles white space and most CTLs 51 return ch > 32 52 && ch != '/' 53 && ch != '<' 54 && ch != '>' 55 && ch != '@' 56 && ch != ',' 57 && ch != ';' 58 && ch != ':' 59 && ch != '"' 60 && ch != '(' 61 && ch != ')' 62 && ch != '[' 63 && ch != ']' 64 && ch != '?' 65 && ch != '=' 66 && ch != '\\' 67 && ch != 127; // DEL 68} 69 70 71// #pragma mark - 72 73 74// Creates an uninitialized BMimeType object. 75BMimeType::BMimeType() 76 : 77 fType(NULL), 78 fCStatus(B_NO_INIT) 79{ 80} 81 82 83// Creates a BMimeType object and initializes it to the supplied 84// MIME type. 85BMimeType::BMimeType(const char* mimeType) 86 : 87 fType(NULL), 88 fCStatus(B_NO_INIT) 89{ 90 SetTo(mimeType); 91} 92 93 94// Frees all resources associated with this object. 95BMimeType::~BMimeType() 96{ 97 Unset(); 98} 99 100 101// Initializes this object to the supplied MIME type. 102status_t 103BMimeType::SetTo(const char* mimeType) 104{ 105 if (mimeType == NULL) { 106 Unset(); 107 } else if (!BMimeType::IsValid(mimeType)) { 108 fCStatus = B_BAD_VALUE; 109 } else { 110 Unset(); 111 fType = new(std::nothrow) char[strlen(mimeType) + 1]; 112 if (fType) { 113 strlcpy(fType, mimeType, B_MIME_TYPE_LENGTH); 114 fCStatus = B_OK; 115 } else { 116 fCStatus = B_NO_MEMORY; 117 } 118 } 119 return fCStatus; 120} 121 122 123// Returns the object to an uninitialized state 124void 125BMimeType::Unset() 126{ 127 delete [] fType; 128 fType = NULL; 129 fCStatus = B_NO_INIT; 130} 131 132 133// Returns the result of the most recent constructor or SetTo() call 134status_t 135BMimeType::InitCheck() const 136{ 137 return fCStatus; 138} 139 140 141// Returns the MIME string represented by this object 142const char* 143BMimeType::Type() const 144{ 145 return fType; 146} 147 148 149// Returns whether the object represents a valid MIME type 150bool 151BMimeType::IsValid() const 152{ 153 return InitCheck() == B_OK && BMimeType::IsValid(Type()); 154} 155 156 157// Returns whether this objects represents a supertype 158bool 159BMimeType::IsSupertypeOnly() const 160{ 161 if (fCStatus == B_OK) { 162 // We assume here fCStatus will be B_OK *only* if 163 // the MIME string is valid 164 size_t len = strlen(fType); 165 for (size_t i = 0; i < len; i++) { 166 if (fType[i] == '/') 167 return false; 168 } 169 return true; 170 } else 171 return false; 172} 173 174 175// Returns whether or not this type is currently installed in the 176// MIME database 177bool 178BMimeType::IsInstalled() const 179{ 180 return InitCheck() == B_OK 181 && default_database_location()->IsInstalled(Type()); 182} 183 184 185// Gets the supertype of the MIME type represented by this object 186status_t 187BMimeType::GetSupertype(BMimeType* supertype) const 188{ 189 if (supertype == NULL) 190 return B_BAD_VALUE; 191 192 supertype->Unset(); 193 status_t status = fCStatus == B_OK ? B_OK : B_BAD_VALUE; 194 if (status == B_OK) { 195 size_t len = strlen(fType); 196 size_t i = 0; 197 for (; i < len; i++) { 198 if (fType[i] == '/') 199 break; 200 } 201 if (i == len) { 202 // object is a supertype only 203 status = B_BAD_VALUE; 204 } else { 205 char superMime[B_MIME_TYPE_LENGTH]; 206 strncpy(superMime, fType, i); 207 superMime[i] = 0; 208 status = supertype->SetTo(superMime) == B_OK ? B_OK : B_BAD_VALUE; 209 } 210 } 211 212 return status; 213} 214 215 216// Returns whether this and the supplied MIME type are equal 217bool 218BMimeType::operator==(const BMimeType &type) const 219{ 220 if (InitCheck() == B_NO_INIT && type.InitCheck() == B_NO_INIT) 221 return true; 222 else if (InitCheck() == B_OK && type.InitCheck() == B_OK) 223 return strcasecmp(Type(), type.Type()) == 0; 224 225 return false; 226} 227 228 229// Returns whether this and the supplied MIME type are equal 230bool 231BMimeType::operator==(const char* type) const 232{ 233 BMimeType mime; 234 if (type) 235 mime.SetTo(type); 236 237 return (*this) == mime; 238} 239 240 241// Returns whether this MIME type is a supertype of or equals the 242// supplied one 243bool 244BMimeType::Contains(const BMimeType* type) const 245{ 246 if (type == NULL) 247 return false; 248 249 if (*this == *type) 250 return true; 251 252 BMimeType super; 253 if (type->GetSupertype(&super) == B_OK && *this == super) 254 return true; 255 return false; 256} 257 258 259// Adds the MIME type to the MIME database 260status_t 261BMimeType::Install() 262{ 263 status_t err = InitCheck(); 264 265 BMessage message(B_REG_MIME_INSTALL); 266 BMessage reply; 267 status_t result; 268 269 // Build and send the message, read the reply 270 if (err == B_OK) 271 err = message.AddString("type", Type()); 272 273 if (err == B_OK) 274 err = BRoster::Private().SendTo(&message, &reply, true); 275 276 if (err == B_OK) 277 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 278 279 if (err == B_OK) 280 err = reply.FindInt32("result", &result); 281 282 if (err == B_OK) 283 err = result; 284 285 return err; 286} 287 288 289// Removes the MIME type from the MIME database 290status_t 291BMimeType::Delete() 292{ 293 status_t err = InitCheck(); 294 295 BMessage message(B_REG_MIME_DELETE); 296 BMessage reply; 297 status_t result; 298 299 // Build and send the message, read the reply 300 if (err == B_OK) 301 err = message.AddString("type", Type()); 302 303 if (err == B_OK) 304 err = BRoster::Private().SendTo(&message, &reply, true); 305 306 if (err == B_OK) 307 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 308 309 if (err == B_OK) 310 err = reply.FindInt32("result", &result); 311 312 if (err == B_OK) 313 err = result; 314 315 return err; 316} 317 318 319// Fetches the large or mini icon associated with the MIME type 320status_t 321BMimeType::GetIcon(BBitmap* icon, icon_size size) const 322{ 323 if (icon == NULL) 324 return B_BAD_VALUE; 325 326 status_t err = InitCheck(); 327 if (err == B_OK) 328 err = default_database_location()->GetIcon(Type(), *icon, size); 329 330 return err; 331} 332 333 334// Fetches the vector icon associated with the MIME type 335status_t 336BMimeType::GetIcon(uint8** data, size_t* size) const 337{ 338 if (data == NULL || size == NULL) 339 return B_BAD_VALUE; 340 341 status_t err = InitCheck(); 342 if (err == B_OK) 343 err = default_database_location()->GetIcon(Type(), *data, *size); 344 345 return err; 346} 347 348 349// Fetches the signature of the MIME type's preferred application from the 350// MIME database 351status_t 352BMimeType::GetPreferredApp(char* signature, app_verb verb) const 353{ 354 status_t err = InitCheck(); 355 if (err == B_OK) { 356 err = default_database_location()->GetPreferredApp(Type(), signature, 357 verb); 358 } 359 360 return err; 361} 362 363 364// Fetches from the MIME database a BMessage describing the attributes 365// typically associated with files of the given MIME type 366status_t 367BMimeType::GetAttrInfo(BMessage* info) const 368{ 369 if (info == NULL) 370 return B_BAD_VALUE; 371 372 status_t err = InitCheck(); 373 if (err == B_OK) 374 err = default_database_location()->GetAttributesInfo(Type(), *info); 375 376 return err; 377} 378 379 380// Fetches the MIME type's associated filename extensions from the MIME 381// database 382status_t 383BMimeType::GetFileExtensions(BMessage* extensions) const 384{ 385 if (extensions == NULL) 386 return B_BAD_VALUE; 387 388 status_t err = InitCheck(); 389 if (err == B_OK) { 390 err = default_database_location()->GetFileExtensions(Type(), 391 *extensions); 392 } 393 394 return err; 395} 396 397 398// Fetches the MIME type's short description from the MIME database 399status_t 400BMimeType::GetShortDescription(char* description) const 401{ 402 status_t err = InitCheck(); 403 if (err == B_OK) { 404 err = default_database_location()->GetShortDescription(Type(), 405 description); 406 } 407 408 return err; 409} 410 411 412// Fetches the MIME type's long description from the MIME database 413status_t 414BMimeType::GetLongDescription(char* description) const 415{ 416 status_t err = InitCheck(); 417 if (err == B_OK) { 418 err = default_database_location()->GetLongDescription(Type(), 419 description); 420 } 421 422 return err; 423} 424 425 426// Fetches a \c BMessage containing a list of MIME signatures of 427// applications that are able to handle files of this MIME type. 428status_t 429BMimeType::GetSupportingApps(BMessage* signatures) const 430{ 431 if (signatures == NULL) 432 return B_BAD_VALUE; 433 434 BMessage message(B_REG_MIME_GET_SUPPORTING_APPS); 435 status_t result; 436 437 status_t err = InitCheck(); 438 if (err == B_OK) 439 err = message.AddString("type", Type()); 440 if (err == B_OK) 441 err = BRoster::Private().SendTo(&message, signatures, true); 442 if (err == B_OK) { 443 err = (status_t)(signatures->what == B_REG_RESULT ? B_OK 444 : B_BAD_REPLY); 445 } 446 if (err == B_OK) 447 err = signatures->FindInt32("result", &result); 448 if (err == B_OK) 449 err = result; 450 451 return err; 452} 453 454 455// Sets the large or mini icon for the MIME type 456status_t 457BMimeType::SetIcon(const BBitmap* icon, icon_size which) 458{ 459 return SetIconForType(NULL, icon, which); 460} 461 462 463// Sets the vector icon for the MIME type 464status_t 465BMimeType::SetIcon(const uint8* data, size_t size) 466{ 467 return SetIconForType(NULL, data, size); 468} 469 470 471// Sets the preferred application for the MIME type 472status_t 473BMimeType::SetPreferredApp(const char* signature, app_verb verb) 474{ 475 status_t err = InitCheck(); 476 477 BMessage message(signature && signature[0] 478 ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 479 BMessage reply; 480 status_t result; 481 482 // Build and send the message, read the reply 483 if (err == B_OK) 484 err = message.AddString("type", Type()); 485 486 if (err == B_OK) 487 err = message.AddInt32("which", B_REG_MIME_PREFERRED_APP); 488 489 if (err == B_OK && signature != NULL) 490 err = message.AddString("signature", signature); 491 492 if (err == B_OK) 493 err = message.AddInt32("app verb", verb); 494 495 if (err == B_OK) 496 err = BRoster::Private().SendTo(&message, &reply, true); 497 498 if (err == B_OK) 499 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 500 501 if (err == B_OK) 502 err = reply.FindInt32("result", &result); 503 504 if (err == B_OK) 505 err = result; 506 507 return err; 508} 509 510 511// Sets the description of the attributes typically associated with files 512// of the given MIME type 513status_t 514BMimeType::SetAttrInfo(const BMessage* info) 515{ 516 status_t err = InitCheck(); 517 518 BMessage message(info ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 519 BMessage reply; 520 status_t result; 521 522 // Build and send the message, read the reply 523 if (err == B_OK) 524 err = message.AddString("type", Type()); 525 if (err == B_OK) 526 err = message.AddInt32("which", B_REG_MIME_ATTR_INFO); 527 if (err == B_OK && info != NULL) 528 err = message.AddMessage("attr info", info); 529 if (err == B_OK) 530 err = BRoster::Private().SendTo(&message, &reply, true); 531 if (err == B_OK) 532 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 533 if (err == B_OK) 534 err = reply.FindInt32("result", &result); 535 if (err == B_OK) 536 err = result; 537 538 return err; 539} 540 541 542// Sets the list of filename extensions associated with the MIME type 543status_t 544BMimeType::SetFileExtensions(const BMessage* extensions) 545{ 546 status_t err = InitCheck(); 547 548 BMessage message(extensions ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 549 BMessage reply; 550 status_t result; 551 552 // Build and send the message, read the reply 553 if (err == B_OK) 554 err = message.AddString("type", Type()); 555 556 if (err == B_OK) 557 err = message.AddInt32("which", B_REG_MIME_FILE_EXTENSIONS); 558 559 if (err == B_OK && extensions != NULL) 560 err = message.AddMessage("extensions", extensions); 561 562 if (err == B_OK) 563 err = BRoster::Private().SendTo(&message, &reply, true); 564 565 if (err == B_OK) 566 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 567 568 if (err == B_OK) 569 err = reply.FindInt32("result", &result); 570 571 if (err == B_OK) 572 err = result; 573 574 return err; 575} 576 577 578// Sets the short description field for the MIME type 579status_t 580BMimeType::SetShortDescription(const char* description) 581{ 582 status_t err = InitCheck(); 583 584 BMessage message(description && description [0] 585 ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 586 BMessage reply; 587 status_t result; 588 589 // Build and send the message, read the reply 590 if (err == B_OK) 591 err = message.AddString("type", Type()); 592 593 if (err == B_OK) 594 err = message.AddInt32("which", B_REG_MIME_DESCRIPTION); 595 596 if (err == B_OK && description) 597 err = message.AddString("description", description); 598 599 if (err == B_OK) 600 err = message.AddBool("long", false); 601 602 if (err == B_OK) 603 err = BRoster::Private().SendTo(&message, &reply, true); 604 605 if (err == B_OK) 606 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 607 608 if (err == B_OK) 609 err = reply.FindInt32("result", &result); 610 611 if (err == B_OK) 612 err = result; 613 614 return err; 615} 616 617 618// Sets the long description field for the MIME type 619status_t 620BMimeType::SetLongDescription(const char* description) 621{ 622 status_t err = InitCheck(); 623 624 BMessage message(description && description[0] 625 ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 626 BMessage reply; 627 status_t result; 628 629 // Build and send the message, read the reply 630 if (err == B_OK) 631 err = message.AddString("type", Type()); 632 633 if (err == B_OK) 634 err = message.AddInt32("which", B_REG_MIME_DESCRIPTION); 635 636 if (err == B_OK && description) 637 err = message.AddString("description", description); 638 639 if (err == B_OK) 640 err = message.AddBool("long", true); 641 642 if (err == B_OK) 643 err = BRoster::Private().SendTo(&message, &reply, true); 644 645 if (err == B_OK) 646 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 647 648 if (err == B_OK) 649 err = reply.FindInt32("result", &result); 650 651 if (err == B_OK) 652 err = result; 653 654 return err; 655} 656 657 658// Fetches a BMessage listing all the MIME supertypes currently 659// installed in the MIME database. 660/*static*/ status_t 661BMimeType::GetInstalledSupertypes(BMessage* supertypes) 662{ 663 if (supertypes == NULL) 664 return B_BAD_VALUE; 665 666 BMessage message(B_REG_MIME_GET_INSTALLED_SUPERTYPES); 667 status_t result; 668 669 status_t err = BRoster::Private().SendTo(&message, supertypes, true); 670 if (err == B_OK) { 671 err = (status_t)(supertypes->what == B_REG_RESULT ? B_OK 672 : B_BAD_REPLY); 673 } 674 if (err == B_OK) 675 err = supertypes->FindInt32("result", &result); 676 if (err == B_OK) 677 err = result; 678 679 return err; 680} 681 682 683// Fetches a BMessage listing all the MIME types currently installed 684// in the MIME database. 685status_t 686BMimeType::GetInstalledTypes(BMessage* types) 687{ 688 return GetInstalledTypes(NULL, types); 689} 690 691 692// Fetches a BMessage listing all the MIME subtypes of the given 693// supertype currently installed in the MIME database. 694/*static*/ status_t 695BMimeType::GetInstalledTypes(const char* supertype, BMessage* types) 696{ 697 if (types == NULL) 698 return B_BAD_VALUE; 699 700 status_t result; 701 702 // Build and send the message, read the reply 703 BMessage message(B_REG_MIME_GET_INSTALLED_TYPES); 704 status_t err = B_OK; 705 706 if (supertype != NULL) 707 err = message.AddString("supertype", supertype); 708 if (err == B_OK) 709 err = BRoster::Private().SendTo(&message, types, true); 710 if (err == B_OK) 711 err = (status_t)(types->what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 712 if (err == B_OK) 713 err = types->FindInt32("result", &result); 714 if (err == B_OK) 715 err = result; 716 717 return err; 718} 719 720 721// Fetches a \c BMessage containing a list of MIME signatures of 722// applications that are able to handle files of any type. 723status_t 724BMimeType::GetWildcardApps(BMessage* wild_ones) 725{ 726 BMimeType mime; 727 status_t err = mime.SetTo("application/octet-stream"); 728 if (err == B_OK) 729 err = mime.GetSupportingApps(wild_ones); 730 return err; 731} 732 733 734// Returns whether the given string represents a valid MIME type. 735bool 736BMimeType::IsValid(const char* string) 737{ 738 if (string == NULL) 739 return false; 740 741 bool foundSlash = false; 742 size_t len = strlen(string); 743 if (len >= B_MIME_TYPE_LENGTH || len == 0) 744 return false; 745 746 for (size_t i = 0; i < len; i++) { 747 char ch = string[i]; 748 if (ch == '/') { 749 if (foundSlash || i == 0 || i == len - 1) 750 return false; 751 else 752 foundSlash = true; 753 } else if (!isValidMimeChar(ch)) { 754 return false; 755 } 756 } 757 return true; 758} 759 760 761// Fetches an \c entry_ref that serves as a hint as to where the MIME type's 762// preferred application might live 763status_t 764BMimeType::GetAppHint(entry_ref* ref) const 765{ 766 if (ref == NULL) 767 return B_BAD_VALUE; 768 769 status_t err = InitCheck(); 770 if (err == B_OK) 771 err = default_database_location()->GetAppHint(Type(), *ref); 772 return err; 773} 774 775 776// Sets the app hint field for the MIME type 777status_t 778BMimeType::SetAppHint(const entry_ref* ref) 779{ 780 status_t err = InitCheck(); 781 782 BMessage message(ref ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 783 BMessage reply; 784 status_t result; 785 786 // Build and send the message, read the reply 787 if (err == B_OK) 788 err = message.AddString("type", Type()); 789 790 if (err == B_OK) 791 err = message.AddInt32("which", B_REG_MIME_APP_HINT); 792 793 if (err == B_OK && ref != NULL) 794 err = message.AddRef("app hint", ref); 795 796 if (err == B_OK) 797 err = BRoster::Private().SendTo(&message, &reply, true); 798 799 if (err == B_OK) 800 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 801 802 if (err == B_OK) 803 err = reply.FindInt32("result", &result); 804 805 if (err == B_OK) 806 err = result; 807 808 return err; 809} 810 811 812// Fetches the large or mini icon used by an application of this type for 813// files of the given type. 814status_t 815BMimeType::GetIconForType(const char* type, BBitmap* icon, icon_size which) const 816{ 817 if (icon == NULL) 818 return B_BAD_VALUE; 819 820 // If type is NULL, this function works just like GetIcon(), othewise, 821 // we need to make sure the give type is valid. 822 status_t err; 823 if (type) { 824 err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; 825 if (err == B_OK) { 826 err = default_database_location()->GetIconForType(Type(), type, 827 *icon, which); 828 } 829 } else 830 err = GetIcon(icon, which); 831 832 return err; 833} 834 835 836// Fetches the vector icon used by an application of this type for files of 837// the given type. 838status_t 839BMimeType::GetIconForType(const char* type, uint8** _data, size_t* _size) const 840{ 841 if (_data == NULL || _size == NULL) 842 return B_BAD_VALUE; 843 844 // If type is NULL, this function works just like GetIcon(), otherwise, 845 // we need to make sure the give type is valid. 846 if (type == NULL) 847 return GetIcon(_data, _size); 848 849 if (!BMimeType::IsValid(type)) 850 return B_BAD_VALUE; 851 852 return default_database_location()->GetIconForType(Type(), type, *_data, 853 *_size); 854} 855 856 857// Sets the large or mini icon used by an application of this type for 858// files of the given type. 859status_t 860BMimeType::SetIconForType(const char* type, const BBitmap* icon, icon_size which) 861{ 862 status_t err = InitCheck(); 863 864 BMessage message(icon ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 865 BMessage reply; 866 status_t result; 867 868 void* data = NULL; 869 int32 dataSize; 870 871 // Build and send the message, read the reply 872 if (err == B_OK) 873 err = message.AddString("type", Type()); 874 875 if (err == B_OK) { 876 err = message.AddInt32("which", 877 type ? B_REG_MIME_ICON_FOR_TYPE : B_REG_MIME_ICON); 878 } 879 880 if (icon != NULL) { 881 if (err == B_OK) 882 err = get_icon_data(icon, which, &data, &dataSize); 883 884 if (err == B_OK) 885 err = message.AddData("icon data", B_RAW_TYPE, data, dataSize); 886 } 887 888 if (err == B_OK) 889 err = message.AddInt32("icon size", which); 890 891 if (type != NULL) { 892 if (err == B_OK) 893 err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; 894 895 if (err == B_OK) 896 err = message.AddString("file type", type); 897 } 898 899 if (err == B_OK) 900 err = BRoster::Private().SendTo(&message, &reply, true); 901 902 if (err == B_OK) 903 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 904 905 if (err == B_OK) 906 err = reply.FindInt32("result", &result); 907 908 if (err == B_OK) 909 err = result; 910 911 delete[] (int8*)data; 912 913 return err; 914} 915 916 917// Sets the large or mini icon used by an application of this type for 918// files of the given type. 919status_t 920BMimeType::SetIconForType(const char* type, const uint8* data, size_t dataSize) 921{ 922 status_t err = InitCheck(); 923 924 BMessage message(data ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 925 BMessage reply; 926 status_t result; 927 928 // Build and send the message, read the reply 929 if (err == B_OK) 930 err = message.AddString("type", Type()); 931 if (err == B_OK) 932 err = message.AddInt32("which", (type ? B_REG_MIME_ICON_FOR_TYPE : B_REG_MIME_ICON)); 933 if (data) { 934 if (err == B_OK) 935 err = message.AddData("icon data", B_RAW_TYPE, data, dataSize); 936 } 937 if (err == B_OK) 938 err = message.AddInt32("icon size", -1); 939 // -1 indicates size should be ignored (vector icon data) 940 if (type) { 941 if (err == B_OK) 942 err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; 943 if (err == B_OK) 944 err = message.AddString("file type", type); 945 } 946 if (err == B_OK) 947 err = BRoster::Private().SendTo(&message, &reply, true); 948 if (err == B_OK) 949 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 950 if (err == B_OK) 951 err = reply.FindInt32("result", &result); 952 if (err == B_OK) 953 err = result; 954 955 return err; 956} 957 958 959// Retrieves the MIME type's sniffer rule 960status_t 961BMimeType::GetSnifferRule(BString* result) const 962{ 963 if (result == NULL) 964 return B_BAD_VALUE; 965 966 status_t err = InitCheck(); 967 if (err == B_OK) 968 err = default_database_location()->GetSnifferRule(Type(), *result); 969 970 return err; 971} 972 973 974// Sets the MIME type's sniffer rule 975status_t 976BMimeType::SetSnifferRule(const char* rule) 977{ 978 status_t err = InitCheck(); 979 if (err == B_OK && rule != NULL && rule[0] != '\0') 980 err = CheckSnifferRule(rule, NULL); 981 982 if (err != B_OK) 983 return err; 984 985 BMessage message(rule && rule[0] ? B_REG_MIME_SET_PARAM 986 : B_REG_MIME_DELETE_PARAM); 987 BMessage reply; 988 status_t result; 989 990 // Build and send the message, read the reply 991 err = message.AddString("type", Type()); 992 if (err == B_OK) 993 err = message.AddInt32("which", B_REG_MIME_SNIFFER_RULE); 994 995 if (err == B_OK && rule) 996 err = message.AddString("sniffer rule", rule); 997 998 if (err == B_OK) 999 err = BRoster::Private().SendTo(&message, &reply, true); 1000 1001 if (err == B_OK) 1002 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1003 1004 if (err == B_OK) 1005 err = reply.FindInt32("result", &result); 1006 1007 if (err == B_OK) 1008 err = result; 1009 1010 return err; 1011} 1012 1013 1014// Checks whether a MIME sniffer rule is valid or not. 1015status_t 1016BMimeType::CheckSnifferRule(const char* rule, BString* parseError) 1017{ 1018 BPrivate::Storage::Sniffer::Rule snifferRule; 1019 1020 return BPrivate::Storage::Sniffer::parse(rule, &snifferRule, parseError); 1021} 1022 1023 1024// Guesses a MIME type for the entry referred to by the given 1025// entry_ref. 1026status_t 1027BMimeType::GuessMimeType(const entry_ref* file, BMimeType* type) 1028{ 1029 status_t err = file && type ? B_OK : B_BAD_VALUE; 1030 1031 BMessage message(B_REG_MIME_SNIFF); 1032 BMessage reply; 1033 status_t result; 1034 const char* str; 1035 1036 // Build and send the message, read the reply 1037 if (err == B_OK) 1038 err = message.AddRef("file ref", file); 1039 1040 if (err == B_OK) 1041 err = BRoster::Private().SendTo(&message, &reply, true); 1042 1043 if (err == B_OK) 1044 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1045 1046 if (err == B_OK) 1047 err = reply.FindInt32("result", &result); 1048 1049 if (err == B_OK) 1050 err = result; 1051 1052 if (err == B_OK) 1053 err = reply.FindString("mime type", &str); 1054 1055 if (err == B_OK) 1056 err = type->SetTo(str); 1057 1058 return err; 1059} 1060 1061 1062// Guesses a MIME type for the supplied chunk of data. 1063status_t 1064BMimeType::GuessMimeType(const void* buffer, int32 length, BMimeType* type) 1065{ 1066 status_t err = buffer && type ? B_OK : B_BAD_VALUE; 1067 1068 BMessage message(B_REG_MIME_SNIFF); 1069 BMessage reply; 1070 status_t result; 1071 const char* str; 1072 1073 // Build and send the message, read the reply 1074 if (err == B_OK) 1075 err = message.AddData("data", B_RAW_TYPE, buffer, length); 1076 1077 if (err == B_OK) 1078 err = BRoster::Private().SendTo(&message, &reply, true); 1079 1080 if (err == B_OK) 1081 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1082 1083 if (err == B_OK) 1084 err = reply.FindInt32("result", &result); 1085 1086 if (err == B_OK) 1087 err = result; 1088 1089 if (err == B_OK) 1090 err = reply.FindString("mime type", &str); 1091 1092 if (err == B_OK) 1093 err = type->SetTo(str); 1094 1095 return err; 1096} 1097 1098 1099// Guesses a MIME type for the given filename. 1100status_t 1101BMimeType::GuessMimeType(const char* filename, BMimeType* type) 1102{ 1103 status_t err = filename && type ? B_OK : B_BAD_VALUE; 1104 1105 BMessage message(B_REG_MIME_SNIFF); 1106 BMessage reply; 1107 status_t result; 1108 const char* str; 1109 1110 // Build and send the message, read the reply 1111 if (err == B_OK) 1112 err = message.AddString("filename", filename); 1113 1114 if (err == B_OK) 1115 err = BRoster::Private().SendTo(&message, &reply, true); 1116 1117 if (err == B_OK) 1118 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1119 1120 if (err == B_OK) 1121 err = reply.FindInt32("result", &result); 1122 1123 if (err == B_OK) 1124 err = result; 1125 1126 if (err == B_OK) 1127 err = reply.FindString("mime type", &str); 1128 1129 if (err == B_OK) 1130 err = type->SetTo(str); 1131 1132 return err; 1133} 1134 1135 1136// Starts monitoring the MIME database for a given target. 1137status_t 1138BMimeType::StartWatching(BMessenger target) 1139{ 1140 BMessage message(B_REG_MIME_START_WATCHING); 1141 BMessage reply; 1142 status_t result; 1143 status_t err; 1144 1145 // Build and send the message, read the reply 1146 err = message.AddMessenger("target", target); 1147 if (err == B_OK) 1148 err = BRoster::Private().SendTo(&message, &reply, true); 1149 1150 if (err == B_OK) 1151 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1152 1153 if (err == B_OK) 1154 err = reply.FindInt32("result", &result); 1155 1156 if (err == B_OK) 1157 err = result; 1158 1159 return err; 1160} 1161 1162 1163// Stops monitoring the MIME database for a given target 1164status_t 1165BMimeType::StopWatching(BMessenger target) 1166{ 1167 BMessage message(B_REG_MIME_STOP_WATCHING); 1168 BMessage reply; 1169 status_t result; 1170 status_t err; 1171 1172 // Build and send the message, read the reply 1173 err = message.AddMessenger("target", target); 1174 if (err == B_OK) 1175 err = BRoster::Private().SendTo(&message, &reply, true); 1176 1177 if (err == B_OK) 1178 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1179 1180 if (err == B_OK) 1181 err = reply.FindInt32("result", &result); 1182 1183 if (err == B_OK) 1184 err = result; 1185 1186 return err; 1187} 1188 1189 1190// Initializes this object to the supplied MIME type 1191status_t 1192BMimeType::SetType(const char* mimeType) 1193{ 1194 return SetTo(mimeType); 1195} 1196 1197 1198void BMimeType::_ReservedMimeType1() {} 1199void BMimeType::_ReservedMimeType2() {} 1200void BMimeType::_ReservedMimeType3() {} 1201 1202 1203#ifdef _BEOS_R5_COMPATIBLE_ 1204// assignment operator. 1205// Unimplemented 1206BMimeType& 1207BMimeType::operator=(const BMimeType &) 1208{ 1209 return *this; 1210 // not implemented 1211} 1212 1213 1214// copy constructor 1215// Unimplemented 1216BMimeType::BMimeType(const BMimeType &) 1217{ 1218} 1219#endif 1220 1221 1222status_t 1223BMimeType::GetSupportedTypes(BMessage* types) 1224{ 1225 if (types == NULL) 1226 return B_BAD_VALUE; 1227 1228 status_t err = InitCheck(); 1229 if (err == B_OK) 1230 err = default_database_location()->GetSupportedTypes(Type(), *types); 1231 1232 return err; 1233} 1234 1235 1236/*! Sets the list of MIME types supported by the MIME type (which is 1237 assumed to be an application signature). 1238 1239 If \a types is \c NULL the application's supported types are unset. 1240 1241 The supported MIME types must be stored in a field "types" of type 1242 \c B_STRING_TYPE in \a types. 1243 1244 For each supported type the result of BMimeType::GetSupportingApps() will 1245 afterwards include the signature of this application. 1246 1247 \a fullSync specifies whether or not any types that are no longer 1248 listed as supported types as of this call to SetSupportedTypes() shall be 1249 updated as well, i.e. whether this application shall be removed from their 1250 lists of supporting applications. 1251 1252 If \a fullSync is \c false, this application will not be removed from the 1253 previously supported types' supporting apps lists until the next call 1254 to BMimeType::SetSupportedTypes() or BMimeType::DeleteSupportedTypes() 1255 with a \c true \a fullSync parameter, the next call to BMimeType::Delete(), 1256 or the next reboot. 1257 1258 \param types The supported types to be assigned to the file. 1259 May be \c NULL. 1260 \param fullSync \c true to also synchronize the previously supported 1261 types, \c false otherwise. 1262 1263 \returns \c B_OK on success or another error code on failure. 1264*/ 1265status_t 1266BMimeType::SetSupportedTypes(const BMessage* types, bool fullSync) 1267{ 1268 status_t err = InitCheck(); 1269 1270 // Build and send the message, read the reply 1271 BMessage message(types ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); 1272 BMessage reply; 1273 status_t result; 1274 1275 if (err == B_OK) 1276 err = message.AddString("type", Type()); 1277 1278 if (err == B_OK) 1279 err = message.AddInt32("which", B_REG_MIME_SUPPORTED_TYPES); 1280 1281 if (err != B_OK && types != NULL) 1282 err = message.AddMessage("types", types); 1283 1284 if (err == B_OK) 1285 err = message.AddBool("full sync", fullSync); 1286 1287 if (err == B_OK) 1288 err = BRoster::Private().SendTo(&message, &reply, true); 1289 1290 if (err == B_OK) 1291 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1292 1293 if (err == B_OK) 1294 err = reply.FindInt32("result", &result); 1295 1296 if (err == B_OK) 1297 err = result; 1298 1299 return err; 1300} 1301 1302 1303/*! Returns a list of mime types associated with the given file extension 1304 1305 The list of types is returned in the pre-allocated \c BMessage pointed to 1306 by \a types. The types are stored in the message's "types" field, which 1307 is an array of \c B_STRING_TYPE values. 1308 1309 \param extension The file extension of interest 1310 \param types Pointer to a pre-allocated BMessage into which the result will 1311 be stored. 1312 1313 \returns \c B_OK on success or another error code on failure. 1314*/ 1315status_t 1316BMimeType::GetAssociatedTypes(const char* extension, BMessage* types) 1317{ 1318 status_t err = extension && types ? B_OK : B_BAD_VALUE; 1319 1320 BMessage message(B_REG_MIME_GET_ASSOCIATED_TYPES); 1321 BMessage &reply = *types; 1322 status_t result; 1323 1324 // Build and send the message, read the reply 1325 if (err == B_OK) 1326 err = message.AddString("extension", extension); 1327 1328 if (err == B_OK) 1329 err = BRoster::Private().SendTo(&message, &reply, true); 1330 1331 if (err == B_OK) 1332 err = (status_t)(reply.what == B_REG_RESULT ? B_OK : B_BAD_REPLY); 1333 1334 if (err == B_OK) 1335 err = reply.FindInt32("result", &result); 1336 1337 if (err == B_OK) 1338 err = result; 1339 1340 return err; 1341} 1342