Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 262 lines (226 sloc) 10.401 kB
b4197ee @klacke ""
authored
1 %%%----------------------------------------------------------------------
2 %%% File : mime_type_c.erl
3 %%% Author : Claes Wikstrom <klacke@hyber.org>
455578a @vinoski major trailing whitespace cleanup
vinoski authored
4 %%% Purpose :
b4197ee @klacke ""
authored
5 %%% Created : 10 Jul 2002 by Claes Wikstrom <klacke@hyber.org>
6 %%%----------------------------------------------------------------------
7
8 -module(mime_type_c).
9 -author('klacke@hyber.org').
eacdbbd fixed warnings about unused imports and export_all
Richard Carlsson authored
10
89a64ef @capflam Make the mime types mappings configurable
capflam authored
11 -export([generate/0, generate/3]).
0be3c7e @klacke untabified all of yaws
authored
12
89a64ef @capflam Make the mime types mappings configurable
capflam authored
13 -include("../include/yaws.hrl").
14
15
16 -define(MIME_TYPES_FILE, filename:join(code:priv_dir(yaws), "mime.types")).
17 -define(DEFAULT_MIME_TYPE, "text/plain").
18
19 %% This function is used during Yaws' compilation. To rebuild/reload mime_types
20 %% module, generate/3 _MUST_ be used.
21 generate() ->
22 %% By default, mime_types.erl is generated in the same directory than
23 %% mime_type_c.erl. The priv directory is supposed to be relative to this
24 %% source directory.
25 SrcDir = filename:dirname(
26 proplists:get_value(source, ?MODULE:module_info(compile))
27 ),
28 PrivDir = filename:join(filename:dirname(SrcDir), "priv"),
29 Charset = read_charset_file(filename:join(PrivDir, "charset.def")),
30 GInfo = #mime_types_info{
31 mime_types_file = filename:join(PrivDir, "mime.types"),
32 default_charset = Charset
33 },
34 ModFile = filename:join(SrcDir, "mime_types.erl"),
35 case generate(ModFile, GInfo, []) of
36 ok ->
37 erlang:halt(0);
38 {error, Reason} ->
39 error_logger:format("Cannot write module ~p: ~p\n",
40 [ModFile, file:format_error(Reason)]),
41 erlang:halt(1)
b4197ee @klacke ""
authored
42 end.
43
44
89a64ef @capflam Make the mime types mappings configurable
capflam authored
45 %% GInfo ::= #mime_types_info{}
46 %% SInfoMap ::= [{{ServerName, Port}, #mime_types_info{}}]
47 %% ServerName ::= string() | atom()
48 generate(ModFile, GInfo, SInfoMap) ->
49 case file:open(ModFile, [write]) of
50 {ok, Fd} ->
51 TypesData = [create_mime_types_data(Name, Info) ||
52 {Name, Info} <- [{global, GInfo}|SInfoMap] ],
53
54 %% Generate module Header
55 io:format(Fd,
56 "-module(mime_types).~n~n"
57 "-export([default_type/0, default_type/1]).~n"
58 "-export([t/1, revt/1]).~n"
59 "-export([t/2, revt/2]).~n~n"
60 "-include_lib(\"yaws/include/yaws.hrl\").~n~n", []),
61
62 %% Generate default_type/0, t/1 and revt/1
63 io:format(Fd,
64 "default_type() -> default_type(global).~n"
65 "t(Ext) -> t(global, Ext).~n"
66 "revt(Ext) -> revt(global, Ext).~n~n", []),
67
68 %% Generate default_type/1
69 io:format(Fd, "default_type(#sconf{servername=SN, port=P}) -> "
70 "default_type({SN,P});~n", []),
71 lists:foreach(fun({Name, _, DefaultType, DefaultCharset}) ->
72 generate_default_type(Fd, Name, DefaultType,
73 DefaultCharset)
74 end, TypesData),
75 io:format(Fd, "default_type(_) -> default_type(global).~n~n", []),
76
77 %% Generate t/2 function
78 io:format(Fd, "t(#sconf{servername=SN, port=P}, Ext) -> "
79 "t({SN,P}, Ext);~n", []),
80 lists:foreach(fun({Name, MimeTypes, DefaultType, DefaultCharset}) ->
81 generate_t(Fd, Name, MimeTypes,
82 DefaultType, DefaultCharset)
83 end, TypesData),
84 io:format(Fd, "t(_, Ext) -> t(global, Ext).~n~n", []),
85
86 %% Generate revt/2 function
87 io:format(Fd,
88 "revt(#sconf{servername=SN, port=P}, Ext) -> "
89 "revt({SN,P}, Ext);~n",
90 []),
91 lists:foreach(fun({Name, MimeTypes, DefaultType, DefaultCharset}) ->
92 generate_revt(Fd, Name, MimeTypes,
93 DefaultType, DefaultCharset)
94 end, TypesData),
95 io:format(Fd, "revt(_, RExt) -> revt(global, RExt).~n", []),
96
97 file:close(Fd),
98 ok;
99
100 {error, Reason} ->
101 {error, Reason}
102 end.
103
0be3c7e @klacke untabified all of yaws
authored
104
89a64ef @capflam Make the mime types mappings configurable
capflam authored
105 %% ----
106 create_mime_types_data(Name, Info) ->
107 Charsets = Info#mime_types_info.charsets,
108 DefaultC = case Info#mime_types_info.default_charset of
109 undefined -> "";
110 DCharset -> "; charset=" ++ DCharset
111 end,
6b289a9 @carsten3347 Added CGI and PHP support.
carsten3347 authored
112
89a64ef @capflam Make the mime types mappings configurable
capflam authored
113 Map = case Info#mime_types_info.mime_types_file of
114 undefined -> read_mime_types_file(?MIME_TYPES_FILE);
115 File -> read_mime_types_file(File)
116 end,
117 TypesData =
118 lists:foldl(fun({Ext, MimeType}, Acc) ->
119 ExtType = get_ext_type(Ext),
120 Charset = case lists:keyfind(Ext, 1, Charsets) of
121 {_,C} ->
122 "; charset=" ++ C;
123 false ->
124 case MimeType of
125 "text/"++_ -> DefaultC;
126 _ -> ""
127 end
128 end,
129 lists:keystore(Ext, 1, Acc,
130 {Ext, ExtType, MimeType, Charset})
131 end, [], Map ++ Info#mime_types_info.types),
132 {Name, TypesData, Info#mime_types_info.default_type, DefaultC}.
0be3c7e @klacke untabified all of yaws
authored
133
b4197ee @klacke ""
authored
134
89a64ef @capflam Make the mime types mappings configurable
capflam authored
135 %% ----
136 generate_default_type(Fd, Name, DefaultType, DefaultCharset) ->
137 io:format(Fd, "default_type(~p) -> \"~s~s\";~n",
138 [Name, DefaultType, DefaultCharset]).
139
140
141 %% ----
142 generate_t(Fd, Name, [], "text/"++_=DefaultType, DefaultCharset) ->
143 io:format(Fd, "t(~p, _) -> {regular, \"~s~s\"};~n",
144 [Name, DefaultType, DefaultCharset]);
145 generate_t(Fd, Name, [], DefaultType, _) ->
146 io:format(Fd, "t(~p, _) -> {regular, \"~s\"};~n", [Name, DefaultType]);
147 generate_t(Fd, Name, [{Ext,ExtType,MimeType,Charset}|Rest],
148 DefaultType, DefaultCharset) ->
149 case string:to_upper(Ext) of
150 Ext ->
151 io:format(Fd, "t(~p, ~p) -> {~p, \"~s~s\"};~n",
152 [Name, Ext, ExtType, MimeType, Charset]);
153 UExt ->
154 io:format(Fd,
155 "t(~p, ~p) -> {~p, \"~s~s\"};~n"
156 "t(~p, ~p) -> {~p, \"~s~s\"};~n",
157 [Name, Ext, ExtType, MimeType, Charset,
158 Name, UExt, ExtType, MimeType, Charset])
159 end,
160 generate_t(Fd, Name, Rest, DefaultType, DefaultCharset).
161
162
163 %% ----
164 generate_revt(Fd, Name, [], "text/"++_=DefaultType, DefaultCharset) ->
165 io:format(Fd,
166 "revt(~p, RExt) -> {regular, lists:reverse(RExt), \"~s~s\"};~n",
167 [Name, DefaultType, DefaultCharset]);
168 generate_revt(Fd, Name, [], DefaultType, _) ->
455578a @vinoski major trailing whitespace cleanup
vinoski authored
169 io:format(Fd,
89a64ef @capflam Make the mime types mappings configurable
capflam authored
170 "revt(~p, RExt) -> {regular, lists:reverse(RExt), \"~s\"};~n",
171 [Name, DefaultType]);
172 generate_revt(Fd, Name, [{Ext,ExtType,MimeType,Charset}|Rest],
173 DefaultType, DefaultCharset) ->
174 RExt = lists:reverse(Ext),
175 case string:to_upper(Ext) of
176 Ext ->
177 io:format(Fd,
178 "revt(~p, ~p) -> {~p, ~p, \"~s~s\"};~n",
179 [Name, RExt, ExtType, Ext, MimeType, Charset]);
180 UExt ->
181 RUExt = lists:reverse(UExt),
182 io:format(Fd,
183 "revt(~p, ~p) -> {~p, ~p, \"~s~s\"};~n"
184 "revt(~p, ~p) -> {~p, ~p, \"~s~s\"};~n",
185 [Name, RExt, ExtType, Ext, MimeType, Charset,
186 Name, RUExt, ExtType, UExt, MimeType, Charset])
187 end,
188 generate_revt(Fd, Name, Rest, DefaultType, DefaultCharset).
0be3c7e @klacke untabified all of yaws
authored
189
190
191
89a64ef @capflam Make the mime types mappings configurable
capflam authored
192 %% ----
193 read_charset_file(File) ->
194 case file:read_file(File) of
195 {ok, B} ->
196 case string:tokens(binary_to_list(B),"\r\n\s\t\0\f") of
197 [] ->
198 undefined;
199 [Charset] ->
200 string:strip(Charset, both, 10);
201 _ ->
202 error_logger:format("Ignoring bad charset in ~p\n", [File]),
203 undefined
204 end;
205 {error, Reason} ->
206 error_logger:format("Cannot read ~p: ~p\n",
207 [File, file:format_error(Reason)]),
208 undefined
209 end.
210
211
212 %% ----
213 read_mime_types_file(File) ->
214 case file:open(File, [read]) of
215 {ok, Io} ->
216 %% Define mime-types for special extensions. It could be overridden
217 Acc0 = [{E, "text/html"} || E <- get_special_exts()],
218 read_mime_types_file(Io, 1, file:read_line(Io), Acc0);
219 {error, Reason} ->
220 error_logger:format("Cannot read ~p: ~p\n",
221 [File, file:format_error(Reason)]),
222 []
223 end.
224
225 read_mime_types_file(Io, _, eof, Acc) ->
226 file:close(Io),
227 lists:reverse(Acc);
228 read_mime_types_file(Io, Lno, {error, Reason}, Acc) ->
229 file:close(Io),
230 error_logger:format("read mime-types config failed at line ~p: ~p\n",
231 [Lno, file:format_error(Reason)]),
232 lists:reverse(Acc);
233 read_mime_types_file(Io, Lno, {ok, [$#|_]}, Acc) ->
234 read_mime_types_file(Io, Lno+1, file:read_line(Io), Acc);
235 read_mime_types_file(Io, Lno, {ok, [$\s|_]}, Acc) ->
236 read_mime_types_file(Io, Lno+1, file:read_line(Io), Acc);
237 read_mime_types_file(Io, Lno, {ok, Line}, Acc0) ->
238 case string:tokens(Line,"\r\n\s\t\0\f") of
239 [] ->
240 read_mime_types_file(Io, Lno+1, file:read_line(Io), Acc0);
241 [_] ->
242 read_mime_types_file(Io, Lno+1, file:read_line(Io), Acc0);
243 [MimeType | Exts] ->
244 Acc1 = lists:foldl(fun(Ext, Acc) ->
245 lists:keystore(Ext, 1, Acc,
246 {Ext, MimeType})
247 end, Acc0, Exts),
248 read_mime_types_file(Io, Lno+1, file:read_line(Io), Acc1)
249 end.
0be3c7e @klacke untabified all of yaws
authored
250
251
89a64ef @capflam Make the mime types mappings configurable
capflam authored
252 %% ----
253 get_special_exts() -> ["yaws", "php", "cgi", "fcgi"].
b4197ee @klacke ""
authored
254
89a64ef @capflam Make the mime types mappings configurable
capflam authored
255 get_ext_type("yaws") -> yaws;
256 get_ext_type("php") -> php;
257 get_ext_type("cgi") -> cgi;
258 get_ext_type("fcgi") -> fcgi;
259 get_ext_type(_) -> regular.
b4197ee @klacke ""
authored
260
261
Something went wrong with that request. Please try again.