digitalmars.D - [RFC] std.mime design
Johannes Pfau <spam example.com> writes:
I've been working a std.mime module for some time now, and I'd like to get some feedback on the API design: Here's the documentation for the current version: http://dl.dropbox.com/u/24218791/d/src/mime.html The freedesktop.org part is complete, the windows part will be added soon (the public API won't change) and it seems there's no API on OSX to get a MIME type for a file, so OSX will have to use the freedesktop.org backend. Here are some specific questions regarding the API design: * I think it's useful to have a global default database which is currently implemented through the global functions like getMimeType, getByData and getByName etc. However, the windows MIME support is very simple and only supports getting the mime type by file extension. So getByData, resolveAlias, typesEqual, isSubclass etc won't work on windows. Should those functions be moved to a FDO specific backend? Should the DataBases be classes so that FDODatabase can be a subclass with additional functionality and user code can check which backend is used? * Is it useful to have methods to load and unload additional databases to be used with the global functions? This would require all global functions to take a lock(ReadWriteMutex). Is it worth it? * If additional databases could be added to the default database lookup, which one should be preferred? For example, if a FDO database is loaded on a windows system, should the windows database or the FDO database be preferred? * It is of course always possible to load a FDOCache manually and use it's instance methods. The preceding questions only affect the global functions. * getTypeFromFS currently doesn't throw if the underlying filesystem doesn't support extended attributes. Consider an application reading a directory with 10_000 files. The app wants to check if the files are music files. If someone explicitly set the files content type, that information can be trusted. So the app calls getTypeFromFS on all 10_000 files. Now if the filesystem didn't support extended attributes and getTypeFromFS did throw, 10_000 exceptions would slow down the application a lot. It's also not possible to say: getTypeFromFS wasn't supported on file 1, so it won't be supported on all other 9_999 files. Those files could be part of a different filesystem, and that's hard/impossible to check. So is it OK in this case not to throw an Exception on a ENOTSUP error? * FDOCache currently uses strings instead of MimeTypes. I guess that should be changed? FDOCache needs some of these functions to return strings though, so I'd have to write wrapper functions taking & returning MimeTypes. * Some of the functions names are not optimal. Thoughts? * Feedback on the documentation is also appreciated. And a small implementation issue: I have to read strings from the mime.cache database files. How can I prevent to!string(char*) from reading past the end of the data buffer if a malformed file is loaded? Is there something like a cross-platform strnlen? -- Johannes Pfau
Oct 01 2011
Michel Fortin <michel.fortin michelf.com> writes:
On 2011-10-01 16:06:31 +0000, Johannes Pfau <spam example.com> said:The freedesktop.org part is complete, the windows part will be added soon (the public API won't change) and it seems there's no API on OSX to get a MIME type for a file, so OSX will have to use the freedesktop.org backend.
Mac OS X uses primarily Uniform Type Identifiers and maps all other kinds of type identifiers (extensions, MIME, HFS+ type codes) to UTIs. <http://developer.apple.com/library/mac/#documentation/FileManagement/Conceptual/understanding_utis/understand_utis_conc/understand_utis_conc.html#//apple_ref/doc/uid/TP40001319-CH202-CHDHIJDE> If you want to get the MIME type for a file, first get its UTI: const char * path; FSRef fileRef; FSPathMakeRef(path, &fileRef, NULL); CFStringRef uti = NULL; LSCopyItemAttribute(&fileRef, kLSRolesAll, kLSItemContentType, &uti); then ask for the preferred MIME type for this UTI: CFStringRef mime = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType); You might want to create a C string from that: size_t mime_c_str_length = CFStringLength(mime); // assuming ASCII here char *mime_c_str = malloc(mime_c_str_length+1); CFStringGetCString(mime, mime_c_str, mime_c_str_length+1, kCFStringEncodingUTF8); And once you're done, don't forget to release all those strings to avoid leaks: CFRelease(uti); CFRelease(mime); free(mime_c_str); -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 01 2011