1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //--------------------------------------------------------------------- 5 /*! 6 \file UpdateMimeInfoThread.h 7 UpdateMimeInfoThread implementation 8 */ 9 10 #include "UpdateMimeInfoThread.h" 11 12 #include <AppFileInfo.h> 13 #include <Bitmap.h> 14 #include <fs_attr.h> 15 #include <Message.h> 16 #include <MimeType.h> 17 #include <mime/database_support.h> 18 #include <Node.h> 19 20 namespace BPrivate { 21 namespace Storage { 22 namespace Mime { 23 24 static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS"; 25 26 // update_icon 27 static status_t 28 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite, 29 const char *type, BBitmap &icon, icon_size iconSize) 30 { 31 status_t err = appFileInfoRead.GetIconForType(type, &icon, iconSize); 32 if (err == B_OK) 33 err = appFileInfoWrite.SetIconForType(type, &icon, iconSize); 34 else if (err == B_ENTRY_NOT_FOUND) 35 err = appFileInfoWrite.SetIconForType(type, NULL, iconSize); 36 return err; 37 } 38 39 // update_icon 40 static status_t 41 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite, 42 const char *type) 43 { 44 uint8* data = NULL; 45 size_t size = 0; 46 47 status_t err = appFileInfoRead.GetIconForType(type, &data, &size); 48 if (err == B_OK) 49 err = appFileInfoWrite.SetIconForType(type, data, size); 50 else if (err == B_ENTRY_NOT_FOUND) 51 err = appFileInfoWrite.SetIconForType(type, NULL, size); 52 53 free(data); 54 55 return err; 56 } 57 58 // is_shared_object_mime_type 59 static bool 60 is_shared_object_mime_type(BMimeType &type) 61 { 62 return (type == B_APP_MIME_TYPE); 63 } 64 65 66 // constructor 67 //! Creates a new UpdateMimeInfoThread object 68 UpdateMimeInfoThread::UpdateMimeInfoThread(const char *name, int32 priority, 69 BMessenger managerMessenger, const entry_ref *root, bool recursive, 70 int32 force, BMessage *replyee) 71 : MimeUpdateThread(name, priority, managerMessenger, root, recursive, force, 72 replyee) 73 { 74 } 75 76 // DoMimeUpdate 77 /*! \brief Performs an update_mime_info() update on the given entry 78 79 If the entry has no \c BEOS:TYPE attribute, or if \c fForce is true, the 80 entry is sniffed and its \c BEOS:TYPE attribute is set accordingly. 81 */ 82 status_t 83 UpdateMimeInfoThread::DoMimeUpdate(const entry_ref *entry, bool *entryIsDir) 84 { 85 status_t err = entry ? B_OK : B_BAD_VALUE; 86 bool updateType = false; 87 bool updateAppInfo = false; 88 BNode node; 89 90 if (!err) 91 err = node.SetTo(entry); 92 if (!err && entryIsDir) 93 *entryIsDir = node.IsDirectory(); 94 if (!err) { 95 // If not forced, only update if the entry has no file type attribute 96 attr_info info; 97 if (fForce == B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL 98 || node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND) { 99 updateType = true; 100 } 101 updateAppInfo = (updateType 102 || fForce == B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE); 103 } 104 105 // guess the MIME type 106 BMimeType type; 107 if (!err && (updateType || updateAppInfo)) { 108 err = BMimeType::GuessMimeType(entry, &type); 109 if (!err) 110 err = type.InitCheck(); 111 } 112 113 // update the MIME type 114 if (!err && updateType) { 115 const char *typeStr = type.Type(); 116 ssize_t len = strlen(typeStr)+1; 117 ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, typeStr, 118 len); 119 if (bytes < B_OK) 120 err = bytes; 121 else 122 err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK); 123 } 124 125 // update the app file info attributes, if this is a shared object 126 BFile file; 127 BAppFileInfo appFileInfoRead; 128 BAppFileInfo appFileInfoWrite; 129 if (!err && updateAppInfo && node.IsFile() 130 && is_shared_object_mime_type(type) 131 && file.SetTo(entry, B_READ_WRITE) == B_OK 132 && appFileInfoRead.SetTo(&file) == B_OK 133 && appFileInfoWrite.SetTo(&file) == B_OK) { 134 135 // we read from resources and write to attributes 136 appFileInfoRead.SetInfoLocation(B_USE_RESOURCES); 137 appFileInfoWrite.SetInfoLocation(B_USE_ATTRIBUTES); 138 139 // signature 140 char signature[B_MIME_TYPE_LENGTH]; 141 err = appFileInfoRead.GetSignature(signature); 142 if (err == B_OK) 143 err = appFileInfoWrite.SetSignature(signature); 144 else if (err == B_ENTRY_NOT_FOUND) 145 err = appFileInfoWrite.SetSignature(NULL); 146 if (err != B_OK) 147 return err; 148 149 // app flags 150 uint32 appFlags; 151 err = appFileInfoRead.GetAppFlags(&appFlags); 152 if (err == B_OK) { 153 err = appFileInfoWrite.SetAppFlags(appFlags); 154 } else if (err == B_ENTRY_NOT_FOUND) { 155 file.RemoveAttr(kAppFlagsAttribute); 156 err = B_OK; 157 } 158 if (err != B_OK) 159 return err; 160 161 // supported types 162 BMessage supportedTypes; 163 bool hasSupportedTypes = false; 164 err = appFileInfoRead.GetSupportedTypes(&supportedTypes); 165 if (err == B_OK) { 166 err = appFileInfoWrite.SetSupportedTypes(&supportedTypes); 167 hasSupportedTypes = true; 168 } else if (err == B_ENTRY_NOT_FOUND) 169 err = appFileInfoWrite.SetSupportedTypes(NULL); 170 if (err != B_OK) 171 return err; 172 173 // vector icon 174 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL); 175 if (err != B_OK) 176 return err; 177 178 // small icon 179 BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, 180 B_CMAP8); 181 if (smallIcon.InitCheck() != B_OK) 182 return smallIcon.InitCheck(); 183 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon, 184 B_MINI_ICON); 185 if (err != B_OK) 186 return err; 187 188 // large icon 189 BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, 190 B_CMAP8); 191 if (largeIcon.InitCheck() != B_OK) 192 return largeIcon.InitCheck(); 193 err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon, 194 B_LARGE_ICON); 195 if (err != B_OK) 196 return err; 197 198 // version infos 199 const version_kind versionKinds[] 200 = {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND}; 201 for (int i = 0; i < 2; i++) { 202 version_kind kind = versionKinds[i]; 203 version_info versionInfo; 204 err = appFileInfoRead.GetVersionInfo(&versionInfo, kind); 205 if (err == B_OK) 206 err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind); 207 else if (err == B_ENTRY_NOT_FOUND) 208 err = appFileInfoWrite.SetVersionInfo(NULL, kind); 209 if (err != B_OK) 210 return err; 211 } 212 213 // icons for supported types 214 if (hasSupportedTypes) { 215 const char *supportedType; 216 for (int32 i = 0; 217 supportedTypes.FindString("types", i, &supportedType) == B_OK; 218 i++) { 219 // vector icon 220 err = update_icon(appFileInfoRead, appFileInfoWrite, 221 supportedType); 222 if (err != B_OK) 223 return err; 224 225 // small icon 226 err = update_icon(appFileInfoRead, appFileInfoWrite, 227 supportedType, smallIcon, B_MINI_ICON); 228 if (err != B_OK) 229 return err; 230 231 // large icon 232 err = update_icon(appFileInfoRead, appFileInfoWrite, 233 supportedType, largeIcon, B_LARGE_ICON); 234 if (err != B_OK) 235 return err; 236 } 237 } 238 } 239 240 return err; 241 } 242 243 } // namespace Mime 244 } // namespace Storage 245 } // namespace BPrivate 246 247