www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - [RFC] std.mime design

reply 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
parent 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 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