xref: /haiku/src/kits/storage/mime/AppMetaMimeCreator.cpp (revision 04a0e9c7b68cbe3a43d38e2bca8e860fd80936fb)
1  /*
2   * Copyright 2002-2013, Haiku, Inc. All Rights Reserved.
3   * Distributed under the terms of the MIT License.
4   *
5   * Authors:
6   *		Tyler Dauwalder
7   *		Axel Dörfler, axeld@pinc-software.de
8   *		Ingo Weinhold, ingo_weinhold@gmx.de
9   */
10  
11  
12  #include <mime/AppMetaMimeCreator.h>
13  
14  #include <stdlib.h>
15  
16  #include <AppFileInfo.h>
17  #include <Bitmap.h>
18  #include <File.h>
19  #include <fs_attr.h>
20  #include <Message.h>
21  #include <MimeType.h>
22  #include <String.h>
23  
24  #include <AutoLocker.h>
25  #include <mime/Database.h>
26  #include <mime/database_support.h>
27  #include <mime/DatabaseLocation.h>
28  
29  
30  namespace BPrivate {
31  namespace Storage {
32  namespace Mime {
33  
34  
35  AppMetaMimeCreator::AppMetaMimeCreator(Database* database,
36  	DatabaseLocker* databaseLocker, int32 force)
37  	:
38  	MimeEntryProcessor(database, databaseLocker, force)
39  {
40  }
41  
42  
43  AppMetaMimeCreator::~AppMetaMimeCreator()
44  {
45  }
46  
47  
48  status_t
49  AppMetaMimeCreator::Do(const entry_ref& entry, bool* _entryIsDir)
50  {
51  	BFile file;
52  	status_t status = file.SetTo(&entry, B_READ_ONLY | O_NOTRAVERSE);
53  	if (status < B_OK)
54  		return status;
55  
56  	bool isDir = file.IsDirectory();
57  	if (_entryIsDir != NULL)
58  		*_entryIsDir = isDir;
59  
60  	if (isDir || !file.IsFile())
61  		return B_OK;
62  
63  	BAppFileInfo appInfo(&file);
64  	status = appInfo.InitCheck();
65  	if (status < B_OK)
66  		return status;
67  
68  	// Read the app sig (which consequently keeps us from updating
69  	// non-applications, since we get an error if the file has no
70  	// app sig)
71  	BString signature;
72  	status = file.ReadAttrString("BEOS:APP_SIG", &signature);
73  	if (status != B_OK)
74  		return B_BAD_TYPE;
75  
76  	if (!BMimeType::IsValid(signature))
77  		return B_BAD_TYPE;
78  
79  	InstallNotificationDeferrer _(fDatabase, signature.String());
80  
81  	if (!fDatabase->Location()->IsInstalled(signature)) {
82  		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
83  		fDatabase->Install(signature);
84  	}
85  
86  	BNode typeNode;
87  	status = fDatabase->Location()->OpenType(signature, typeNode);
88  	if (status != B_OK)
89  		return status;
90  
91  	// Preferred App
92  	attr_info info;
93  	if (status == B_OK
94  		&& (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) {
95  		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
96  		status = fDatabase->SetPreferredApp(signature, signature);
97  	}
98  
99  	// Short Description (name of the application)
100  	if (status == B_OK
101  		&& (fForce
102  			|| typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) {
103  		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
104  		status = fDatabase->SetShortDescription(signature, entry.name);
105  	}
106  
107  	// App Hint
108  	if (status == B_OK
109  		&& (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) {
110  		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
111  		status = fDatabase->SetAppHint(signature, &entry);
112  	}
113  
114  	// Vector Icon
115  	if (status == B_OK
116  		&& (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) {
117  		uint8* data = NULL;
118  		size_t size = 0;
119  		if (appInfo.GetIcon(&data, &size) == B_OK) {
120  			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
121  			status = fDatabase->SetIcon(signature, data, size);
122  			free(data);
123  		}
124  	}
125  	// Mini Icon
126  	BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
127  	if (status == B_OK
128  		&& (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) {
129  		if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) {
130  			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
131  			status = fDatabase->SetIcon(signature, &miniIcon, B_MINI_ICON);
132  		}
133  	}
134  	// Large Icon
135  	BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
136  	if (status == B_OK
137  		&& (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) {
138  		if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) {
139  			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
140  			status = fDatabase->SetIcon(signature, &largeIcon, B_LARGE_ICON);
141  		}
142  	}
143  
144  	// Supported Types
145  	bool setSupportedTypes = false;
146  	BMessage supportedTypes;
147  	if (status == B_OK
148  		&& (fForce
149  			|| typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) {
150  		if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK)
151  			setSupportedTypes = true;
152  	}
153  
154  	// defer notifications for supported types
155  	const char* type;
156  	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
157  		fDatabase->DeferInstallNotification(type);
158  
159  	// set supported types
160  	if (setSupportedTypes) {
161  		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
162  		status = fDatabase->SetSupportedTypes(signature, &supportedTypes, true);
163  	}
164  
165  	// Icons for supported types
166  	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK;
167  		 i++) {
168  		// vector icon
169  		uint8* data = NULL;
170  		size_t size = 0;
171  		if (status == B_OK
172  			&& appInfo.GetIconForType(type, &data, &size) == B_OK) {
173  			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
174  			status = fDatabase->SetIconForType(signature, type, data, size);
175  			free(data);
176  		}
177  		// mini icon
178  		if (status == B_OK
179  			&& appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) {
180  			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
181  			status = fDatabase->SetIconForType(signature, type, &miniIcon,
182  				B_MINI_ICON);
183  		}
184  		// large icon
185  		if (status == B_OK
186  			&& appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) {
187  			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
188  			status = fDatabase->SetIconForType(signature, type, &largeIcon,
189  				B_LARGE_ICON);
190  		}
191  	}
192  
193  	// undefer notifications for supported types
194  	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
195  		fDatabase->UndeferInstallNotification(type);
196  
197  	return status;
198  }
199  
200  
201  } // namespace Mime
202  } // namespace Storage
203  } // namespace BPrivate
204