You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Rodent of Unusual Size <co...@decus.org> on 1997/07/18 18:31:29 UTC

[PATCH] AddTypeParameter for adding media-type parameters

    (I know Dean is going to hate this because it adds a directive,
    but..)

    PR#241 requests the ability to add media-type parameters (in his
    example, "charset=ISO8859-2").  This sounds like a primo enhancement
    to me.  The attached patch does this with a

     AddTypeParameter parameter type [...]

    For instance, for his example

     AddTypeParameter charset=ISO8859-2 .html .shtml

    #ken    :-)}

Index: httpd.h
===================================================================
RCS file: /export/home/cvs/apache/src/httpd.h,v
retrieving revision 1.128
diff -c -r1.128 httpd.h
*** httpd.h	1997/07/17 19:44:49	1.128
--- httpd.h	1997/07/18 16:37:42
***************
*** 449,565 ****
  
  struct request_rec {
  
!   pool *pool;
!   conn_rec *connection;
!   server_rec *server;
  
!   request_rec *next;		/* If we wind up getting redirected,
  				 * pointer to the request we redirected to.
  				 */
!   request_rec *prev;		/* If this is an internal redirect,
  				 * pointer to where we redirected *from*.
  				 */
    
!   request_rec *main;		/* If this is a sub_request (see request.h) 
  				 * pointer back to the main request.
  				 */
  
!   /* Info about the request itself... we begin with stuff that only
!    * protocol.c should ever touch...
!    */
!   
!   char *the_request;		/* First line of request, so we can log it */
!   int assbackwards;		/* HTTP/0.9, "simple" request */
!   int proxyreq;                 /* A proxy request */
!   int header_only;		/* HEAD request, as opposed to GET */
!   char *protocol;		/* Protocol, as given to us, or HTTP/0.9 */
!   int proto_num;		/* Number version of protocol; 1.1 = 1001 */
!   char *hostname;		/* Host, as set by full URI or Host: */
!   int hostlen;			/* Length of http://host:port in full URI */
! 
!   time_t request_time;		/* When the request started */
! 
!   char *status_line;		/* Status line, if set by script */
!   int status;			/* In any case */
!   
!   /* Request method, two ways; also, protocol, etc..  Outside of protocol.c,
!    * look, but don't touch.
!    */
!   
!   char *method;			/* GET, HEAD, POST, etc. */
!   int method_number;		/* M_GET, M_POST, etc. */
!   int allowed;			/* Allowed methods - for 405, OPTIONS, etc */
! 
!   int sent_bodyct;		/* byte count in stream is for body */
!   long bytes_sent;		/* body byte count, for easy access */
! 
!   /* HTTP/1.1 connection-level features */
! 
!   int chunked;			/* sending chunked transfer-coding */
!   int byterange;		/* number of byte ranges */
!   char *boundary;		/* multipart/byteranges boundary */
!   char *range;			/* The Range: header */
!   long clength;			/* The "real" content length */
! 
!   long remaining;		/* bytes left to read */
!   long read_length;		/* bytes that have been read */
!   int read_body;   		/* how the request body should be read */
!   int read_chunked;		/* reading chunked transfer-coding */
! 
!   /* MIME header environments, in and out.  Also, an array containing
!    * environment variables to be passed to subprocesses, so people can
!    * write modules to add to that environment.
!    *
!    * The difference between headers_out and err_headers_out is that the
!    * latter are printed even on error, and persist across internal redirects
!    * (so the headers printed for ErrorDocument handlers will have them).
!    *
!    * The 'notes' table is for notes from one module to another, with no
!    * other set purpose in mind...
!    */
!   
!   table *headers_in;
!   table *headers_out;
!   table *err_headers_out;
!   table *subprocess_env;
!   table *notes;
! 
!   char *content_type;		/* Break these out --- we dispatch on 'em */
!   char *handler;		/* What we *really* dispatch on           */
! 
!   char *content_encoding;
!   char *content_language;	/* for back-compat. only -- do not use */
!   array_header *content_languages; /* array of (char*) */
!   
!   int no_cache;
!   int no_local_copy;
!   
!   /* What object is being requested (either directly, or via include
!    * or content-negotiation mapping).
!    */
  
!   char *uri;                    /* complete URI for a proxy req, or
                                     URL path for a non-proxy req */
!   char *filename;
!   char *path_info;
!   char *args;			/* QUERY_ARGS, if any */
!   struct stat finfo;		/* ST_MODE set to zero if no such file */
!   
!   /* Various other config info which may change with .htaccess files
!    * These are config vectors, with one void* pointer for each module
!    * (the thing pointed to being the module's business).
!    */
!   
!   void *per_dir_config;		/* Options set in config files, etc. */
!   void *request_config;		/* Notes on *this* request */
! 
! /*
!  * a linked list of the configuration directives in the .htaccess files
!  * accessed by this request.
!  * N.B. always add to the head of the list, _never_ to the end.
!  * that way, a sub request's list can (temporarily) point to a parent's list
!  */
!   const struct htaccess_result *htaccess;
  };
  
  
