📄 mimetmac.cpp
字号:
else { outdictfile.Close(); wxLogDebug(wxT("Could not read in new dictionary")); } } else { wxLogDebug(wxString(wxT("Could not open [")) + sInfoPath + wxT("] for writing.")); } } else { wxLogDebug(wxT("No info dictionary in main bundle")); } } else { wxLogDebug(wxT("Can only call associate from bundled app within XXX.app")); } } else { wxLogDebug(wxT("No main bundle")); }#if defined(__DARWIN__) if (!bInfoSuccess) return NULL;#endif // on mac you have to embed it into the mac's file reference resource ('FREF' I believe) // or, alternately, you could just add an entry to m_hDatabase, but you'd need to get // the app's signature somehow... OSType processType, creator; OSStatus status = MoreProcGetProcessTypeSignature(NULL, &processType, &creator); if (status == noErr) { Str255 psCreatorName;#ifndef __LP64__ FSSpec dummySpec; status = FindApplication(creator, false, psCreatorName, &dummySpec);#else FSRef fsref; status = LSFindApplicationForInfo( creator, NULL, NULL, &fsref ,NULL); HFSUniStr255 name; status = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, &name, NULL, NULL); CFStringRef str = FSCreateStringFromHFSUniStr( 0 , &name ); CFStringGetPascalString(str, psCreatorName, 256, CFStringGetSystemEncoding()); CFRelease( str );#endif if (status == noErr) { //get the file type if it exists - //if it really does then modify the database then save it, //otherwise we need to create a whole new entry wxFileType* pFileType = GetFileTypeFromExtension(asExtensions[dwFoundIndex]); if (pFileType) { ICMapEntry entry; ICGetMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, pFileType->m_impl->m_lIndex, &entry ); memcpy(entry.creatorAppName, psCreatorName, sizeof(Str255)); entry.fileCreator = creator; status = ICSetMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, pFileType->m_impl->m_lIndex, &entry ); //success if (status == noErr) { return pFileType; //kICAttrNoChange means we don't care about attributes such as //locking in the database// status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping,// kICAttrNoChange, (Handle) m_hDatabase);// if (status == noErr)// return pFileType;// else// {// wxLogDebug(wxString::Format(wxT("%i - %s"), (int)status, wxT("ICSetPrefHandle failed.")));// } } else { wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetMapEntry failed."))); } // failure - cleanup delete pFileType; } else { // TODO: Maybe force all 3 of these to be non-empty? Str255 psExtension, psMimeType, psDescription; wxMacStringToPascal(wxString(wxT(".")) + ftInfo.GetExtensions()[0], psExtension); wxMacStringToPascal(ftInfo.GetMimeType(), psMimeType); wxMacStringToPascal(ftInfo.GetDescription(), psDescription); Str255 psPostCreatorName; wxMacStringToPascal(wxEmptyString, psPostCreatorName); //add the entry to the database ICMapEntry entry; entry.totalLength = sizeof(ICMapEntry); entry.fixedLength = kICMapFixedLength; entry.version = 0; entry.fileType = 0; //TODO: File type? entry.fileCreator = creator; entry.postCreator = 0; entry.flags = kICMapDataForkBit; //TODO: Maybe resource is valid by default too? PLstrcpy( entry.extension , psExtension ) ; memcpy(entry.creatorAppName, psCreatorName, sizeof(Str255)); memcpy(entry.postAppName, psPostCreatorName, sizeof(Str255)); memcpy(entry.MIMEType, psMimeType, sizeof(Str255)); memcpy(entry.entryName, psDescription, sizeof(Str255)); status = ICAddMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, &entry); if (status == noErr) { return GetFileTypeFromExtension(ftInfo.GetMimeType());// kICAttrNoChange means we don't care about attributes such as// locking in the database// status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping,// kICAttrNoChange, (Handle) m_hDatabase); // return the entry in the database if successful// if (status == noErr)// return GetFileTypeFromExtension(ftInfo.GetMimeType());// else// {// wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetPrefHandle failed."))); // } } else { wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICAppMapEntry failed."))); } } } // end if FindApplcation was successful else { wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("FindApplication failed."))); } } // end if it could obtain app's signature else { wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("GetProcessSignature failed."))); } return NULL;}boolwxMimeTypesManagerImpl::Unassociate(wxFileType *pFileType){ wxASSERT(pFileType); bool bInfoSuccess = false; wxArrayString asExtensions; pFileType->GetExtensions(asExtensions); if (!asExtensions.GetCount()) { wxLogDebug(wxT("Must have extension to disassociate")); return false; } // Find and write to Info.plist in main bundle (note that some other // apps have theirs named differently, i.e. IE's is named Info-macos.plist // some apps (non-wx) use the 'plst' resource instead CFBundleRef cfbMain = CFBundleGetMainBundle(); if (cfbMain) { UInt32 dwBundleType, dwBundleCreator; CFBundleGetPackageInfo(cfbMain, &dwBundleType, &dwBundleCreator); // if launching terminal non-app, version will be 'BNDL' (generic bundle, maybe in other cases too), // which will give us the incorrect info.plist path // otherwise it will be 'APPL', or in the case of a framework, 'FMWK' if (dwBundleType == 'APPL') { wxCFURL cfurlBundleLoc((CFTypeRef)CFBundleCopyBundleURL(cfbMain));// wxCFURL cfurlBundleLoc((CFTypeRef)CFBundleCopyExecutableURL(cfbMain)); wxString sInfoPath;// sInfoPath << wxT("file://"); sInfoPath << cfurlBundleLoc.BuildWXString(); sInfoPath << wxT("Contents/Info.plist");// wxCFDictionary cfdInfo( (CFTypeRef) CFBundleGetInfoDictionary(cfbMain), wxCF_RETAIN ); wxCFDictionary cfdInfo; bool bInfoOpenSuccess = false; wxFile indictfile; if (indictfile.Open(sInfoPath, wxFile::read)) { CFIndex cfiBufLen = (CFIndex) indictfile.Length(); const UInt8* pBuffer = new UInt8[cfiBufLen]; indictfile.Read((void*)pBuffer, cfiBufLen); wxCFData cfdaInDict(pBuffer, cfiBufLen); wxString sError; bInfoOpenSuccess = cfdInfo.ReadAsXML(cfdaInDict, &sError); if (!bInfoOpenSuccess) wxLogDebug(sError); indictfile.Close(); } if (bInfoOpenSuccess) { cfdInfo.MakeMutable( cfdInfo.GetCount() + 1 ); wxCFArray cfaDocTypes( cfdInfo[ wxCFString(wxT("CFBundleDocumentTypes")) ], wxCF_RETAIN ); if (cfaDocTypes.IsOk()) { bool bEntryFound = false; //search for duplicate CFIndex i; for (i = 0; i < cfaDocTypes.GetCount(); ++i) { wxCFDictionary cfdDocTypeEntry( cfaDocTypes[i], wxCF_RETAIN ); //A lot of apps dont do to mime types for some reason //so we go by extensions only wxCFArray cfaExtensions( cfdDocTypeEntry[ wxCFString(wxT("CFBundleTypeExtensions")) ], wxCF_RETAIN ); if (!cfaExtensions.IsOk()) continue; for (CFIndex iExt = 0; iExt < cfaExtensions.GetCount(); ++iExt) { for (size_t iWXExt = 0; iWXExt < asExtensions.GetCount(); ++iWXExt) { if (asExtensions[iWXExt] == wxCFString(cfaExtensions[iExt], wxCF_RETAIN).BuildWXString()) { bEntryFound = true; cfaDocTypes.Remove(i); cfdInfo.Set( wxCFString(wxT("CFBundleDocumentTypes")) , cfaDocTypes ); break; } } //end of wxstring array if (bEntryFound) break; } //end for cf array if (bEntryFound) break; }//end for doctypes if (bEntryFound) { cfdInfo.MakeValidXML(); wxFile outdictfile; if (outdictfile.Open(sInfoPath, wxFile::write)) { wxCFData cfdaInfo(cfdInfo.WriteAsXML()); if (cfdaInfo.IsOk()) { if (outdictfile.Write(cfdaInfo.GetValue(), cfdaInfo.GetCount()) != (wxFileOffset)cfdaInfo.GetCount()) { wxLogDebug(wxT("error in writing to file")); } else { bInfoSuccess = true;//#if defined(__DARWIN__)// //force launch services to update its database for the finder// OSStatus status = LSRegisterURL((CFURLRef)(CFTypeRef)cfurlBundleLoc, true);// if (status != noErr)// {// wxLogDebug(wxT("LSRegisterURL Failed."));// }//#endif } outdictfile.Close(); } else { outdictfile.Close(); wxLogDebug(wxT("Could not read in new dictionary")); } } else { wxLogDebug( wxString(wxT("Could not open [")) + sInfoPath + wxT("] for writing.")); } } else { wxLogDebug(wxT("Entry not found to remove")); wxString sPrintOut; wxCFDictionary::PrintOutArray(sPrintOut, (CFArrayRef)(CFTypeRef)cfaDocTypes); wxLogDebug(sPrintOut); for (size_t i = 0; i < asExtensions.GetCount(); ++i) wxLogDebug(asExtensions[i]); } } else { wxLogDebug(wxT("No doc types array found")); wxString sPrintOut; cfdInfo.PrintOut(sPrintOut); wxLogDebug(sPrintOut); } } else { wxLogDebug(wxT("No info dictionary in main bundle")); } } else { wxLogDebug(wxT("Can only call associate from bundled app within XXX.app")); } } else { wxLogDebug(wxT("No main bundle")); }#if defined(__DARWIN__) if (!bInfoSuccess) return false;#endif // this should be as easy as removing the entry from the database // and then saving the database OSStatus status = ICDeleteMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, pFileType->m_impl->m_lIndex); if (status == noErr) { return true; //kICAttrNoChange means we don't care about attributes such as //locking in the database// status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping,// kICAttrNoChange, (Handle) m_hDatabase);// if (status == noErr)// {// return true;// }// else// {// wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetPrefHandle failed.")));// } } else { wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICDeleteMapEntry failed."))); } return false;}#if 0 CFWriteStreamRef cfwsInfo = CFWriteStreamCreateWithFile( kCFAllocatorDefault, (CFURLRef) (CFTypeRef)cfurlInfoLoc );// CFShow(cfdInfo); if (cfwsInfo) { Boolean bOpened = CFWriteStreamOpen(cfwsInfo); if (bOpened) { CFStringRef cfsError; CFIndex cfiWritten = CFPropertyListWriteToStream((CFPropertyListRef)(CFTypeRef)cfdInfo, cfwsInfo, kCFPropertyListXMLFormat_v1_0, //100 &cfsError); if (cfsError && cfiWritten == 0) { wxLogDebug(wxCFString(cfsError).BuildWXString()); wxString sMessage; cfdInfo.PrintOut(sMessage); wxLogDebug(sMessage); } else { bInfoSuccess = true;//#if defined(__DARWIN__)// //force launch services to update its database for the finder// OSStatus status = LSRegisterURL((CFURLRef)(CFTypeRef)cfurlBundleLoc, true);// if (status != noErr)// {// wxLogDebug(wxT("LSRegisterURL Failed."));// }//#endif } CFWriteStreamClose(cfwsInfo);#endif#endif //wxUSE_MIMETYPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -