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