--- 449,567 ----
  
  struct request_rec {
  
!     pool *pool;
!     conn_rec *connection;
!     server_rec *server;
  
!     request_rec *next;		/* If we wind up getting redirected,
  				 * pointer to the request we redirected to.
  				 */
!     request_rec *prev;		/* If this is an internal redirect,
  				 * pointer to where we redirected *from*.
  				 */
    
!     request_rec *main;		/* If this is a sub_request (see request.h) 
  				 * pointer back to the main request.
  				 */
  
!     /* Info about the request itself... we begin with stuff that only
!      * protocol.c should ever touch...
!      */
!   
!     char *the_request;		/* First line of request, so we can log it */
!     int assbackwards;		/* HTTP/0.9, "simple" request */
!     int proxyreq;               /* A proxy request */
!     int header_only;		/* HEAD request, as opposed to GET */
!     char *protocol;		/* Protocol, as given to us, or HTTP/0.9 */
!     int proto_num;		/* Number version of protocol; 1.1 = 1001 */
!     char *hostname;		/* Host, as set by full URI or Host: */
!     int hostlen;		/* Length of http://host:port in full URI */
! 
!     time_t request_time;	/* When the request started */
! 
!     char *status_line;		/* Status line, if set by script */
!     int status;			/* In any case */
!   
!     /* Request method, two ways; also, protocol, etc..  Outside of protocol.c,
!      * look, but don't touch.
!      */
!   
!     char *method;		/* GET, HEAD, POST, etc. */
!     int method_number;		/* M_GET, M_POST, etc. */
!     int allowed;		/* Allowed methods - for 405, OPTIONS, etc */
! 
!     int sent_bodyct;		/* byte count in stream is for body */
!     long bytes_sent;		/* body byte count, for easy access */
! 
!     /* HTTP/1.1 connection-level features */
! 
!     int chunked;		/* sending chunked transfer-coding */
!     int byterange;		/* number of byte ranges */
!     char *boundary;		/* multipart/byteranges boundary */
!     char *range;		/* The Range: header */
!     long clength;		/* The "real" content length */
! 
!     long remaining;		/* bytes left to read */
!     long read_length;		/* bytes that have been read */
!     int read_body;   		/* how the request body should be read */
!     int read_chunked;		/* reading chunked transfer-coding */
! 
!     /* MIME header environments, in and out.  Also, an array containing
!      * environment variables to be passed to subprocesses, so people can
!      * write modules to add to that environment.
!      *
!      * The difference between headers_out and err_headers_out is that the
!      * latter are printed even on error, and persist across internal redirects
!      * (so the headers printed for ErrorDocument handlers will have them).
!      *
!      * The 'notes' table is for notes from one module to another, with no
!      * other set purpose in mind...
!      */
!   
!     table *headers_in;
!     table *headers_out;
!     table *err_headers_out;
!     table *subprocess_env;
!     table *notes;
! 
!     char *content_type;		/* Break these out --- we dispatch on 'em */
!     char *content_params;	/* Things like "; charset=mumble"	  */
!     char *handler;		/* What we *really* dispatch on           */
! 
!     char *content_encoding;
!     char *content_language;	/* for back-compat. only -- do not use */
!     array_header *content_languages; /* array of (char*) */
!   
!     int no_cache;
!     int no_local_copy;
!   
!     /* What object is being requested (either directly, or via include
!      * or content-negotiation mapping).
!      */
  
!     char *uri;			/* complete URI for a proxy req, or
                                     URL path for a non-proxy req */
!     char *filename;
!     char *path_info;
!     char *args;			/* QUERY_ARGS, if any */
!     struct stat finfo;		/* ST_MODE set to zero if no such file */
!   
!     /* Various other config info which may change with .htaccess files
!      * These are config vectors, with one void* pointer for each module
!      * (the thing pointed to being the module's business).
!      */
!   
!     void *per_dir_config;		/* Options set in config files, etc. */
!     void *request_config;		/* Notes on *this* request */
! 
!     /*
!      * a linked list of the configuration directives in the .htaccess files
!      * accessed by this request.
!      * N.B. always add to the head of the list, _never_ to the end.
!      * that way, a sub request's list can (temporarily) point to a parent's
!      * list.
!      */
!     const struct htaccess_result *htaccess;
  };
  
  
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.139
diff -c -r1.139 http_protocol.c
*** http_protocol.c	1997/07/15 22:36:51	1.139
--- http_protocol.c	1997/07/18 16:37:51
***************
*** 1215,1220 ****
--- 1215,1227 ----
      else
          table_set(r->headers_out, "Content-Type", default_type(r));
      
