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
29 using namespace BPrivate;
30
31 // Private helper functions
32 static bool isValidMimeChar(const char ch);
33
34 using namespace BPrivate::Storage::Mime;
35 using namespace std;
36
37 const char* B_PEF_APP_MIME_TYPE = "application/x-be-executable";
38 const char* B_PE_APP_MIME_TYPE = "application/x-vnd.Be-peexecutable";
39 const char* B_ELF_APP_MIME_TYPE = "application/x-vnd.Be-elfexecutable";
40 const char* B_RESOURCE_MIME_TYPE = "application/x-be-resource";
41 const 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.
44 const char* B_APP_MIME_TYPE = B_ELF_APP_MIME_TYPE;
45
46
47 static bool
isValidMimeChar(const char ch)48 isValidMimeChar(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.
BMimeType()75 BMimeType::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.
BMimeType(const char * mimeType)85 BMimeType::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.
~BMimeType()95 BMimeType::~BMimeType()
96 {
97 Unset();
98 }
99
100
101 // Initializes this object to the supplied MIME type.
102 status_t
SetTo(const char * mimeType)103 BMimeType::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
124 void
Unset()125 BMimeType::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
134 status_t
InitCheck() const135 BMimeType::InitCheck() const
136 {
137 return fCStatus;
138 }
139
140
141 // Returns the MIME string represented by this object
142 const char*
Type() const143 BMimeType::Type() const
144 {
145 return fType;
146 }
147
148
149 // Returns whether the object represents a valid MIME type
150 bool
IsValid() const151 BMimeType::IsValid() const
152 {
153 return InitCheck() == B_OK && BMimeType::IsValid(Type());
154 }
155
156
157 // Returns whether this objects represents a supertype
158 bool
IsSupertypeOnly() const159 BMimeType::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
177 bool
IsInstalled() const178 BMimeType::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
186 status_t
GetSupertype(BMimeType * supertype) const187 BMimeType::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
217 bool
operator ==(const BMimeType & type) const218 BMimeType::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
230 bool
operator ==(const char * type) const231 BMimeType::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
243 bool
Contains(const BMimeType * type) const244 BMimeType::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
260 status_t
Install()261 BMimeType::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
290 status_t
Delete()291 BMimeType::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
320 status_t
GetIcon(BBitmap * icon,icon_size size) const321 BMimeType::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
335 status_t
GetIcon(uint8 ** data,size_t * size) const336 BMimeType::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
351 status_t
GetPreferredApp(char * signature,app_verb verb) const352 BMimeType::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
366 status_t
GetAttrInfo(BMessage * info) const367 BMimeType::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
382 status_t
GetFileExtensions(BMessage * extensions) const383 BMimeType::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
399 status_t
GetShortDescription(char * description) const400 BMimeType::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
413 status_t
GetLongDescription(char * description) const414 BMimeType::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.
428 status_t
GetSupportingApps(BMessage * signatures) const429 BMimeType::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
456 status_t
SetIcon(const BBitmap * icon,icon_size which)457 BMimeType::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
464 status_t
SetIcon(const uint8 * data,size_t size)465 BMimeType::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
472 status_t
SetPreferredApp(const char * signature,app_verb verb)473 BMimeType::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
513 status_t
SetAttrInfo(const BMessage * info)514 BMimeType::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
543 status_t
SetFileExtensions(const BMessage * extensions)544 BMimeType::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
579 status_t
SetShortDescription(const char * description)580 BMimeType::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
619 status_t
SetLongDescription(const char * description)620 BMimeType::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
GetInstalledSupertypes(BMessage * supertypes)661 BMimeType::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.
685 status_t
GetInstalledTypes(BMessage * types)686 BMimeType::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
GetInstalledTypes(const char * supertype,BMessage * types)695 BMimeType::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.
723 status_t
GetWildcardApps(BMessage * wild_ones)724 BMimeType::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.
735 bool
IsValid(const char * string)736 BMimeType::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
763 status_t
GetAppHint(entry_ref * ref) const764 BMimeType::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
777 status_t
SetAppHint(const entry_ref * ref)778 BMimeType::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.
814 status_t
GetIconForType(const char * type,BBitmap * icon,icon_size which) const815 BMimeType::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.
838 status_t
GetIconForType(const char * type,uint8 ** _data,size_t * _size) const839 BMimeType::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.
859 status_t
SetIconForType(const char * type,const BBitmap * icon,icon_size which)860 BMimeType::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.
919 status_t
SetIconForType(const char * type,const uint8 * data,size_t dataSize)920 BMimeType::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
960 status_t
GetSnifferRule(BString * result) const961 BMimeType::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
975 status_t
SetSnifferRule(const char * rule)976 BMimeType::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.
1015 status_t
CheckSnifferRule(const char * rule,BString * parseError)1016 BMimeType::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.
1026 status_t
GuessMimeType(const entry_ref * file,BMimeType * type)1027 BMimeType::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.
1063 status_t
GuessMimeType(const void * buffer,int32 length,BMimeType * type)1064 BMimeType::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.
1100 status_t
GuessMimeType(const char * filename,BMimeType * type)1101 BMimeType::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.
1137 status_t
StartWatching(BMessenger target)1138 BMimeType::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
1164 status_t
StopWatching(BMessenger target)1165 BMimeType::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
1191 status_t
SetType(const char * mimeType)1192 BMimeType::SetType(const char* mimeType)
1193 {
1194 return SetTo(mimeType);
1195 }
1196
1197
_ReservedMimeType1()1198 void BMimeType::_ReservedMimeType1() {}
_ReservedMimeType2()1199 void BMimeType::_ReservedMimeType2() {}
_ReservedMimeType3()1200 void BMimeType::_ReservedMimeType3() {}
1201
1202
1203 #ifdef __HAIKU_BEOS_COMPATIBLE
1204 // assignment operator.
1205 // Unimplemented
1206 BMimeType&
operator =(const BMimeType &)1207 BMimeType::operator=(const BMimeType &)
1208 {
1209 return *this;
1210 // not implemented
1211 }
1212
1213
1214 // copy constructor
1215 // Unimplemented
BMimeType(const BMimeType &)1216 BMimeType::BMimeType(const BMimeType &)
1217 {
1218 }
1219 #endif
1220
1221
1222 status_t
GetSupportedTypes(BMessage * types)1223 BMimeType::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 */
1265 status_t
SetSupportedTypes(const BMessage * types,bool fullSync)1266 BMimeType::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 */
1315 status_t
GetAssociatedTypes(const char * extension,BMessage * types)1316 BMimeType::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