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, false); 40 else if (err == B_ENTRY_NOT_FOUND) 41 err = appFileInfoWrite.SetIconForType(type, NULL, iconSize, false); 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, false); 56 else if (err == B_ENTRY_NOT_FOUND) 57 err = appFileInfoWrite.SetIconForType(type, NULL, size, false); 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, false, 181 false); 182 hasSupportedTypes = true; 183 } else if (err == B_ENTRY_NOT_FOUND) 184 err = appFileInfoWrite.SetSupportedTypes(NULL, false, false); 185 if (err != B_OK) 186 return err; 187 188 // vector icon 189 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL); 190 if (err != B_OK) 191 return err; 192 193 // small icon 194 BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, 195 B_CMAP8); 196 if (smallIcon.InitCheck() != B_OK) 197 return smallIcon.InitCheck(); 198 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon, 199 B_MINI_ICON); 200 if (err != B_OK) 201 return err; 202 203 // large icon 204 BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, 205 B_CMAP8); 206 if (largeIcon.InitCheck() != B_OK) 207 return largeIcon.InitCheck(); 208 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon, 209 B_LARGE_ICON); 210 if (err != B_OK) 211 return err; 212 213 // version infos 214 const version_kind versionKinds[] 215 = {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND}; 216 for (int i = 0; i < 2; i++) { 217 version_kind kind = versionKinds[i]; 218 version_info versionInfo; 219 err = appFileInfoRead.GetVersionInfo(&versionInfo, kind); 220 if (err == B_OK) 221 err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind); 222 else if (err == B_ENTRY_NOT_FOUND) 223 err = appFileInfoWrite.SetVersionInfo(NULL, kind); 224 if (err != B_OK) 225 return err; 226 } 227 228 // icons for supported types 229 if (hasSupportedTypes) { 230 const char *supportedType; 231 for (int32 i = 0; 232 supportedTypes.FindString("types", i, &supportedType) == B_OK; 233 i++) { 234 // vector icon 235 err = update_icon(appFileInfoRead, appFileInfoWrite, 236 supportedType); 237 if (err != B_OK) 238 return err; 239 240 // small icon 241 err = update_icon(appFileInfoRead, appFileInfoWrite, 242 supportedType, smallIcon, B_MINI_ICON); 243 if (err != B_OK) 244 return err; 245 246 // large icon 247 err = update_icon(appFileInfoRead, appFileInfoWrite, 248 supportedType, largeIcon, B_LARGE_ICON); 249 if (err != B_OK) 250 return err; 251 } 252 } 253 } 254 255 return err; 256 } 257 258 259 } // namespace Mime 260 } // namespace Storage 261 } // namespace BPrivate 262