+     if (r->content_params != NULL) {
+ 	char *full_type;
+ 	full_type = pstrcat (r->pool,
+ 			     table_get(r->headers_out, "Content-Type"),
+ 			     r->content_params, NULL);
+ 	table_set(r->headers_out, "Content-Type", full_type);
+     }
      if (r->content_encoding)
          table_set(r->headers_out, "Content-Encoding", r->content_encoding);
      
Index: mod_mime.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_mime.c,v
retrieving revision 1.19
diff -c -r1.19 mod_mime.c
*** mod_mime.c	1997/07/17 22:27:39	1.19
--- mod_mime.c	1997/07/18 16:37:54
***************
*** 67,72 ****
--- 67,73 ----
      table *encoding_types;	/* Added with AddEncoding... */
      table *language_types;	/* Added with AddLanguage... */
      table *handlers;		/* Added with AddHandler...  */
+     table *content_params;	/* Added with AddTypeParameter...  */
  
      char *type;			/* Type forced with ForceType  */
      char *handler;		/* Handler forced with SetHandler */
***************
*** 83,88 ****
--- 84,90 ----
      new->encoding_types = make_table (p, 4);
      new->language_types = make_table (p, 4);
      new->handlers = make_table (p, 4);
+     new->content_params = make_table (p, 4);
  
      new->type = NULL;
      new->handler = NULL;
***************
*** 104,110 ****
      new->language_types = overlay_tables (p, add->language_types,
  					  base->language_types);
      new->handlers = overlay_tables (p, add->handlers,
! 					  base->handlers);
  
      new->type = add->type ? add->type : base->type;
      new->handler = add->handler ? add->handler : base->handler;
--- 106,114 ----
      new->language_types = overlay_tables (p, add->language_types,
  					  base->language_types);
      new->handlers = overlay_tables (p, add->handlers,
! 				    base->handlers);
!     new->content_params = overlay_tables (p, add->content_params,
! 					  base->content_params);
  
      new->type = add->type ? add->type : base->type;
      new->handler = add->handler ? add->handler : base->handler;
