[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] MIME type guessing improved for *nix systems

From: Matthew Hambley <matthew_at_therealm.demon.co.uk>
Date: 2003-03-29 17:01:58 CET

This patch improves subversions ability to guess the MIME type of a file as
it is added or imported. It does this on *nix systems by interogating the
mime.types file. Other platforms may have more appropriate mechanisms.
(for instance on Risc OS a call to the MIME map module) Quite frankly the
build mechanism scares the willies out of me so I have left well alone. If
someone can tell me why my unit tests don't get run I would be greatful.
Also I need a #define to let me know if the target platform is *nix or not.

Proposed log entries:

include/svn_mime.h
   New file.
   (svn_mime_guess_type_from_file) Accepts a filename and returns a best
     guess at the MIME type for that file.

include/svn_io.h
   (svn_io_detect_mimetype) Removed this function as it is replaced by
     svn_mime_guess_type_from_file.

libsvn_wc/adm_ops.c
   (svn_wc_add) Altered to use svn_mime_guess_type_from_file instead of
     svn_io_detect_mimetype

libsvn_subr/mime_nix.c
   New file.
   (white_space_found) Local inline function. Returns true if character
     passed in is one of ' ', '\t' or '\n'
   (comment_found) Local inline function. Returns true if character passed
     in is '#'
   (eol_found) Local inline function. Returns true if character passed in
     is '\n'
   (find_mime_type_nix) New local function which accepts a fie extension and
     returns the MIME type if a mapping was found.
   (svn_mime_type_from_file_nix) New function. Accepts a filename and
     returns the MIME type if a mapping was found.

libsvn_subr/io.c
   (svn_io_detect_mimetype) Function removed as it is replaced by
     svn_mime_guess_type_from_file.

libsvn_subr/svn_mime.c
   New file
   (statistical_scan) New function which uses the same code as
     svn_io_detect_mimetype to determine the MIME type of a file based on
     counting the number of ASCII/non-ASCII characters in the file.
   (svn_mime_guess_type_from_file) New function. The public interface to
     the MIME type guessing code. Accepts a filename and returns the best
     guess for the MIME type.

libsvn_client/commit.c
   (import_file) Altered to use svn_mime_guess_type_from_file instead of
     svn_io_detect_mimetype.

tests/libsvn_subr/mime-test.c
   New file
   (identify_file_test, identify_extension_test) New functions. Local
     functions to perform generic tests.
   (test_unextenshion ed_text_file, test_unextensioned_binary_file,
    test_unextensioned_mostly_text_file, test_extensioned_text_file,
    test_extensioned_binary_file, test_extensioned_mostly_text_file,
    test_no_such_extension_text_file, test_no_such_extension_binary_file,
    test_no_such_extension_mostly_text_file, test_missing_subject_file)
     New functions. Various unit tests for the MIME type sub-system.

tests/libsvn_subr/mime-test-text
   New file. A simple HTML document for testing purposes.

tests/libsvn_subr/mime-tests-binary
   New file. A tiny PNG for testing purposes.

tests/libsvn_subr/mime-tests-mostly-text
   New file. A short text file with a few non-text characters in it.

build.conf
   Added the MIME type unit tests to the test build.

-- 
(\/)atthew )-(ambley

Index: subversion/include/svn_mime.h
===================================================================
--- subversion/include/svn_mime.h (working copy)
+++ subversion/include/svn_mime.h (working copy)
@@ -0,0 +1,28 @@
+/*****************************************************************************
+ * svn_mime.h *
+ *****************************************************************************/
+
+#ifndef SVN_MIME_H
+#define SVN_MIME_H
+
+#include <apr.h>
+#include <apr_pools.h>
+
+#include "svn_types.h"
+
+/** Find the mime type of a file.
+ *
+ * Examine utf8-encoded @a file to determine if it can be described by a
+ * known (as in, known by this function) Multipurpose Internet Mail
+ * Extension (MIME) type. If so, set @a mimetype to a character string
+ * describing the MIME type, else set it to @c NULL. Use @a pool for any
+ * necessary allocations.
+ */
+
+svn_error_t *svn_mime_guess_type_from_file(const char **type,
+ const char *filename,
+ apr_pool_t *pool);
+
+#endif /* SVN_MIME_H */
+
+/*****************************************************************************/
Index: subversion/include/svn_io.h
===================================================================
--- subversion/include/svn_io.h (revision 5492)
+++ subversion/include/svn_io.h (working copy)
@@ -615,20 +615,6 @@
                                const char *diff3_cmd,
                                apr_pool_t *pool);
 
