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 * Jonas Sundström, jonas@kirilla.com 8 * Michael Lotz, mmlr@mlotz.ch 9 * Ingo Weinhold, ingo_weinhold@gmx.de 10 */ 11 12 13 #include <mime/MimeInfoUpdater.h> 14 15 #include <stdlib.h> 16 17 #include <AppFileInfo.h> 18 #include <Bitmap.h> 19 #include <File.h> 20 #include <fs_attr.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 28 29 static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS"; 30 31 32 static status_t 33 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite, 34 const char *type, BBitmap &icon, icon_size iconSize) 35 { 36 status_t err = appFileInfoRead.GetIconForType(type, &icon, iconSize); 37 if (err == B_OK) 38 err = appFileInfoWrite.SetIconForType(type, &icon, iconSize); 39 else if (err == B_ENTRY_NOT_FOUND) 40 err = appFileInfoWrite.SetIconForType(type, NULL, iconSize); 41 return err; 42 } 43 44 45 static status_t 46 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite, 47 const char *type) 48 { 49 uint8* data = NULL; 50 size_t size = 0; 51 52 status_t err = appFileInfoRead.GetIconForType(type, &data, &size); 53 if (err == B_OK) 54 err = appFileInfoWrite.SetIconForType(type, data, size); 55 else if (err == B_ENTRY_NOT_FOUND) 56 err = appFileInfoWrite.SetIconForType(type, NULL, size); 57 58 free(data); 59 60 return err; 61 } 62 63 64 static bool 65 is_shared_object_mime_type(const BString &type) 66 { 67 return type.ICompare(B_APP_MIME_TYPE) == 0; 68 } 69 70 71 namespace BPrivate { 72 namespace Storage { 73 namespace Mime { 74 75 76 MimeInfoUpdater::MimeInfoUpdater(Database* database, 77 DatabaseLocker* databaseLocker, int32 force) 78 : 79 MimeEntryProcessor(database, databaseLocker, force) 80 { 81 } 82 83 84 MimeInfoUpdater::~MimeInfoUpdater() 85 { 86 } 87 88 89 status_t 90 MimeInfoUpdater::Do(const entry_ref& entry, bool* _entryIsDir) 91 { 92 bool updateType = false; 93 bool updateAppInfo = false; 94 BNode node; 95 96 status_t err = node.SetTo(&entry); 97 if (!err && _entryIsDir) 98 *_entryIsDir = node.IsDirectory(); 99 if (!err) { 100 // If not forced, only update if the entry has no file type attribute 101 attr_info info; 102 if (fForce == B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL 103 || node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND) { 104 updateType = true; 105 } 106 updateAppInfo = (updateType 107 || fForce == B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE); 108 } 109 110 // guess the MIME type 111 BString type; 112 if (!err && (updateType || updateAppInfo)) { 113 AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker); 114 err = fDatabase->GuessMimeType(&entry, &type); 115 } 116 117 // update the MIME type 118 if (!err && updateType) { 119 ssize_t len = type.Length() + 1; 120 ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, type, 121 len); 122 if (bytes < B_OK) 123 err = bytes; 124 else 125 err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK); 126 } 127 128 // update the app file info attributes, if this is a shared object 129 BFile file; 130 BAppFileInfo appFileInfoRead; 131 BAppFileInfo appFileInfoWrite; 132 if (!err && updateAppInfo && node.IsFile() 133 && is_shared_object_mime_type(type) 134 && file.SetTo(&entry, B_READ_WRITE) == B_OK 135 && appFileInfoRead.SetTo(&file) == B_OK 136 && appFileInfoWrite.SetTo(&file) == B_OK) { 137 138 // we read from resources and write to attributes 139 appFileInfoRead.SetInfoLocation(B_USE_RESOURCES); 140 appFileInfoWrite.SetInfoLocation(B_USE_ATTRIBUTES); 141 142 // signature 143 char signature[B_MIME_TYPE_LENGTH]; 144 err = appFileInfoRead.GetSignature(signature); 145 if (err == B_OK) 146 err = appFileInfoWrite.SetSignature(signature); 147 else if (err == B_ENTRY_NOT_FOUND) 148 err = appFileInfoWrite.SetSignature(NULL); 149 if (err != B_OK) 150 return err; 151 152 // catalog entry 153 char catalogEntry[B_MIME_TYPE_LENGTH * 3]; 154 err = appFileInfoRead.GetCatalogEntry(catalogEntry); 155 if (err == B_OK) 156 err = appFileInfoWrite.SetCatalogEntry(catalogEntry); 157 else if (err == B_ENTRY_NOT_FOUND) 158 err = appFileInfoWrite.SetCatalogEntry(NULL); 159 if (err != B_OK) 160 return err; 161 162 // app flags 163 uint32 appFlags; 164 err = appFileInfoRead.GetAppFlags(&appFlags); 165 if (err == B_OK) { 166 err = appFileInfoWrite.SetAppFlags(appFlags); 167 } else if (err == B_ENTRY_NOT_FOUND) { 168 file.RemoveAttr(kAppFlagsAttribute); 169 err = B_OK; 170 } 171 if (err != B_OK) 172 return err; 173 174 // supported types 175 BMessage supportedTypes; 176 bool hasSupportedTypes = false; 177 err = appFileInfoRead.GetSupportedTypes(&supportedTypes); 178 if (err == B_OK) { 179 err = appFileInfoWrite.SetSupportedTypes(&supportedTypes); 180 hasSupportedTypes = true; 181 } else if (err == B_ENTRY_NOT_FOUND) 182 err = appFileInfoWrite.SetSupportedTypes(NULL); 183 if (err != B_OK) 184 return err; 185 186 // vector icon 187 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL); 188 if (err != B_OK) 189 return err; 190 191 // small icon 192 BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, 193 B_CMAP8); 194 if (smallIcon.InitCheck() != B_OK) 195 return smallIcon.InitCheck(); 196 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon, 197 B_MINI_ICON); 198 if (err != B_OK) 199 return err; 200 201 // large icon 202 BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, 203 B_CMAP8); 204 if (largeIcon.InitCheck() != B_OK) 205 return largeIcon.InitCheck(); 206 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon, 207 B_LARGE_ICON); 208 if (err != B_OK) 209 return err; 210 211 // version infos 212 const version_kind versionKinds[] 213 = {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND}; 214 for (int i = 0; i < 2; i++) { 215 version_kind kind = versionKinds[i]; 216 version_info versionInfo; 217 err = appFileInfoRead.GetVersionInfo(&versionInfo, kind); 218 if (err == B_OK) 219 err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind); 220 else if (err == B_ENTRY_NOT_FOUND) 221 err = appFileInfoWrite.SetVersionInfo(NULL, kind); 222 if (err != B_OK) 223 return err; 224 } 225 226 // icons for supported types 227 if (hasSupportedTypes) { 228 const char *supportedType; 229 for (int32 i = 0; 230 supportedTypes.FindString("types", i, &supportedType) == B_OK; 231 i++) { 232 // vector icon 233 err = update_icon(appFileInfoRead, appFileInfoWrite, 234 supportedType); 235 if (err != B_OK) 236 return err; 237 238 // small icon 239 err = update_icon(appFileInfoRead, appFileInfoWrite, 240 supportedType, smallIcon, B_MINI_ICON); 241 if (err != B_OK) 242 return err; 243 244 // large icon 245 err = update_icon(appFileInfoRead, appFileInfoWrite, 246 supportedType, largeIcon, B_LARGE_ICON); 247 if (err != B_OK) 248 return err; 249 } 250 } 251 } 252 253 return err; 254 } 255 256 257 } // namespace Mime 258 } // namespace Storage 259 } // namespace BPrivate 260