***************
*** 119,124 ****
--- 123,149 ----
      return NULL;
  }
  
+ /*
+  * Add media parameters for the Content-Type header field (e.g.,
+  * charset=mumble).
+  */
+ const char *add_type_parameter(cmd_parms *cmd, mime_dir_config *m, char *cp,
+ 			       char *ext)
+ {
+     char *newlist;
+ 
+     if (*ext == '.') ++ext;
+     newlist = table_get (m->content_params, ext);
+     if (newlist == NULL) {
+ 	newlist = pstrcat (cmd->pool, "; ", cp, NULL);
+     }
+     else {
+ 	newlist = pstrcat (cmd->pool, newlist, "; ", cp, NULL);
+     }
+     table_set (m->content_params, ext, newlist);
+     return NULL;
+ }
+ 
  const char *add_encoding(cmd_parms *cmd, mime_dir_config *m, char *enc,
  			 char *ext)
  {
***************
*** 156,162 ****
  
  command_rec mime_cmds[] = {
  { "AddType", add_type, NULL, OR_FILEINFO, ITERATE2,
!     "a mime type followed by one or more file extensions" },
  { "AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2,
      "an encoding (e.g., gzip), followed by one or more file extensions" },
  { "AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2,
--- 181,189 ----
  
  command_rec mime_cmds[] = {
  { "AddType", add_type, NULL, OR_FILEINFO, ITERATE2,
!     "a MIME type followed by one or more file extensions" },
! { "AddTypeParameter", add_type_parameter, NULL, OR_FILEINFO, ITERATE2,
!     "an HTTP/1.1 media type parameter followed by one or more file extensions" },
  { "AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2,
      "an encoding (e.g., gzip), followed by one or more file extensions" },
  { "AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2,
***************
*** 164,170 ****
  { "AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2,
      "a handler name followed by one or more file extensions" },
  { "ForceType", set_string_slot, (void*)XtOffsetOf(mime_dir_config, type),
!     OR_FILEINFO, TAKE1, "a media type" },
  { "SetHandler", set_string_slot, (void*)XtOffsetOf(mime_dir_config, handler),
      OR_FILEINFO, TAKE1, "a handler name" },
  { "TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1,
--- 191,197 ----
  { "AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2,
      "a handler name followed by one or more file extensions" },
  { "ForceType", set_string_slot, (void*)XtOffsetOf(mime_dir_config, type),
!     OR_FILEINFO, TAKE1, "a MIME media type" },
  { "SetHandler", set_string_slot, (void*)XtOffsetOf(mime_dir_config, handler),
      OR_FILEINFO, TAKE1, "a handler name" },
  { "TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1,
***************
*** 235,241 ****
       * pointer to getword, causing a SEGV ..
       */
  
!     if(fn == NULL) fn = r->filename;
  
      /* Parse filename extensions, which can be in any order */
      while ((ext = getword(r->pool, &fn, '.')) && *ext) {
--- 262,269 ----
       * pointer to getword, causing a SEGV ..
       */
  
!     if (fn == NULL)
! 	fn = r->filename;
  
      /* Parse filename extensions, which can be in any order */
      while ((ext = getword(r->pool, &fn, '.')) && *ext) {
***************
*** 248,253 ****
--- 276,287 ----
  	  found = 1;
        }
  
+       /* Check for media-type parameters */
+       if ((type = table_get (conf->content_params, ext)) != NULL) {
+ 	r->content_params  = type;
+ 	found = 1;
+       }
+ 
        /* Check for Content-Language */
        if ((type = table_get (conf->language_types, ext))) {
  	  char **new;
***************
*** 283,288 ****
--- 317,323 ----
  
        if (!found) {
  	r->content_type = NULL;
+ 	r->content_params = NULL;
  	r->content_language = NULL;
  	r->content_languages = NULL;
  	r->content_encoding = NULL;