-
-/** Find the mime type of a file.
- *
- * Examine utf8-encoded @a file to determine if it can be described by a
- * known (as in, known by this function) Multipurpose Internet Mail
- * Extension (MIME) type. If so, set @a mimetype to a character string
- * describing the MIME type, else set it to @c NULL. Use @a pool for any
- * necessary allocations.
- */
-svn_error_t *svn_io_detect_mimetype (const char **mimetype,
- const char *file,
- apr_pool_t *pool);
-
-
 /** Wrapper for @c apr_file_open().
  *
  * Wrapper for @c apr_file_open(), which see. @a fname is utf8-encoded.
Index: subversion/libsvn_wc/adm_ops.c
===================================================================
--- subversion/libsvn_wc/adm_ops.c (revision 5492)
+++ subversion/libsvn_wc/adm_ops.c (working copy)
@@ -967,7 +967,7 @@
          values in the original file. */
       if (! copyfrom_url)
         {
- SVN_ERR (svn_io_detect_mimetype (&mimetype, path, pool));
+ SVN_ERR (svn_mime_guess_type_from_file(&mimetype, path, pool));
           if (mimetype)
             {
               svn_string_t mt_str;
Index: subversion/libsvn_subr/mime_nix.c
===================================================================
--- subversion/libsvn_subr/mime_nix.c (working copy)
+++ subversion/libsvn_subr/mime_nix.c (working copy)
@@ -0,0 +1,295 @@
+/*****************************************************************************
+ * mime_nix.c : Map files to mime types *
+ * *
+ * Uses the mime.types file. Currently does not take into account the *
+ * psibility of a local .mimetypes file. *
+ *****************************************************************************/
+
+/* This def doesn't exist, but it needs to and I can't work out how to
+ clobber the build process to include it. */
+
+/*#ifdef SVN_NIX*/
+
+
+#include <apr_file_info.h>
+#include <apr_file_io.h>
+#include "svn_private_config.h"
+#include "svn_mime.h"
+#include "svn_error.h"
+#include "svn_string.h"
+
+#include <string.h>
+
+/*****************************************************************************
+ Constants
+ *****************************************************************************/
+
+#define GLOBAL_MAP_FILE "/etc/mime.types"
+#define LOCAL_MAP_FILE "~/.mimetypes"
+
+#define PARSE_BUFFER_SIZE 10
+
+/*****************************************************************************
+ Inline character identifier functions
+ *****************************************************************************/
+
+inline int
+white_space_found (char Character)
+{
+ return (Character == ' ')
+ || (Character == '\t')
+ || (Character == '\n');
+}
+
+inline int
+comment_found (char Character)
+{
+ return (Character == '#');
+}
+
+inline int
+eol_found (char Character)
+{
+ return (Character == '\n');
+}
+
+
+/*****************************************************************************
+ Internal function to interogate the MIME map file
+
+ THOUGHTS: Idealy what is needed here is a call to an external library which
+ keeps the MIME map in an easily searchable form in memory. This
+ would result in a great speed up. As it is we have to search the
+ file (which may not be in order) each time.
+ *****************************************************************************/
+
+svn_error_t *
+find_mime_type_nix (const char **type,
+ const char *extension,
+ apr_pool_t *pool)
+{
+ svn_error_t *Result = SVN_NO_ERROR;
+
+ svn_node_kind_t NodeKind;
+ apr_file_t *FHandle;
+ apr_status_t OK;
+
+ svn_string_t *ExtensionStr = svn_string_create(extension, pool);
+ svn_stringbuf_t *CurrentType = svn_stringbuf_create("", pool),
+ *CurrentExtension = svn_stringbuf_create("", pool);
+
+ char ParseBuffer[PARSE_BUFFER_SIZE],
+ Grabbed;
+ int ParseBufferIndex;
+
+ enum {StartOfLine, SkippingComment,
+ SkippingLeadingSpace, GrabbingType,
+ SkippingMiddleSpace, GrabbingExtension,
+ GotExtension, EndOfLine, FoundExtension} ParseState;
+
+ /* The MIME type defaults to 'none' */
+
+ *type = NULL;
+
+ /* Check that the map file exists */
+
+ SVN_ERR (svn_io_check_path (GLOBAL_MAP_FILE, &NodeKind, pool));
+ if (NodeKind != svn_node_file)
+ {
+ return svn_error_createf (SVN_ERR_BAD_FILENAME, NULL,
+ "find_mime_type_nix: MIME map file '%s' is not a file as I expected it to be",
+ GLOBAL_MAP_FILE);
+ }
+
+ /* Open it */
+
+ SVN_ERR (svn_io_file_open (&FHandle, GLOBAL_MAP_FILE, APR_READ, 0, pool));
+
+ /* Parse it */
+
+ ParseState = StartOfLine;
+ OK = apr_file_eof(FHandle);
+
+ while ((OK == APR_SUCCESS) && (ParseState != FoundExtension))
+ {
+ switch (ParseState)
+ {
+ case StartOfLine :
+ ParseState = SkippingLeadingSpace;
+ break;
+
+ case EndOfLine :
+ ParseState = StartOfLine;
+ break;
+
+ case GotExtension :
+ if (svn_string_compare_stringbuf (ExtensionStr, CurrentExtension))
+ {
+ /* + 1 for zero terminator */
+ *type = apr_palloc (pool, CurrentType->len + 1);
+
+ strncpy (*type, CurrentType->data, CurrentType->len);
+
+ ParseState = FoundExtension;
+ }
+ else
+ {
+ if (eol_found (Grabbed))
+ {
+ ParseState = EndOfLine;
+ }
+ else
+ {
+ ParseState = SkippingMiddleSpace;
+ }
+ }
+ break;
+
+ case SkippingLeadingSpace :
+ if (comment_found (Grabbed))
+ {
+ ParseState = SkippingComment;
+ }
+ else if (!white_space_found (Grabbed))
+ {
+ svn_stringbuf_setempty (CurrentType);
+
+ ParseBufferIndex = 0;
+ ParseBuffer[ParseBufferIndex++] = Grabbed;
+
+ ParseState = GrabbingType;
+ }
+ break;
+
+ case GrabbingType :
+ if (!white_space_found(Grabbed))
+ {
+ ParseBuffer[ParseBufferIndex++] = Grabbed;
+
+ if (ParseBufferIndex > PARSE_BUFFER_SIZE)
+ {
+ svn_stringbuf_appendbytes (CurrentType,
+ ParseBuffer,
+ ParseBufferIndex);
+ ParseBufferIndex = 0;
+ }
+ }
+ else
+ {
+ svn_stringbuf_appendbytes (CurrentType,
+ ParseBuffer,
+ ParseBufferIndex);
+
+ if (eol_found (Grabbed))
+ ParseState = StartOfLine;
+ else
+ ParseState = SkippingMiddleSpace;
+ }
+ break;
+
+ case SkippingMiddleSpace :
+ if (!white_space_found (Grabbed))
+ {
+ svn_stringbuf_setempty (CurrentExtension);
+
+ ParseBufferIndex = 0;
+ ParseBuffer[ParseBufferIndex++] = Grabbed;
+
+ ParseState = GrabbingExtension;
+ }
+ break;
+
+ case GrabbingExtension :
+ if (!white_space_found (Grabbed))
+ {
+ ParseBuffer[ParseBufferIndex++] = Grabbed;
+
+ if (ParseBufferIndex > PARSE_BUFFER_SIZE)
+ {
+ svn_stringbuf_appendbytes (CurrentExtension,
+ ParseBuffer,
+ ParseBufferIndex);
+ ParseBufferIndex = 0;
+ }
+ }
+ else
+ {
+ svn_stringbuf_appendbytes (CurrentExtension,
+ ParseBuffer,
+ ParseBufferIndex);
+
+ ParseState = GotExtension;
+ }
+ break;
+
+ case SkippingComment :
+ if (eol_found (Grabbed))
+ {
+ ParseState = EndOfLine;
+ }
+ break;
+ }
+
+ /* Only certain states cause another character to be grabbed */
+
+ switch (ParseState)
+ {
+ case StartOfLine :
+ case GotExtension :
+ case EndOfLine:
+ case FoundExtension :
+ break;
+ default :
+ OK = apr_file_getc (&Grabbed, FHandle);
+ }
+ }
+
+ apr_file_close (FHandle);
+
+ return Result;
+}
+
+
+/*****************************************************************************
+ Uses the mime.type file to try and convert a filename, to a MIME type
+ *****************************************************************************/
+
+svn_error_t *
+svn_mime_type_from_file_nix(const char **type,
+ const char *filename,
+ apr_pool_t *pool)
+{
+ svn_error_t *result = SVN_NO_ERROR;
+
+ char *leafname,
+ *extension;
+
+ /* Default to unknown type */
+
+ *type = NULL;
+
+ /* Find the extension */
+
+ leafname = strrchr (filename, '/') + 1; // + 1 to skip '/'
+ if (leafname == NULL)
+ {
+ leafname = filename;
+ }
+
+ extension = strrchr (leafname, '.');
+
+ /* If no extension was found then we can stop trying */
+
+ if (extension != NULL)
+ {
+ ++extension; // Skips over the leading '.'
+
+ result = find_mime_type_nix (type, extension, pool);
+ }
+
+ return result;
+}
+
+/*****************************************************************************/
+
+/*#endif*/ /* SVN_NIX */
Index: subversion/libsvn_subr/io.c
===================================================================
--- subversion/libsvn_subr/io.c (revision 5492)
+++ subversion/libsvn_subr/io.c (working copy)
@@ -1306,83 +1306,6 @@
 
 
 svn_error_t *
-svn_io_detect_mimetype (const char **mimetype,
- const char *file,
- apr_pool_t *pool)
-{
- static const char * const generic_binary = "application/octet-stream";
-
- svn_node_kind_t kind;
- apr_file_t *fh;
- apr_status_t apr_err;
- unsigned char block[1024];
- apr_size_t amt_read = sizeof (block);
-
- /* Default return value is NULL. */
- *mimetype = NULL;
-
- /* See if this file even exists, and make sure it really is a file. */
- SVN_ERR (svn_io_check_path (file, &kind, pool));
- if (kind != svn_node_file)
- return svn_error_createf (SVN_ERR_BAD_FILENAME, NULL,
- "svn_io_detect_mimetype: "
- "Can't detect mimetype of non-file '%s'",
- file);
-
- SVN_ERR (svn_io_file_open (&fh, file, APR_READ, 0, pool));
-
- /* Read a block of data from FILE. */
- apr_err = apr_file_read (fh, block, &amt_read);
- if (apr_err && ! APR_STATUS_IS_EOF(apr_err))
- return svn_error_createf (apr_err, NULL,
- "svn_io_detect_mimetype: error reading '%s'",
- file);
-
- /* Now close the file. No use keeping it open any more. */
- apr_file_close (fh);
-
-
- /* Right now, this function is going to be really stupid. It's
- going to examine the first block of data, and make sure that 85%
- of the bytes are such that their value is in the ranges 0x07-0x0D
- or 0x20-0x7F, and that 100% of those bytes is not 0x00.
-
- If those criteria are not met, we're calling it binary. */
- if (amt_read > 0)
- {
- apr_size_t i;
- int binary_count = 0;
-
- /* Run through the data we've read, counting the 'binary-ish'
- bytes. HINT: If we see a 0x00 byte, we'll set our count to its
- max and stop reading the file. */
- for (i = 0; i < amt_read; i++)
- {
- if (block[i] == 0)
- {
- binary_count = amt_read;
- break;
- }
- if ((block[i] < 0x07)
- || ((block[i] > 0x0D) && (block[i] < 0x20))
- || (block[i] > 0x7F))
- {
- binary_count++;
- }
- }
-
- if (((binary_count * 1000) / amt_read) > 850)
- {
- *mimetype = generic_binary;
- return SVN_NO_ERROR;
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
 svn_io_file_open (apr_file_t **new_file, const char *fname,
                   apr_int32_t flag, apr_fileperms_t perm,
                   apr_pool_t *pool)
Index: subversion/libsvn_subr/svn_mime.c
===================================================================
--- subversion/libsvn_subr/svn_mime.c (working copy)
+++ subversion/libsvn_subr/svn_mime.c (working copy)
@@ -0,0 +1,124 @@
+/*****************************************************************************
+ * svn_mime.c *
+ *****************************************************************************/
+
+#include <apr_file_io.h>
+#include "svn_private_config.h"
+#include "svn_error.h"
+#include "svn_mime.h"
+
+#ifdef SVN_NIX
+#include "mime_nix.h"
+#endif
+
+/*****************************************************************************
+ The statistical method wipped from io.c forms the fall-back position.
+ *****************************************************************************/
+
+svn_error_t *
+statistical_scan(const char **type,
+ const char *file,
+ apr_pool_t *pool)
+{
+ static const char * const generic_binary = "application/octet-stream";
+ static const char * const generic_text = "text/plain";
+
+ svn_node_kind_t kind;
+ apr_file_t *fh;
+ apr_status_t apr_err;
+ unsigned char block[1024];
+ apr_size_t amt_read = sizeof (block);
+
+ /* Default return value is NULL. */
+ *type = NULL;
+
+ /* See if this file even exists, and make sure it really is a file. */
+ SVN_ERR (svn_io_check_path (file, &kind, pool));
+ if (kind != svn_node_file)
+ return svn_error_createf (SVN_ERR_BAD_FILENAME, NULL,
+ "svn_mime.c statistical_scan : Can't detect mimetype of non-file '%s'",
+ file);
+
+ SVN_ERR (svn_io_file_open (&fh, file, APR_READ, 0, pool));
+
+ /* Read a block of data from FILE. */
+ apr_err = apr_file_read (fh, block, &amt_read);
+ if (apr_err && ! APR_STATUS_IS_EOF(apr_err))
+ return svn_error_createf (apr_err, NULL,
+ "svn_mime.c statistical_scan: Error reading '%s'",
+ file);
+
+ /* Now close the file. No use keeping it open any more. */
+ apr_file_close (fh);
+
+
+ /* Right now, this function is going to be really stupid. It's
+ going to examine the first block of data, and make sure that 85%
+ of the bytes are such that their value is in the ranges 0x07-0x0D
+ or 0x20-0x7F, and that 100% of those bytes is not 0x00.
+
+ If those criteria are not met, we're calling it binary. */
+ if (amt_read > 0)
+ {
+ apr_size_t i;
+ int binary_count = 0;
+
+ /* Run through the data we've read, counting the 'binary-ish'
+ bytes. HINT: If we see a 0x00 byte, we'll set our count to its
+ max and stop reading the file. */
+ for (i = 0; i < amt_read; i++)
+ {
+ if (block[i] == 0)
+ {
+ binary_count = amt_read;
+ break;
+ }
+ if ((block[i] < 0x07)
+ || ((block[i] > 0x0D) && (block[i] < 0x20))
+ || (block[i] > 0x7F))
+ {
+ binary_count++;
+ }
+ }
+
+ if (((binary_count * 1000) / amt_read) > 850)
+ {
+ *type = generic_binary;
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ *type = generic_text;
+ return SVN_NO_ERROR;
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/*****************************************************************************
+ Try to work out what MIME type a file should have
+ *****************************************************************************/
+
+svn_error_t *
+svn_mime_guess_type_from_file(const char **type,
+ const char *filename,
+ apr_pool_t *pool)
+{
+ svn_error_t *Result = SVN_NO_ERROR;
+
+ *type = NULL;
+
+ /*#ifdef SVN_NIX*/
+ Result = svn_mime_type_from_file_nix (type, filename, pool);
+ /*#endif*/
+
+ if (*type == NULL)
+ {
+ Result = statistical_scan (type, filename, pool);
+ }
+
+ return Result;
+}
+
+/*****************************************************************************/
Index: subversion/libsvn_client/commit.c
===================================================================
--- subversion/libsvn_client/commit.c (revision 5492)
+++ subversion/libsvn_client/commit.c (working copy)
@@ -107,7 +107,7 @@
 
   /* If the file has a discernable mimetype, add that as a property to
      the file. */
- SVN_ERR (svn_io_detect_mimetype (&mimetype, path, pool));
+ SVN_ERR (svn_mime_guess_type_from_file(&mimetype, path, pool));
   if (mimetype)
     SVN_ERR (editor->change_file_prop (file_baton, SVN_PROP_MIME_TYPE,
                                        svn_string_create (mimetype, pool),
Index: subversion/tests/libsvn_subr/mime-test.c
===================================================================
--- subversion/tests/libsvn_subr/mime-test.c (working copy)
+++ subversion/tests/libsvn_subr/mime-test.c (working copy)
@@ -0,0 +1,320 @@
+/*****************************************************************************
+ * mime-test.c *
+ * *
+ * When adding tests don't forget to add them to the struct at the end of *
+ * this file. *
+ *****************************************************************************/
+
+#include <apr_file_io.h>
+#include <apr_strings.h>
+#include "svn_test.h"
+#include "svn_error.h"
+#include "svn_mime.h"
+
+/*****************************************************************************
+ Constants
+ *****************************************************************************/
+
+#define TEXT_FILE "./mime-test-text"
+#define BINARY_FILE "./mime-test-binary"
+#define MOSTLY_TEXT_FILE "./mime-test-mostly-text"
+#define NO_SUCH_FILE "./mime-test-no-such"
+
+#define HTML_EXT ".html"
+#define PNG_EXT ".png"
+#define TEXT_EXT ".txt"
+#define NO_SUCH_EXT ".cheese"
+
+#define MIME_TEXT "text/plain"
+#define MIME_HTML "text/html"
+#define MIME_BINARY "application/octet-stream"
+#define MIME_PNG "image/png"
+
+/*****************************************************************************
+ Generic identify file test
+ *****************************************************************************/
+
+static svn_error_t *
+identify_file_test(const char*File,
+ const char*ExpectedType,
+ apr_pool_t *pool)
+{
+ apr_file_t *file;
+ char *type;
+
+ /* Just check to make sure our test file is there */
+
+ if (apr_file_open(&file, TEXT_FILE, APR_READ, APR_OS_DEFAULT, pool))
+ return svn_error_createf(SVN_ERR_TEST_FAILED,
+ NULL,
+ "Unable to open test text file (%s)",
+ File);
+ else
+ apr_file_close(file);
+
+ /* Now we make the call */
+
+ SVN_ERR(svn_mime_guess_type_from_file(&type, File, pool));
+
+ if (apr_strnatcmp(type, ExpectedType) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED,
+ NULL,
+ "type guess returned '%s' but '%s' expected",
+ type,
+ ExpectedType);
+
+ return SVN_NO_ERROR;
+}
+
+/*****************************************************************************
+ Generic add extension to file and identify it test
+ *****************************************************************************/
+
+
+static svn_error_t *
+identify_extension_test(const char *Filename,
+ const char *Extension,
+ const char *ExpectedType,
+ apr_pool_t *pool)
+{
+ svn_error_t *Result;
+ char *type,
+ *csd,
+ *testfile,
+ *newfile;
+
+ /* Put an extension on our test file */
+
+ SVN_ERR(apr_filepath_get(&csd, NULL, pool));
+ testfile = apr_pstrcat(pool, csd, "/", Filename, NULL);
+ newfile = apr_pstrcat(pool, csd, "/", Filename, Extension, NULL);
+ SVN_ERR(apr_file_copy(testfile, newfile, APR_FILE_SOURCE_PERMS, pool));
+
+ /* Perform the test */
+
+ Result = identify_file_test(newfile, ExpectedType, pool);
+
+ /* Tidy up */
+
+ SVN_ERR(apr_file_remove(newfile, pool));
+
+ return Result;
+}
+
+/*****************************************************************************
+ Identify text file without extension as a text file
+ *****************************************************************************/
+
+static svn_error_t *
+test_unextensioned_text_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of extensionless text file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_file_test(TEXT_FILE, MIME_TEXT, pool);
+}
+
+/*****************************************************************************
+ Identify binary file without extension as a text file
+ *****************************************************************************/
+
+static svn_error_t *
+test_unextensioned_binary_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of extensionless binary file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_file_test(BINARY_FILE, MIME_BINARY, pool);
+}
+
+/*****************************************************************************
+ Identify text file without extension as a text file
+ *****************************************************************************/
+
+static svn_error_t *
+test_unextensioned_mostly_text_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of extensionless mostly text file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_file_test(MOSTLY_TEXT_FILE, MIME_TEXT, pool);
+}
+
+/*****************************************************************************
+ This test has a crack with a text file, with file extension.
+ *****************************************************************************/
+
+static svn_error_t *
+test_extensioned_text_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of an extensioned text file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_extension_test(TEXT_FILE, HTML_EXT, MIME_HTML, pool);
+}
+
+/*****************************************************************************
+ This test has a crack with a binary file, with file extension.
+ *****************************************************************************/
+
+static svn_error_t *
+test_extensioned_binary_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of an extensioned binary file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_extension_test(BINARY_FILE, PNG_EXT, MIME_PNG, pool);
+}
+
+/*****************************************************************************
+ This test has a crack with a mostly text file, with file extension.
+ *****************************************************************************/
+
+static svn_error_t *
+test_extensioned_mostly_text_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of an extensioned mostly text file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_extension_test(MOSTLY_TEXT_FILE, TEXT_EXT, MIME_TEXT, pool);
+}
+
+/*****************************************************************************
+ Ensure correct failure when seeking an extension which coes not exist in
+ the mime.types file. Text file.
+ *****************************************************************************/
+
+static svn_error_t *
+test_no_such_extension_text_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of text file, non-existant extension";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_extension_test(TEXT_FILE, NO_SUCH_EXT, MIME_TEXT, pool);
+}
+
+/*****************************************************************************
+ Ensure correct failure when seeking an extension which coes not exist in
+ the mime.types file. Binary file.
+ *****************************************************************************/
+
+static svn_error_t *
+test_no_such_extension_binary_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of binary file, non-existant extension";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_extension_test(BINARY_FILE, NO_SUCH_EXT, MIME_BINARY, pool);
+}
+
+/*****************************************************************************
+ Ensure correct failure when seeking an extension which coes not exist in
+ the mime.types file. Mostly text file.
+ *****************************************************************************/
+
+static svn_error_t *
+test_no_such_extension_mostly_text_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "discern MIME type of mostly text file, non-existant extension";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ return identify_extension_test(MOSTLY_TEXT_FILE,
+ NO_SUCH_EXT,
+ MIME_TEXT,
+ pool);
+}
+
+/*****************************************************************************
+ Test responce to missing subject file
+ *****************************************************************************/
+
+static svn_error_t *
+test_missing_subject_file(const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ apr_file_t *file;
+ char *type;
+ svn_error_t *result;
+
+ *msg = "discern MIME type of a non-existant file";
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ /* Just check to make sure our test file is not there */
+
+ if (!apr_file_open(&file, NO_SUCH_FILE, APR_READ, APR_OS_DEFAULT, pool))
+ {
+ apr_file_close(file);
+ return svn_error_createf(SVN_ERR_TEST_FAILED,
+ NULL,
+ "Non-existant file exists! (%s)",
+ NO_SUCH_FILE);
+ }
+
+ /* Now we make the call */
+
+ result = svn_mime_guess_type_from_file(&type, NO_SUCH_FILE, pool);
+
+ if (result->apr_err != SVN_ERR_BAD_FILENAME)
+ return result;
+
+ if (type != NULL)
+ return svn_error_createf(SVN_ERR_TEST_FAILED,
+ NULL,
+ "type guess returned '%s' but NULL expected",
+ type);
+
+ return SVN_NO_ERROR;
+}
+
+
+/*****************************************************************************
+ Test table
+ *****************************************************************************/
+
+struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_PASS(test_unextensioned_text_file),
+ SVN_TEST_PASS(test_unextensioned_binary_file),
+ SVN_TEST_PASS(test_unextensioned_mostly_text_file),
+ SVN_TEST_PASS(test_extensioned_text_file),
+ SVN_TEST_PASS(test_extensioned_binary_file),
+ SVN_TEST_PASS(test_extensioned_mostly_text_file),
+ SVN_TEST_PASS(test_no_such_extension_text_file),
+ SVN_TEST_PASS(test_no_such_extension_binary_file),
+ SVN_TEST_PASS(test_no_such_extension_mostly_text_file),
+ SVN_TEST_PASS(test_missing_subject_file),
+ /* I don't know how to simulate a missing mime.types file */
+ SVN_TEST_NULL
+ };
+
+/*****************************************************************************/
Index: subversion/tests/libsvn_subr/mime-test-text
===================================================================
--- subversion/tests/libsvn_subr/mime-test-text (working copy)
+++ subversion/tests/libsvn_subr/mime-test-text (working copy)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+ <head>
+ <title>One of a miriad test pages</title>
+ </head>
+ <body>
+ <h1>Hello World</h1>
+ <p>Mr Inventive strikes again.</p>
+ </body>
+</html>
Index: subversion/tests/libsvn_subr/mime-test-binary
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: subversion/tests/libsvn_subr/mime-test-binary
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: subversion/tests/libsvn_subr/mime-test-mostly-text
===================================================================
--- subversion/tests/libsvn_subr/mime-test-mostly-text (working copy)
+++ subversion/tests/libsvn_subr/mime-test-mostly-text (working copy)
@@ -0,0 +1,5 @@
+This is  short text file in which most of the content is actually text.
+
+However look out for the odd non-text character creaping in there. Don't
+have kittens, this is perfectly normal and nothing to gt too woried about.
+Have a last.
Index: build.conf
===================================================================
--- build.conf (revision 5492)
+++ build.conf (working copy)
@@ -361,6 +361,14 @@
 install = test
 libs = libsvn_test libsvn_delta libsvn_subr $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS)
 
+# test MIME mapping code
+[mime-test]
+type = exe
+path = subversion/tests/libsvn_subr
+sources = mime-test.c
+install = test
+libs = libsvn_test libsvn_delta libsvn_subr $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS)
+
 # test svn_stringbuf_t utilities
 [stringtest]
 type = exe

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Mar 29 17:03:35 2003

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.