xref: /haiku/src/kits/storage/MimeType.cpp (revision b47e8b0cadeb9a9d985d7f72d2e9a099cbcb8f90)
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