iodine 0.1.21 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +3 -2
- data/.travis.yml +23 -2
- data/CHANGELOG.md +9 -2
- data/README.md +232 -179
- data/Rakefile +13 -1
- data/bin/config.ru +63 -0
- data/bin/console +6 -0
- data/bin/echo +42 -32
- data/bin/http-hello +62 -0
- data/bin/http-playground +124 -0
- data/bin/playground +62 -0
- data/bin/poc/Gemfile.lock +23 -0
- data/bin/poc/README.md +37 -0
- data/bin/poc/config.ru +66 -0
- data/bin/poc/gemfile +1 -0
- data/bin/poc/www/index.html +57 -0
- data/bin/raw-rbhttp +35 -0
- data/bin/raw_broadcast +66 -0
- data/bin/test_with_faye +40 -0
- data/bin/ws-broadcast +108 -0
- data/bin/ws-echo +108 -0
- data/exe/iodine +59 -0
- data/ext/iodine/base64.c +264 -0
- data/ext/iodine/base64.h +72 -0
- data/ext/iodine/bscrypt-common.h +109 -0
- data/ext/iodine/bscrypt.h +49 -0
- data/ext/iodine/extconf.rb +41 -0
- data/ext/iodine/hex.c +123 -0
- data/ext/iodine/hex.h +70 -0
- data/ext/iodine/http.c +200 -0
- data/ext/iodine/http.h +128 -0
- data/ext/iodine/http1.c +402 -0
- data/ext/iodine/http1.h +56 -0
- data/ext/iodine/http1_simple_parser.c +473 -0
- data/ext/iodine/http1_simple_parser.h +59 -0
- data/ext/iodine/http_request.h +128 -0
- data/ext/iodine/http_response.c +1606 -0
- data/ext/iodine/http_response.h +393 -0
- data/ext/iodine/http_response_http1.h +374 -0
- data/ext/iodine/iodine_core.c +641 -0
- data/ext/iodine/iodine_core.h +70 -0
- data/ext/iodine/iodine_http.c +615 -0
- data/ext/iodine/iodine_http.h +19 -0
- data/ext/iodine/iodine_websocket.c +430 -0
- data/ext/iodine/iodine_websocket.h +21 -0
- data/ext/iodine/libasync.c +552 -0
- data/ext/iodine/libasync.h +117 -0
- data/ext/iodine/libreact.c +347 -0
- data/ext/iodine/libreact.h +244 -0
- data/ext/iodine/libserver.c +912 -0
- data/ext/iodine/libserver.h +435 -0
- data/ext/iodine/libsock.c +950 -0
- data/ext/iodine/libsock.h +478 -0
- data/ext/iodine/misc.c +181 -0
- data/ext/iodine/misc.h +76 -0
- data/ext/iodine/random.c +193 -0
- data/ext/iodine/random.h +48 -0
- data/ext/iodine/rb-call.c +127 -0
- data/ext/iodine/rb-call.h +60 -0
- data/ext/iodine/rb-libasync.h +79 -0
- data/ext/iodine/rb-rack-io.c +389 -0
- data/ext/iodine/rb-rack-io.h +17 -0
- data/ext/iodine/rb-registry.c +213 -0
- data/ext/iodine/rb-registry.h +33 -0
- data/ext/iodine/sha1.c +359 -0
- data/ext/iodine/sha1.h +85 -0
- data/ext/iodine/sha2.c +825 -0
- data/ext/iodine/sha2.h +138 -0
- data/ext/iodine/siphash.c +136 -0
- data/ext/iodine/siphash.h +15 -0
- data/ext/iodine/spnlock.h +235 -0
- data/ext/iodine/websockets.c +696 -0
- data/ext/iodine/websockets.h +120 -0
- data/ext/iodine/xor-crypt.c +189 -0
- data/ext/iodine/xor-crypt.h +107 -0
- data/iodine.gemspec +25 -18
- data/lib/iodine.rb +57 -58
- data/lib/iodine/http.rb +0 -189
- data/lib/iodine/protocol.rb +36 -245
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +145 -2
- metadata +115 -37
- data/bin/core_http_test +0 -51
- data/bin/em playground +0 -56
- data/bin/hello_world +0 -75
- data/bin/setup +0 -7
- data/lib/iodine/client.rb +0 -5
- data/lib/iodine/core.rb +0 -102
- data/lib/iodine/core_init.rb +0 -143
- data/lib/iodine/http/hpack.rb +0 -553
- data/lib/iodine/http/http1.rb +0 -251
- data/lib/iodine/http/http2.rb +0 -507
- data/lib/iodine/http/rack_support.rb +0 -108
- data/lib/iodine/http/request.rb +0 -462
- data/lib/iodine/http/response.rb +0 -474
- data/lib/iodine/http/session.rb +0 -143
- data/lib/iodine/http/websocket_client.rb +0 -335
- data/lib/iodine/http/websocket_handler.rb +0 -101
- data/lib/iodine/http/websockets.rb +0 -336
- data/lib/iodine/io.rb +0 -56
- data/lib/iodine/logging.rb +0 -46
- data/lib/iodine/settings.rb +0 -158
- data/lib/iodine/ssl_connector.rb +0 -48
- data/lib/iodine/timers.rb +0 -95
@@ -0,0 +1,59 @@
|
|
1
|
+
#ifndef HTTP1_SIMPLE_PARSER_H
|
2
|
+
#define HTTP1_SIMPLE_PARSER_H
|
3
|
+
#include "http_request.h"
|
4
|
+
|
5
|
+
#ifndef HTTP_HEADERS_LOWERCASE
|
6
|
+
/** when defined, HTTP headers will be converted to lowercase and header
|
7
|
+
* searches will be case sensitive. This improves the parser performance in some
|
8
|
+
* instances (which surprised me.) */
|
9
|
+
#define HTTP_HEADERS_LOWERCASE 1
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifndef HTTP_PARSER_TEST
|
13
|
+
/* a debugging flag that adds the test function and decleration */
|
14
|
+
#define HTTP_PARSER_TEST 0
|
15
|
+
#endif
|
16
|
+
|
17
|
+
/**
|
18
|
+
Parses HTTP request headers. This allows review of the expected content length
|
19
|
+
before accepting any content (server resource management).
|
20
|
+
|
21
|
+
Returns the number of bytes consumed before the full request was accepted.
|
22
|
+
|
23
|
+
Returns -1 on fatal error (i.e. protocol error).
|
24
|
+
Returns -2 when the request parsing didn't complete.
|
25
|
+
|
26
|
+
Incomplete request parsing updates the content in the buffer. The same buffer
|
27
|
+
and the same `http_request_s` should be returned to the parsed on the next
|
28
|
+
attempt, only the `len` argument is expected to grow.
|
29
|
+
|
30
|
+
The buffer should be kept intact for the life of the request object, as the
|
31
|
+
HTTP/1.1 parser does NOT copy any data.
|
32
|
+
*/
|
33
|
+
ssize_t http1_parse_request_headers(void* buffer,
|
34
|
+
size_t len,
|
35
|
+
http_request_s* request);
|
36
|
+
|
37
|
+
/**
|
38
|
+
Parses HTTP request body content (if any).
|
39
|
+
|
40
|
+
Returns the number of bytes consumed before the body consumption was complete.
|
41
|
+
|
42
|
+
Returns -1 on fatal error (i.e. protocol error).
|
43
|
+
Returns -2 when the request parsing didn't complete (all the data was consumed).
|
44
|
+
|
45
|
+
Incomplete body parsing doesn't require the buffer to remain static (it can be
|
46
|
+
recycled).
|
47
|
+
|
48
|
+
It is expected that the next attempt will contain fresh data in the `buffer`
|
49
|
+
argument.
|
50
|
+
*/
|
51
|
+
ssize_t http1_parse_request_body(void* buffer,
|
52
|
+
size_t len,
|
53
|
+
http_request_s* request);
|
54
|
+
|
55
|
+
#if defined(DEBUG) && DEBUG == 1
|
56
|
+
void http_parser_test(void);
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#endif
|
@@ -0,0 +1,128 @@
|
|
1
|
+
#ifndef HTTP_REQUEST_H
|
2
|
+
#define HTTP_REQUEST_H
|
3
|
+
|
4
|
+
#ifndef _GNU_SOURCE
|
5
|
+
#define _GNU_SOURCE
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdint.h>
|
11
|
+
#include <unistd.h>
|
12
|
+
#include <string.h>
|
13
|
+
|
14
|
+
#ifndef __unused
|
15
|
+
#define __unused __attribute__((unused))
|
16
|
+
#endif
|
17
|
+
|
18
|
+
typedef struct {
|
19
|
+
const char* name;
|
20
|
+
const char* value;
|
21
|
+
uint16_t name_length;
|
22
|
+
uint16_t value_length;
|
23
|
+
} http_headers_s;
|
24
|
+
|
25
|
+
typedef struct {
|
26
|
+
/** points to the HTTP method name. */
|
27
|
+
const char* method;
|
28
|
+
/** The portion of the request URL that comes before the '?', if any. */
|
29
|
+
const char* path;
|
30
|
+
/** The string length of the path (editing the path requires update). */
|
31
|
+
/** The portion of the request URL that follows the ?, if any. */
|
32
|
+
const char* query;
|
33
|
+
/** Points to a version string. */
|
34
|
+
const char* version;
|
35
|
+
/** Points to the body's host header value (a required header). */
|
36
|
+
const char* host;
|
37
|
+
/** points to the body's content type header, if any. */
|
38
|
+
const char* content_type;
|
39
|
+
/** points to the Upgrade header, if any. */
|
40
|
+
const char* upgrade;
|
41
|
+
/** points to the Connection header, if any. */
|
42
|
+
const char* connection;
|
43
|
+
|
44
|
+
/** the body's content's length, in bytes (can be 0). */
|
45
|
+
size_t content_length;
|
46
|
+
|
47
|
+
/* string lengths */
|
48
|
+
|
49
|
+
uint16_t method_len;
|
50
|
+
uint16_t path_len;
|
51
|
+
uint16_t query_len;
|
52
|
+
uint16_t host_len;
|
53
|
+
uint16_t content_type_len;
|
54
|
+
uint16_t upgrade_len;
|
55
|
+
|
56
|
+
/** `version_len` is signed, to allow negative values (SPDY/HTTP2 etc). */
|
57
|
+
int16_t version_len;
|
58
|
+
|
59
|
+
/**
|
60
|
+
Points the body of the request, if the body exists and is stored in memory.
|
61
|
+
Otherwise, NULL. */
|
62
|
+
const char* body_str;
|
63
|
+
/** points a tmpfile file descriptor containing the body of the request. */
|
64
|
+
int body_file;
|
65
|
+
/** semi-private information. */
|
66
|
+
struct {
|
67
|
+
/**
|
68
|
+
When pooling request objects, this points to the next object.
|
69
|
+
In other times it may contain arbitrary data that can be used by the parser
|
70
|
+
or implementation.
|
71
|
+
*/
|
72
|
+
void* next;
|
73
|
+
/**
|
74
|
+
Implementation specific. This, conceptually, holds information about the
|
75
|
+
"owner" of this request. */
|
76
|
+
void* owner;
|
77
|
+
/**
|
78
|
+
Implementation specific. This, conceptually, holds the connection that
|
79
|
+
"owns" this request, or an implementation identifier. */
|
80
|
+
intptr_t fd;
|
81
|
+
/** the current header position, for API or parser states. */
|
82
|
+
uint16_t headers_pos;
|
83
|
+
/** the maximum number of header space availble. */
|
84
|
+
uint16_t max_headers;
|
85
|
+
} metadata;
|
86
|
+
|
87
|
+
uint16_t connection_len;
|
88
|
+
uint16_t headers_count;
|
89
|
+
|
90
|
+
http_headers_s headers[];
|
91
|
+
} http_request_s;
|
92
|
+
|
93
|
+
__unused static inline void http_request_clear(http_request_s* request) {
|
94
|
+
if (request->body_file > 0) /* assumes no tempfile with fd 0 */
|
95
|
+
close(request->body_file);
|
96
|
+
*request = (http_request_s){
|
97
|
+
.metadata.owner = request->metadata.owner,
|
98
|
+
.metadata.fd = request->metadata.fd,
|
99
|
+
.metadata.max_headers = request->metadata.max_headers,
|
100
|
+
};
|
101
|
+
}
|
102
|
+
|
103
|
+
/** searches for a header in the header array, both reaturnning it's value and
|
104
|
+
* setting it's position in the `request->metadata.header_pos` variable.*/
|
105
|
+
__unused static inline const char* http_request_find_header(
|
106
|
+
http_request_s* request,
|
107
|
+
const char* header,
|
108
|
+
size_t header_len) {
|
109
|
+
if (header == NULL || request == NULL)
|
110
|
+
return NULL;
|
111
|
+
if (header_len == 0)
|
112
|
+
header_len = strlen(header);
|
113
|
+
request->metadata.headers_pos = 0;
|
114
|
+
while (request->metadata.headers_pos < request->headers_count) {
|
115
|
+
if (header_len ==
|
116
|
+
request->headers[request->metadata.headers_pos].name_length &&
|
117
|
+
strncasecmp(request->headers[request->metadata.headers_pos].name,
|
118
|
+
header, header_len) == 0)
|
119
|
+
return request->headers[request->metadata.headers_pos].value;
|
120
|
+
request->metadata.headers_pos += 1;
|
121
|
+
}
|
122
|
+
return NULL;
|
123
|
+
}
|
124
|
+
|
125
|
+
#define HTTP_REQUEST_SIZE(header_count) \
|
126
|
+
(sizeof(http_request_s) + ((header_count) * sizeof(http_headers_s)))
|
127
|
+
|
128
|
+
#endif
|
@@ -0,0 +1,1606 @@
|
|
1
|
+
#include "http.h"
|
2
|
+
#include "http_response_http1.h"
|
3
|
+
#include <netinet/in.h>
|
4
|
+
#include <netinet/ip.h>
|
5
|
+
#include <arpa/inet.h>
|
6
|
+
#include <fcntl.h>
|
7
|
+
#include <sys/stat.h>
|
8
|
+
#include <sys/types.h>
|
9
|
+
#include <sys/socket.h>
|
10
|
+
#include <time.h>
|
11
|
+
#include <sys/resource.h>
|
12
|
+
|
13
|
+
/* *****************************************************************************
|
14
|
+
Helpers
|
15
|
+
***************************************************************************** */
|
16
|
+
|
17
|
+
#define forward_func(response, func, ...) \
|
18
|
+
if ((response)->metadata.version == 1) { \
|
19
|
+
return h1p_##func(__VA_ARGS__); \
|
20
|
+
} else \
|
21
|
+
return -1;
|
22
|
+
#define perform_func(response, func, ...) \
|
23
|
+
if ((response)->metadata.version == 1) { \
|
24
|
+
h1p_##func(__VA_ARGS__); \
|
25
|
+
}
|
26
|
+
|
27
|
+
// static char* MONTH_NAMES[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ",
|
28
|
+
// "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec
|
29
|
+
// "};
|
30
|
+
//
|
31
|
+
#define is_num(c) ((c) >= '0' && (c) <= '9')
|
32
|
+
#define num_val(c) ((c)-48)
|
33
|
+
|
34
|
+
/* *****************************************************************************
|
35
|
+
API implementation
|
36
|
+
***************************************************************************** */
|
37
|
+
|
38
|
+
/**
|
39
|
+
Initializes a response object with the request object. This function assumes the
|
40
|
+
response object memory is garbage and might have been stack-allocated.
|
41
|
+
|
42
|
+
Notice that the `http_request_s` pointer must point at a valid request object
|
43
|
+
and that the request object must remain valid until the response had been
|
44
|
+
completed.
|
45
|
+
|
46
|
+
Hangs on failuer (waits for available resources).
|
47
|
+
*/
|
48
|
+
http_response_s http_response_init(http_request_s *request) {
|
49
|
+
protocol_s *http = request->metadata.owner;
|
50
|
+
time_t date = server_last_tick();
|
51
|
+
return (http_response_s){
|
52
|
+
.metadata.request = request,
|
53
|
+
.metadata.fd = request->metadata.fd,
|
54
|
+
.metadata.packet = sock_checkout_packet(),
|
55
|
+
.status = 200,
|
56
|
+
.date = date,
|
57
|
+
.last_modified = date,
|
58
|
+
.metadata.version = (http->service == HTTP1 ? 1 : 0),
|
59
|
+
.metadata.should_close =
|
60
|
+
(request && request->connection &&
|
61
|
+
request->connection_len ==
|
62
|
+
5), // don't check header value, length is unique enough.
|
63
|
+
};
|
64
|
+
}
|
65
|
+
/**
|
66
|
+
Releases any resources held by the response object (doesn't release the response
|
67
|
+
object itself, which might have been allocated on the stack).
|
68
|
+
|
69
|
+
This function assumes the response object might have been stack-allocated.
|
70
|
+
*/
|
71
|
+
void http_response_destroy(http_response_s *response) {
|
72
|
+
if (response->metadata.packet) {
|
73
|
+
sock_free_packet(response->metadata.packet);
|
74
|
+
response->metadata.packet = NULL;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
/**
|
78
|
+
Writes a header to the response. This function writes only the requested
|
79
|
+
number of bytes from the header name and the requested number of bytes from
|
80
|
+
the header value. It can be used even when the header name and value don't
|
81
|
+
contain NULL terminating bytes by passing the `.name_len` or `.value_len` data
|
82
|
+
in the `http_headers_s` structure.
|
83
|
+
|
84
|
+
If the header buffer is full or the headers were already sent (new headers
|
85
|
+
cannot be sent), the function will return -1.
|
86
|
+
|
87
|
+
On success, the function returns 0.
|
88
|
+
*/
|
89
|
+
#undef http_response_write_header
|
90
|
+
int http_response_write_header(http_response_s *response,
|
91
|
+
http_headers_s header) {
|
92
|
+
// check if the header is a reserved header
|
93
|
+
if ((header.name_length == 4 || header.name_length == 0) &&
|
94
|
+
strncasecmp(header.name, "date", 4) == 0)
|
95
|
+
response->metadata.date_written = 1;
|
96
|
+
else if ((header.name_length == 10 || header.name_length == 0) &&
|
97
|
+
strncasecmp(header.name, "connection", 10) == 0) {
|
98
|
+
response->metadata.connection_written = 1;
|
99
|
+
if (header.value && header.value[0] == 'c')
|
100
|
+
response->metadata.should_close = 1;
|
101
|
+
} else if ((header.name_length == 14 || header.name_length == 0) &&
|
102
|
+
strncasecmp(header.name, "content-length", 14) == 0)
|
103
|
+
response->metadata.content_length_written = 1;
|
104
|
+
|
105
|
+
// write the header to the protocol
|
106
|
+
forward_func(response, response_write_header, response, header);
|
107
|
+
}
|
108
|
+
#define http_response_write_header(response, ...) \
|
109
|
+
http_response_write_header(response, (http_headers_s){__VA_ARGS__})
|
110
|
+
|
111
|
+
/**
|
112
|
+
Set / Delete a cookie using this helper function.
|
113
|
+
|
114
|
+
To set a cookie, use (in this example, a session cookie):
|
115
|
+
|
116
|
+
http_response_set_cookie(response,
|
117
|
+
.name = "my_cookie",
|
118
|
+
.value = "data");
|
119
|
+
|
120
|
+
To delete a cookie, use:
|
121
|
+
|
122
|
+
http_response_set_cookie(response,
|
123
|
+
.name = "my_cookie",
|
124
|
+
.value = NULL);
|
125
|
+
|
126
|
+
This function writes a cookie header to the response. Only the requested
|
127
|
+
number of bytes from the cookie value and name are written (if none are
|
128
|
+
provided, a terminating NULL byte is assumed).
|
129
|
+
|
130
|
+
Both the name and the value of the cookie are checked for validity (legal
|
131
|
+
characters), but other properties aren't reviewed (domain/path) - please make
|
132
|
+
sure to use only valid data, as HTTP imposes restrictions on these things.
|
133
|
+
|
134
|
+
If the header buffer is full or the headers were already sent (new headers
|
135
|
+
cannot be sent), the function will return -1.
|
136
|
+
|
137
|
+
On success, the function returns 0.
|
138
|
+
*/
|
139
|
+
#undef http_response_set_cookie
|
140
|
+
int http_response_set_cookie(http_response_s *response, http_cookie_s cookie) {
|
141
|
+
forward_func(response, response_set_cookie, response, cookie);
|
142
|
+
};
|
143
|
+
|
144
|
+
/**
|
145
|
+
Indicates that any pending data (i.e. unsent headers) should be sent and that no
|
146
|
+
more use of the response object will be made.
|
147
|
+
*/
|
148
|
+
void http_response_finish(http_response_s *response) {
|
149
|
+
perform_func(response, response_finish, response);
|
150
|
+
if (response->metadata.logged)
|
151
|
+
http_response_log_finish(response);
|
152
|
+
http_response_destroy(response);
|
153
|
+
}
|
154
|
+
/**
|
155
|
+
Sends the headers (if they weren't previously sent) and writes the data to the
|
156
|
+
underlying socket.
|
157
|
+
|
158
|
+
The body will be copied to the server's outgoing buffer.
|
159
|
+
|
160
|
+
If the connection was already closed, the function will return -1. On success,
|
161
|
+
the function returns 0.
|
162
|
+
*/
|
163
|
+
int http_response_write_body(http_response_s *response, const char *body,
|
164
|
+
size_t length) {
|
165
|
+
forward_func(response, response_write_body, response, body, length);
|
166
|
+
}
|
167
|
+
/**
|
168
|
+
Sends the headers (if they weren't previously sent) and writes the data to the
|
169
|
+
underlying socket.
|
170
|
+
|
171
|
+
The server's outgoing buffer will take ownership of the file and close it
|
172
|
+
using `fclose` once the data was sent.
|
173
|
+
|
174
|
+
If the connection was already closed, the function will return -1. On success,
|
175
|
+
the function returns 0.
|
176
|
+
*/
|
177
|
+
int http_response_sendfile(http_response_s *response, int source_fd,
|
178
|
+
off_t offset, size_t length) {
|
179
|
+
forward_func(response, response_sendfile, response, source_fd, offset,
|
180
|
+
length);
|
181
|
+
}
|
182
|
+
/**
|
183
|
+
Attempts to send the file requested using an **optional** response object (if no
|
184
|
+
response object is pointed to, a temporary response object will be created).
|
185
|
+
|
186
|
+
If a `file_path_unsafe` is provided, it will be appended to the `file_path_safe`
|
187
|
+
(if any) and URL decoded before attempting to locate and open the file. Any
|
188
|
+
insecure path manipulations in the `file_path_unsafe` (i.e. `..` or `//`) will
|
189
|
+
cause the function to fail.
|
190
|
+
|
191
|
+
`file_path_unsafe` MUST begine with a `/`, or it will be appended to
|
192
|
+
`file_path_safe` as part of the last folder's name. if `file_path_safe` ends
|
193
|
+
with a `/`, it will be trancated.
|
194
|
+
|
195
|
+
If the `log` flag is set, response logging will be performed.
|
196
|
+
|
197
|
+
On failure, the function will return -1 (no response will be sent).
|
198
|
+
|
199
|
+
On success, the function returns 0.
|
200
|
+
*/
|
201
|
+
int http_response_sendfile2(http_response_s *response, http_request_s *request,
|
202
|
+
const char *file_path_safe, size_t path_safe_len,
|
203
|
+
const char *file_path_unsafe,
|
204
|
+
size_t path_unsafe_len, uint8_t log) {
|
205
|
+
static char *HEAD = "HEAD";
|
206
|
+
if (request == NULL || (file_path_safe == NULL && file_path_unsafe == NULL))
|
207
|
+
return -1;
|
208
|
+
http_response_s tmp_response;
|
209
|
+
|
210
|
+
if (file_path_safe && path_safe_len == 0)
|
211
|
+
path_safe_len = strlen(file_path_safe);
|
212
|
+
|
213
|
+
if (file_path_unsafe && path_unsafe_len == 0)
|
214
|
+
path_unsafe_len = strlen(file_path_unsafe);
|
215
|
+
|
216
|
+
const char *mime = NULL;
|
217
|
+
const char *ext = NULL;
|
218
|
+
struct stat file_data = {};
|
219
|
+
// fprintf(stderr, "\n\noriginal request path: %s\n", req->path);
|
220
|
+
char *fname = malloc(path_safe_len + path_unsafe_len + 1 + 11);
|
221
|
+
if (fname == NULL)
|
222
|
+
return -1;
|
223
|
+
if (file_path_safe)
|
224
|
+
memcpy(fname, file_path_safe, path_safe_len);
|
225
|
+
fname[path_safe_len] = 0;
|
226
|
+
// if the last character is a '/', step back.
|
227
|
+
if (file_path_unsafe) {
|
228
|
+
if (fname[path_safe_len - 1] == '/')
|
229
|
+
path_safe_len--;
|
230
|
+
ssize_t tmp = http_decode_url(fname + path_safe_len, file_path_unsafe,
|
231
|
+
path_unsafe_len);
|
232
|
+
if (tmp < 0)
|
233
|
+
goto no_file;
|
234
|
+
path_safe_len += tmp;
|
235
|
+
if (fname[path_safe_len - 1] == '/') {
|
236
|
+
memcpy(fname + path_safe_len, "index.html", 10);
|
237
|
+
fname[path_safe_len += 10] = 0;
|
238
|
+
}
|
239
|
+
|
240
|
+
// scan path string for double dots (security - prevent path manipulation)
|
241
|
+
// set the extention point value, while were doing so.
|
242
|
+
tmp = 0;
|
243
|
+
while (fname[tmp]) {
|
244
|
+
if (fname[tmp] == '.')
|
245
|
+
ext = fname + tmp;
|
246
|
+
// return false if we found a "/.." or "/" in our string.
|
247
|
+
if (fname[tmp++] == '/' &&
|
248
|
+
((fname[tmp++] == '.' && fname[tmp++] == '.') || fname[tmp] == '/'))
|
249
|
+
goto no_file;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
// fprintf(stderr, "file name: %s\noriginal request path: %s\n", fname,
|
253
|
+
// req->path);
|
254
|
+
// get file data (prevent folder access and get modification date)
|
255
|
+
if (stat(fname, &file_data))
|
256
|
+
goto no_file;
|
257
|
+
// check that we have a file and not something else
|
258
|
+
if (!S_ISREG(file_data.st_mode) && !S_ISLNK(file_data.st_mode))
|
259
|
+
goto no_file;
|
260
|
+
|
261
|
+
if (response == NULL) {
|
262
|
+
response = &tmp_response;
|
263
|
+
tmp_response = http_response_init(request);
|
264
|
+
if (log)
|
265
|
+
http_response_log_start(response);
|
266
|
+
}
|
267
|
+
|
268
|
+
if (*((uint32_t *)request->method) == *((uint32_t *)HEAD)) {
|
269
|
+
forward_func(response, response_finish, response);
|
270
|
+
}
|
271
|
+
|
272
|
+
// we have a file, time to handle response details.
|
273
|
+
int file = open(fname, O_RDONLY);
|
274
|
+
if (file == -1) {
|
275
|
+
goto no_file;
|
276
|
+
}
|
277
|
+
// free the allocated fname memory
|
278
|
+
free(fname);
|
279
|
+
fname = NULL;
|
280
|
+
|
281
|
+
// get the mime type (we have an ext pointer and the string isn't empty)
|
282
|
+
if (ext && ext[1]) {
|
283
|
+
mime = http_response_ext2mime(ext + 1);
|
284
|
+
if (mime) {
|
285
|
+
http_response_write_header(response, .name = "Content-Type",
|
286
|
+
.name_length = 12, .value = mime);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
response->last_modified = file_data.st_mtime;
|
291
|
+
http_response_write_header(response, .name = "Cache-Control",
|
292
|
+
.name_length = 13, .value = "public, max-age=3600",
|
293
|
+
.value_length = 20);
|
294
|
+
|
295
|
+
// Range handling
|
296
|
+
if ((ext = http_request_find_header(request, "range", 5)) &&
|
297
|
+
(ext[0] | 32) == 'b' && (ext[1] | 32) == 'y' && (ext[2] | 32) == 't' &&
|
298
|
+
(ext[3] | 32) == 'e' && (ext[4] | 32) == 's' && (ext[5] | 32) == '=') {
|
299
|
+
// ext holds the first range, starting on index 6 i.e. RANGE: bytes=0-1
|
300
|
+
// "HTTP/1.1 206 Partial content\r\n"
|
301
|
+
// "Accept-Ranges: bytes\r\n"
|
302
|
+
// "Content-Range: bytes %lu-%lu/%lu\r\n"
|
303
|
+
// fprintf(stderr, "Got a range request %s\n", ext);
|
304
|
+
size_t start = 0, finish = 0;
|
305
|
+
ext = ext + 6;
|
306
|
+
while (is_num(*ext)) {
|
307
|
+
start = start * 10;
|
308
|
+
start += num_val(*ext);
|
309
|
+
ext++;
|
310
|
+
}
|
311
|
+
// fprintf(stderr, "Start: %lu / %lld\n", start, file_data.st_size);
|
312
|
+
if (start >= file_data.st_size - 1)
|
313
|
+
goto invalid_range;
|
314
|
+
ext++;
|
315
|
+
while (is_num(*ext)) {
|
316
|
+
finish = finish * 10;
|
317
|
+
finish += num_val(*ext);
|
318
|
+
ext++;
|
319
|
+
}
|
320
|
+
// going to the EOF (big chunk or EOL requested) - send as file
|
321
|
+
if (finish >= file_data.st_size)
|
322
|
+
finish = file_data.st_size;
|
323
|
+
char buffer[64];
|
324
|
+
char *pos = buffer + 6;
|
325
|
+
memcpy(buffer, "bytes ", 6);
|
326
|
+
pos += http_ul2a(pos, start);
|
327
|
+
*(pos++) = '-';
|
328
|
+
pos += http_ul2a(pos, finish);
|
329
|
+
*(pos++) = '/';
|
330
|
+
pos += http_ul2a(pos, file_data.st_size);
|
331
|
+
http_response_write_header(response, .name = "Content-Range",
|
332
|
+
.name_length = 13, .value = buffer,
|
333
|
+
.value_length = pos - buffer);
|
334
|
+
response->status = 206;
|
335
|
+
http_response_write_header(response, .name = "Accept-Ranges",
|
336
|
+
.name_length = 13, .value = "bytes",
|
337
|
+
.value_length = 5);
|
338
|
+
|
339
|
+
http_response_sendfile(response, file, start, finish - start + 1);
|
340
|
+
if (log)
|
341
|
+
http_response_log_finish(response);
|
342
|
+
return 0;
|
343
|
+
}
|
344
|
+
|
345
|
+
invalid_range:
|
346
|
+
http_response_write_header(response, .name = "Accept-Ranges",
|
347
|
+
.name_length = 13, .value = "none",
|
348
|
+
.value_length = 4);
|
349
|
+
|
350
|
+
http_response_sendfile(response, file, 0, file_data.st_size);
|
351
|
+
if (log)
|
352
|
+
http_response_log_finish(response);
|
353
|
+
return 0;
|
354
|
+
no_file:
|
355
|
+
free(fname);
|
356
|
+
return -1;
|
357
|
+
}
|
358
|
+
|
359
|
+
#ifdef RUSAGE_SELF
|
360
|
+
const static size_t CLOCK_RESOLUTION = 1000; /* in miliseconds */
|
361
|
+
static size_t get_clock_mili(void) {
|
362
|
+
struct rusage rusage;
|
363
|
+
getrusage(RUSAGE_SELF, &rusage);
|
364
|
+
return ((rusage.ru_utime.tv_sec + rusage.ru_stime.tv_sec) * 1000000) +
|
365
|
+
(rusage.ru_utime.tv_usec + rusage.ru_stime.tv_usec);
|
366
|
+
}
|
367
|
+
#elif defined CLOCKS_PER_SEC
|
368
|
+
#define get_clock_mili() (size_t) clock()
|
369
|
+
#define CLOCK_RESOLUTION (CLOCKS_PER_SEC / 1000)
|
370
|
+
#else
|
371
|
+
#define get_clock_mili() 0
|
372
|
+
#define CLOCK_RESOLUTION 1
|
373
|
+
#endif
|
374
|
+
|
375
|
+
/**
|
376
|
+
Starts counting miliseconds for log results.
|
377
|
+
*/
|
378
|
+
void http_response_log_start(http_response_s *response) {
|
379
|
+
response->metadata.clock_start = get_clock_mili();
|
380
|
+
response->metadata.logged = 1;
|
381
|
+
}
|
382
|
+
/**
|
383
|
+
prints out the log to stderr.
|
384
|
+
*/
|
385
|
+
void http_response_log_finish(http_response_s *response) {
|
386
|
+
// TODO optimize using fwrite
|
387
|
+
http_request_s *request = response->metadata.request;
|
388
|
+
uintptr_t bytes_sent = (uintptr_t)response->metadata.headers_pos;
|
389
|
+
|
390
|
+
size_t mili = response->metadata.logged
|
391
|
+
? ((get_clock_mili() - response->metadata.clock_start) /
|
392
|
+
CLOCK_RESOLUTION)
|
393
|
+
: 0;
|
394
|
+
struct tm tm;
|
395
|
+
struct sockaddr_in addrinfo;
|
396
|
+
socklen_t addrlen = sizeof(addrinfo);
|
397
|
+
time_t last_tick = server_last_tick();
|
398
|
+
http_gmtime(&last_tick, &tm);
|
399
|
+
int got_add = getpeername(sock_uuid2fd(request->metadata.fd),
|
400
|
+
(struct sockaddr *)&addrinfo, &addrlen);
|
401
|
+
#define HTTP_REQUEST_LOG_LIMIT 128
|
402
|
+
char buffer[HTTP_REQUEST_LOG_LIMIT];
|
403
|
+
char *tmp;
|
404
|
+
size_t pos;
|
405
|
+
if (got_add == 0) {
|
406
|
+
tmp = inet_ntoa(addrinfo.sin_addr);
|
407
|
+
pos = strlen(tmp);
|
408
|
+
memcpy(buffer, tmp, pos);
|
409
|
+
} else {
|
410
|
+
memcpy(buffer, "[unknown]", 9);
|
411
|
+
pos = 9;
|
412
|
+
}
|
413
|
+
memcpy(buffer + pos, " - - [", 6);
|
414
|
+
pos += 6;
|
415
|
+
pos += http_date2str(buffer + pos, &tm);
|
416
|
+
buffer[pos++] = ']';
|
417
|
+
buffer[pos++] = ' ';
|
418
|
+
buffer[pos++] = '"';
|
419
|
+
// limit method to 10 chars
|
420
|
+
if (request->method_len <= 10) {
|
421
|
+
memcpy(buffer + pos, request->method, request->method_len);
|
422
|
+
pos += request->method_len;
|
423
|
+
} else {
|
424
|
+
const char *j = request->method;
|
425
|
+
// copy first 7 chars
|
426
|
+
while (j < request->method + 7)
|
427
|
+
buffer[pos++] = *(j++);
|
428
|
+
// add three dots.
|
429
|
+
buffer[pos++] = '.';
|
430
|
+
buffer[pos++] = '.';
|
431
|
+
buffer[pos++] = '.';
|
432
|
+
}
|
433
|
+
buffer[pos++] = ' ';
|
434
|
+
// limit path to 24 chars
|
435
|
+
if (request->path_len <= 24) {
|
436
|
+
memcpy(buffer + pos, request->path, request->path_len);
|
437
|
+
pos += request->path_len;
|
438
|
+
} else {
|
439
|
+
const char *j = request->path;
|
440
|
+
// copy first 7 chars
|
441
|
+
while (j < request->path + 21)
|
442
|
+
buffer[pos++] = *(j++);
|
443
|
+
// add three dots.
|
444
|
+
buffer[pos++] = '.';
|
445
|
+
buffer[pos++] = '.';
|
446
|
+
buffer[pos++] = '.';
|
447
|
+
}
|
448
|
+
buffer[pos++] = ' ';
|
449
|
+
// limit version to 10 chars
|
450
|
+
if (request->version_len <= 10) {
|
451
|
+
memcpy(buffer + pos, request->version, request->version_len);
|
452
|
+
pos += request->version_len;
|
453
|
+
} else {
|
454
|
+
const char *j = request->version;
|
455
|
+
// copy first 7 chars
|
456
|
+
while (j < request->version + 7)
|
457
|
+
buffer[pos++] = *(j++);
|
458
|
+
// add three dots.
|
459
|
+
buffer[pos++] = '.';
|
460
|
+
buffer[pos++] = '.';
|
461
|
+
buffer[pos++] = '.';
|
462
|
+
}
|
463
|
+
buffer[pos++] = '"';
|
464
|
+
buffer[pos++] = ' ';
|
465
|
+
pos += http_ul2a(buffer + pos, response->status > 0 && response->status < 1000
|
466
|
+
? response->status
|
467
|
+
: 0);
|
468
|
+
|
469
|
+
buffer[pos++] = ' ';
|
470
|
+
pos += http_ul2a(buffer + pos, bytes_sent);
|
471
|
+
if (response->metadata.logged) {
|
472
|
+
buffer[pos++] = ' ';
|
473
|
+
pos += http_ul2a(buffer + pos, mili);
|
474
|
+
buffer[pos++] = 'm';
|
475
|
+
buffer[pos++] = 's';
|
476
|
+
}
|
477
|
+
buffer[pos++] = '\n';
|
478
|
+
response->metadata.logged = 0;
|
479
|
+
fwrite(buffer, 1, pos, stderr);
|
480
|
+
}
|
481
|
+
|
482
|
+
/* *****************************************************************************
|
483
|
+
Hardcded lists / matching
|
484
|
+
*****************************************************************************
|
485
|
+
*/
|
486
|
+
|
487
|
+
/** Gets a response status, as a string */
|
488
|
+
const char *http_response_status_str(uint16_t status) {
|
489
|
+
static struct {
|
490
|
+
int i_status;
|
491
|
+
char *s_status;
|
492
|
+
} List[] = {{200, "OK"},
|
493
|
+
{301, "Moved Permanently"},
|
494
|
+
{302, "Found"},
|
495
|
+
{100, "Continue"},
|
496
|
+
{101, "Switching Protocols"},
|
497
|
+
{403, "Forbidden"},
|
498
|
+
{404, "Not Found"},
|
499
|
+
{400, "Bad Request"},
|
500
|
+
{500, "Internal Server Error"},
|
501
|
+
{501, "Not Implemented"},
|
502
|
+
{502, "Bad Gateway"},
|
503
|
+
{503, "Service Unavailable"},
|
504
|
+
{102, "Processing"},
|
505
|
+
{201, "Created"},
|
506
|
+
{202, "Accepted"},
|
507
|
+
{203, "Non-Authoritative Information"},
|
508
|
+
{204, "No Content"},
|
509
|
+
{205, "Reset Content"},
|
510
|
+
{206, "Partial Content"},
|
511
|
+
{207, "Multi-Status"},
|
512
|
+
{208, "Already Reported"},
|
513
|
+
{226, "IM Used"},
|
514
|
+
{300, "Multiple Choices"},
|
515
|
+
{303, "See Other"},
|
516
|
+
{304, "Not Modified"},
|
517
|
+
{305, "Use Proxy"},
|
518
|
+
{306, "(Unused) "},
|
519
|
+
{307, "Temporary Redirect"},
|
520
|
+
{308, "Permanent Redirect"},
|
521
|
+
{401, "Unauthorized"},
|
522
|
+
{402, "Payment Required"},
|
523
|
+
{405, "Method Not Allowed"},
|
524
|
+
{406, "Not Acceptable"},
|
525
|
+
{407, "Proxy Authentication Required"},
|
526
|
+
{408, "Request Timeout"},
|
527
|
+
{409, "Conflict"},
|
528
|
+
{410, "Gone"},
|
529
|
+
{411, "Length Required"},
|
530
|
+
{412, "Precondition Failed"},
|
531
|
+
{413, "Payload Too Large"},
|
532
|
+
{414, "URI Too Long"},
|
533
|
+
{415, "Unsupported Media Type"},
|
534
|
+
{416, "Range Not Satisfiable"},
|
535
|
+
{417, "Expectation Failed"},
|
536
|
+
{421, "Misdirected Request"},
|
537
|
+
{422, "Unprocessable Entity"},
|
538
|
+
{423, "Locked"},
|
539
|
+
{424, "Failed Dependency"},
|
540
|
+
{425, "Unassigned"},
|
541
|
+
{426, "Upgrade Required"},
|
542
|
+
{427, "Unassigned"},
|
543
|
+
{428, "Precondition Required"},
|
544
|
+
{429, "Too Many Requests"},
|
545
|
+
{430, "Unassigned"},
|
546
|
+
{431, "Request Header Fields Too Large"},
|
547
|
+
{504, "Gateway Timeout"},
|
548
|
+
{505, "HTTP Version Not Supported"},
|
549
|
+
{506, "Variant Also Negotiates"},
|
550
|
+
{507, "Insufficient Storage"},
|
551
|
+
{508, "Loop Detected"},
|
552
|
+
{509, "Unassigned"},
|
553
|
+
{510, "Not Extended"},
|
554
|
+
{511, "Network Authentication Required"},
|
555
|
+
{0, 0}};
|
556
|
+
int pos = 0;
|
557
|
+
while (List[pos].i_status) {
|
558
|
+
if (List[pos].i_status == status)
|
559
|
+
return List[pos].s_status;
|
560
|
+
pos++;
|
561
|
+
}
|
562
|
+
return NULL;
|
563
|
+
}
|
564
|
+
|
565
|
+
/** Gets the mime-type string (C string) associated with the file extension.
|
566
|
+
*/
|
567
|
+
const char *http_response_ext2mime(const char *ext) {
|
568
|
+
static struct {
|
569
|
+
char ext[12];
|
570
|
+
char *mime;
|
571
|
+
} List[] = {
|
572
|
+
{"123", "application/vnd.lotus-1-2-3"},
|
573
|
+
{"3dml", "text/vnd.in3d.3dml"},
|
574
|
+
{"3ds", "image/x-3ds"},
|
575
|
+
{"3g2", "video/3gpp2"},
|
576
|
+
{"3gp", "video/3gpp"},
|
577
|
+
{"7z", "application/x-7z-compressed"},
|
578
|
+
{"aab", "application/x-authorware-bin"},
|
579
|
+
{"aac", "audio/x-aac"},
|
580
|
+
{"aam", "application/x-authorware-map"},
|
581
|
+
{"aas", "application/x-authorware-seg"},
|
582
|
+
{"abw", "application/x-abiword"},
|
583
|
+
{"ac", "application/pkix-attr-cert"},
|
584
|
+
{"acc", "application/vnd.americandynamics.acc"},
|
585
|
+
{"ace", "application/x-ace-compressed"},
|
586
|
+
{"acu", "application/vnd.acucobol"},
|
587
|
+
{"acutc", "application/vnd.acucorp"},
|
588
|
+
{"adp", "audio/adpcm"},
|
589
|
+
{"aep", "application/vnd.audiograph"},
|
590
|
+
{"afm", "application/x-font-type1"},
|
591
|
+
{"afp", "application/vnd.ibm.modcap"},
|
592
|
+
{"ahead", "application/vnd.ahead.space"},
|
593
|
+
{"ai", "application/postscript"},
|
594
|
+
{"aif", "audio/x-aiff"},
|
595
|
+
{"aifc", "audio/x-aiff"},
|
596
|
+
{"aiff", "audio/x-aiff"},
|
597
|
+
{"air", "application/vnd.adobe.air-application-installer-package+zip"},
|
598
|
+
{"ait", "application/vnd.dvb.ait"},
|
599
|
+
{"ami", "application/vnd.amiga.ami"},
|
600
|
+
{"apk", "application/vnd.android.package-archive"},
|
601
|
+
{"appcache", "text/cache-manifest"},
|
602
|
+
{"application", "application/x-ms-application"},
|
603
|
+
{
|
604
|
+
"pptx",
|
605
|
+
"application/"
|
606
|
+
"vnd.openxmlformats-officedocument.presentationml.presentation",
|
607
|
+
},
|
608
|
+
{"apr", "application/vnd.lotus-approach"},
|
609
|
+
{"arc", "application/x-freearc"},
|
610
|
+
{"asc", "application/pgp-signature"},
|
611
|
+
{"asf", "video/x-ms-asf"},
|
612
|
+
{"asm", "text/x-asm"},
|
613
|
+
{"aso", "application/vnd.accpac.simply.aso"},
|
614
|
+
{"asx", "video/x-ms-asf"},
|
615
|
+
{"atc", "application/vnd.acucorp"},
|
616
|
+
{"atom", "application/atom+xml"},
|
617
|
+
{"atomcat", "application/atomcat+xml"},
|
618
|
+
{"atomsvc", "application/atomsvc+xml"},
|
619
|
+
{"atx", "application/vnd.antix.game-component"},
|
620
|
+
{"au", "audio/basic"},
|
621
|
+
{"avi", "video/x-msvideo"},
|
622
|
+
{"aw", "application/applixware"},
|
623
|
+
{"azf", "application/vnd.airzip.filesecure.azf"},
|
624
|
+
{"azs", "application/vnd.airzip.filesecure.azs"},
|
625
|
+
{"azw", "application/vnd.amazon.ebook"},
|
626
|
+
{"bat", "application/x-msdownload"},
|
627
|
+
{"bcpio", "application/x-bcpio"},
|
628
|
+
{"bdf", "application/x-font-bdf"},
|
629
|
+
{"bdm", "application/vnd.syncml.dm+wbxml"},
|
630
|
+
{"bed", "application/vnd.realvnc.bed"},
|
631
|
+
{"bh2", "application/vnd.fujitsu.oasysprs"},
|
632
|
+
{"bin", "application/octet-stream"},
|
633
|
+
{"blb", "application/x-blorb"},
|
634
|
+
{"blorb", "application/x-blorb"},
|
635
|
+
{"bmi", "application/vnd.bmi"},
|
636
|
+
{"bmp", "image/bmp"},
|
637
|
+
{"book", "application/vnd.framemaker"},
|
638
|
+
{"box", "application/vnd.previewsystems.box"},
|
639
|
+
{"boz", "application/x-bzip2"},
|
640
|
+
{"bpk", "application/octet-stream"},
|
641
|
+
{"btif", "image/prs.btif"},
|
642
|
+
{"bz", "application/x-bzip"},
|
643
|
+
{"bz2", "application/x-bzip2"},
|
644
|
+
{"c", "text/x-c"},
|
645
|
+
{"c11amc", "application/vnd.cluetrust.cartomobile-config"},
|
646
|
+
{"c11amz", "application/vnd.cluetrust.cartomobile-config-pkg"},
|
647
|
+
{"c4d", "application/vnd.clonk.c4group"},
|
648
|
+
{"c4f", "application/vnd.clonk.c4group"},
|
649
|
+
{"c4g", "application/vnd.clonk.c4group"},
|
650
|
+
{"c4p", "application/vnd.clonk.c4group"},
|
651
|
+
{"c4u", "application/vnd.clonk.c4group"},
|
652
|
+
{"cab", "application/vnd.ms-cab-compressed"},
|
653
|
+
{"caf", "audio/x-caf"},
|
654
|
+
{"cap", "application/vnd.tcpdump.pcap"},
|
655
|
+
{"car", "application/vnd.curl.car"},
|
656
|
+
{"cat", "application/vnd.ms-pki.seccat"},
|
657
|
+
{"cb7", "application/x-cbr"},
|
658
|
+
{"cba", "application/x-cbr"},
|
659
|
+
{"cbr", "application/x-cbr"},
|
660
|
+
{"cbt", "application/x-cbr"},
|
661
|
+
{"cbz", "application/x-cbr"},
|
662
|
+
{"cc", "text/x-c"},
|
663
|
+
{"cct", "application/x-director"},
|
664
|
+
{"ccxml", "application/ccxml+xml"},
|
665
|
+
{"cdbcmsg", "application/vnd.contact.cmsg"},
|
666
|
+
{"cdf", "application/x-netcdf"},
|
667
|
+
{"cdkey", "application/vnd.mediastation.cdkey"},
|
668
|
+
{"cdmia", "application/cdmi-capability"},
|
669
|
+
{"cdmic", "application/cdmi-container"},
|
670
|
+
{"cdmid", "application/cdmi-domain"},
|
671
|
+
{"cdmio", "application/cdmi-object"},
|
672
|
+
{"cdmiq", "application/cdmi-queue"},
|
673
|
+
{"cdx", "chemical/x-cdx"},
|
674
|
+
{"cdxml", "application/vnd.chemdraw+xml"},
|
675
|
+
{"cdy", "application/vnd.cinderella"},
|
676
|
+
{"cer", "application/pkix-cert"},
|
677
|
+
{"cfs", "application/x-cfs-compressed"},
|
678
|
+
{"cgm", "image/cgm"},
|
679
|
+
{"chat", "application/x-chat"},
|
680
|
+
{"chm", "application/vnd.ms-htmlhelp"},
|
681
|
+
{"chrt", "application/vnd.kde.kchart"},
|
682
|
+
{"cif", "chemical/x-cif"},
|
683
|
+
{"cii", "application/vnd.anser-web-certificate-issue-initiation"},
|
684
|
+
{"cil", "application/vnd.ms-artgalry"},
|
685
|
+
{"cla", "application/vnd.claymore"},
|
686
|
+
{"class", "application/java-vm"},
|
687
|
+
{"clkk", "application/vnd.crick.clicker.keyboard"},
|
688
|
+
{"clkp", "application/vnd.crick.clicker.palette"},
|
689
|
+
{"clkt", "application/vnd.crick.clicker.template"},
|
690
|
+
{"clkw", "application/vnd.crick.clicker.wordbank"},
|
691
|
+
{"clkx", "application/vnd.crick.clicker"},
|
692
|
+
{"clp", "application/x-msclip"},
|
693
|
+
{"cmc", "application/vnd.cosmocaller"},
|
694
|
+
{"cmdf", "chemical/x-cmdf"},
|
695
|
+
{"cml", "chemical/x-cml"},
|
696
|
+
{"cmp", "application/vnd.yellowriver-custom-menu"},
|
697
|
+
{"cmx", "image/x-cmx"},
|
698
|
+
{"cod", "application/vnd.rim.cod"},
|
699
|
+
{"com", "application/x-msdownload"},
|
700
|
+
{"conf", "text/plain"},
|
701
|
+
{"cpio", "application/x-cpio"},
|
702
|
+
{"cpp", "text/x-c"},
|
703
|
+
{"cpt", "application/mac-compactpro"},
|
704
|
+
{"crd", "application/x-mscardfile"},
|
705
|
+
{"crl", "application/pkix-crl"},
|
706
|
+
{"crt", "application/x-x509-ca-cert"},
|
707
|
+
{"cryptonote", "application/vnd.rig.cryptonote"},
|
708
|
+
{"csh", "application/x-csh"},
|
709
|
+
{"csml", "chemical/x-csml"},
|
710
|
+
{"csp", "application/vnd.commonspace"},
|
711
|
+
{"css", "text/css"},
|
712
|
+
{"cst", "application/x-director"},
|
713
|
+
{"csv", "text/csv"},
|
714
|
+
{"cu", "application/cu-seeme"},
|
715
|
+
{"curl", "text/vnd.curl"},
|
716
|
+
{"cww", "application/prs.cww"},
|
717
|
+
{"cxt", "application/x-director"},
|
718
|
+
{"cxx", "text/x-c"},
|
719
|
+
{"dae", "model/vnd.collada+xml"},
|
720
|
+
{"daf", "application/vnd.mobius.daf"},
|
721
|
+
{"dart", "application/vnd.dart"},
|
722
|
+
{"dataless", "application/vnd.fdsn.seed"},
|
723
|
+
{"davmount", "application/davmount+xml"},
|
724
|
+
{"dbk", "application/docbook+xml"},
|
725
|
+
{"dcr", "application/x-director"},
|
726
|
+
{"dcurl", "text/vnd.curl.dcurl"},
|
727
|
+
{"dd2", "application/vnd.oma.dd2+xml"},
|
728
|
+
{"ddd", "application/vnd.fujixerox.ddd"},
|
729
|
+
{"deb", "application/x-debian-package"},
|
730
|
+
{"def", "text/plain"},
|
731
|
+
{"deploy", "application/octet-stream"},
|
732
|
+
{"der", "application/x-x509-ca-cert"},
|
733
|
+
{"dfac", "application/vnd.dreamfactory"},
|
734
|
+
{"dgc", "application/x-dgc-compressed"},
|
735
|
+
{"dic", "text/x-c"},
|
736
|
+
{"dir", "application/x-director"},
|
737
|
+
{"dis", "application/vnd.mobius.dis"},
|
738
|
+
{"dist", "application/octet-stream"},
|
739
|
+
{"distz", "application/octet-stream"},
|
740
|
+
{"djv", "image/vnd.djvu"},
|
741
|
+
{"djvu", "image/vnd.djvu"},
|
742
|
+
{"dll", "application/x-msdownload"},
|
743
|
+
{"dmg", "application/x-apple-diskimage"},
|
744
|
+
{"dmp", "application/vnd.tcpdump.pcap"},
|
745
|
+
{"dms", "application/octet-stream"},
|
746
|
+
{"dna", "application/vnd.dna"},
|
747
|
+
{"doc", "application/msword"},
|
748
|
+
{"docm", "application/vnd.ms-word.document.macroenabled.12"},
|
749
|
+
{"docx", "application/"
|
750
|
+
"vnd.openxmlformats-officedocument.wordprocessingml.document"},
|
751
|
+
{"dot", "application/msword"},
|
752
|
+
{"dotm", "application/vnd.ms-word.template.macroenabled.12"},
|
753
|
+
{"dotx", "application/"
|
754
|
+
"vnd.openxmlformats-officedocument.wordprocessingml.template"},
|
755
|
+
{"dp", "application/vnd.osgi.dp"},
|
756
|
+
{"dpg", "application/vnd.dpgraph"},
|
757
|
+
{"dra", "audio/vnd.dra"},
|
758
|
+
{"dsc", "text/prs.lines.tag"},
|
759
|
+
{"dssc", "application/dssc+der"},
|
760
|
+
{"dtb", "application/x-dtbook+xml"},
|
761
|
+
{"dtd", "application/xml-dtd"},
|
762
|
+
{"dts", "audio/vnd.dts"},
|
763
|
+
{"dtshd", "audio/vnd.dts.hd"},
|
764
|
+
{"dump", "application/octet-stream"},
|
765
|
+
{"dvb", "video/vnd.dvb.file"},
|
766
|
+
{"dvi", "application/x-dvi"},
|
767
|
+
{"dwf", "model/vnd.dwf"},
|
768
|
+
{"dwg", "image/vnd.dwg"},
|
769
|
+
{"dxf", "image/vnd.dxf"},
|
770
|
+
{"dxp", "application/vnd.spotfire.dxp"},
|
771
|
+
{"dxr", "application/x-director"},
|
772
|
+
{"ecelp4800", "audio/vnd.nuera.ecelp4800"},
|
773
|
+
{"ecelp7470", "audio/vnd.nuera.ecelp7470"},
|
774
|
+
{"ecelp9600", "audio/vnd.nuera.ecelp9600"},
|
775
|
+
{"ecma", "application/ecmascript"},
|
776
|
+
{"edm", "application/vnd.novadigm.edm"},
|
777
|
+
{"edx", "application/vnd.novadigm.edx"},
|
778
|
+
{"efif", "application/vnd.picsel"},
|
779
|
+
{"ei6", "application/vnd.pg.osasli"},
|
780
|
+
{"elc", "application/octet-stream"},
|
781
|
+
{"emf", "application/x-msmetafile"},
|
782
|
+
{"eml", "message/rfc822"},
|
783
|
+
{"emma", "application/emma+xml"},
|
784
|
+
{"emz", "application/x-msmetafile"},
|
785
|
+
{"eol", "audio/vnd.digital-winds"},
|
786
|
+
{"eot", "application/vnd.ms-fontobject"},
|
787
|
+
{"eps", "application/postscript"},
|
788
|
+
{"epub", "application/epub+zip"},
|
789
|
+
{"es3", "application/vnd.eszigno3+xml"},
|
790
|
+
{"esa", "application/vnd.osgi.subsystem"},
|
791
|
+
{"esf", "application/vnd.epson.esf"},
|
792
|
+
{"et3", "application/vnd.eszigno3+xml"},
|
793
|
+
{"etx", "text/x-setext"},
|
794
|
+
{"eva", "application/x-eva"},
|
795
|
+
{"evy", "application/x-envoy"},
|
796
|
+
{"exe", "application/x-msdownload"},
|
797
|
+
{"exi", "application/exi"},
|
798
|
+
{"ext", "application/vnd.novadigm.ext"},
|
799
|
+
{"ez", "application/andrew-inset"},
|
800
|
+
{"ez2", "application/vnd.ezpix-album"},
|
801
|
+
{"ez3", "application/vnd.ezpix-package"},
|
802
|
+
{"f", "text/x-fortran"},
|
803
|
+
{"f4v", "video/x-f4v"},
|
804
|
+
{"f77", "text/x-fortran"},
|
805
|
+
{"f90", "text/x-fortran"},
|
806
|
+
{"fbs", "image/vnd.fastbidsheet"},
|
807
|
+
{"fcdt", "application/vnd.adobe.formscentral.fcdt"},
|
808
|
+
{"fcs", "application/vnd.isac.fcs"},
|
809
|
+
{"fdf", "application/vnd.fdf"},
|
810
|
+
{"fe_launch", "application/vnd.denovo.fcselayout-link"},
|
811
|
+
{"fg5", "application/vnd.fujitsu.oasysgp"},
|
812
|
+
{"fgd", "application/x-director"},
|
813
|
+
{"fh", "image/x-freehand"},
|
814
|
+
{"fh4", "image/x-freehand"},
|
815
|
+
{"fh5", "image/x-freehand"},
|
816
|
+
{"fh7", "image/x-freehand"},
|
817
|
+
{"fhc", "image/x-freehand"},
|
818
|
+
{"fig", "application/x-xfig"},
|
819
|
+
{"flac", "audio/x-flac"},
|
820
|
+
{"fli", "video/x-fli"},
|
821
|
+
{"flo", "application/vnd.micrografx.flo"},
|
822
|
+
{"flv", "video/x-flv"},
|
823
|
+
{"flw", "application/vnd.kde.kivio"},
|
824
|
+
{"flx", "text/vnd.fmi.flexstor"},
|
825
|
+
{"fly", "text/vnd.fly"},
|
826
|
+
{"fm", "application/vnd.framemaker"},
|
827
|
+
{"fnc", "application/vnd.frogans.fnc"},
|
828
|
+
{"for", "text/x-fortran"},
|
829
|
+
{"fpx", "image/vnd.fpx"},
|
830
|
+
{"frame", "application/vnd.framemaker"},
|
831
|
+
{"fsc", "application/vnd.fsc.weblaunch"},
|
832
|
+
{"fst", "image/vnd.fst"},
|
833
|
+
{"ftc", "application/vnd.fluxtime.clip"},
|
834
|
+
{"fti", "application/vnd.anser-web-funds-transfer-initiation"},
|
835
|
+
{"fvt", "video/vnd.fvt"},
|
836
|
+
{"fxp", "application/vnd.adobe.fxp"},
|
837
|
+
{"fxpl", "application/vnd.adobe.fxp"},
|
838
|
+
{"fzs", "application/vnd.fuzzysheet"},
|
839
|
+
{"g2w", "application/vnd.geoplan"},
|
840
|
+
{"g3", "image/g3fax"},
|
841
|
+
{"g3w", "application/vnd.geospace"},
|
842
|
+
{"gac", "application/vnd.groove-account"},
|
843
|
+
{"gam", "application/x-tads"},
|
844
|
+
{"gbr", "application/rpki-ghostbusters"},
|
845
|
+
{"gca", "application/x-gca-compressed"},
|
846
|
+
{"gdl", "model/vnd.gdl"},
|
847
|
+
{"geo", "application/vnd.dynageo"},
|
848
|
+
{"gex", "application/vnd.geometry-explorer"},
|
849
|
+
{"ggb", "application/vnd.geogebra.file"},
|
850
|
+
{"ggt", "application/vnd.geogebra.tool"},
|
851
|
+
{"ghf", "application/vnd.groove-help"},
|
852
|
+
{"gif", "image/gif"},
|
853
|
+
{"gim", "application/vnd.groove-identity-message"},
|
854
|
+
{"gml", "application/gml+xml"},
|
855
|
+
{"gmx", "application/vnd.gmx"},
|
856
|
+
{"gnumeric", "application/x-gnumeric"},
|
857
|
+
{"gph", "application/vnd.flographit"},
|
858
|
+
{"gpx", "application/gpx+xml"},
|
859
|
+
{"gqf", "application/vnd.grafeq"},
|
860
|
+
{"gqs", "application/vnd.grafeq"},
|
861
|
+
{"gram", "application/srgs"},
|
862
|
+
{"gramps", "application/x-gramps-xml"},
|
863
|
+
{"gre", "application/vnd.geometry-explorer"},
|
864
|
+
{"grv", "application/vnd.groove-injector"},
|
865
|
+
{"grxml", "application/srgs+xml"},
|
866
|
+
{"gsf", "application/x-font-ghostscript"},
|
867
|
+
{"gtar", "application/x-gtar"},
|
868
|
+
{"gtm", "application/vnd.groove-tool-message"},
|
869
|
+
{"gtw", "model/vnd.gtw"},
|
870
|
+
{"gv", "text/vnd.graphviz"},
|
871
|
+
{"gxf", "application/gxf"},
|
872
|
+
{"gxt", "application/vnd.geonext"},
|
873
|
+
{"h", "text/x-c"},
|
874
|
+
{"h261", "video/h261"},
|
875
|
+
{"h263", "video/h263"},
|
876
|
+
{"h264", "video/h264"},
|
877
|
+
{"hal", "application/vnd.hal+xml"},
|
878
|
+
{"hbci", "application/vnd.hbci"},
|
879
|
+
{"hdf", "application/x-hdf"},
|
880
|
+
{"hh", "text/x-c"},
|
881
|
+
{"hlp", "application/winhlp"},
|
882
|
+
{"hpgl", "application/vnd.hp-hpgl"},
|
883
|
+
{"hpid", "application/vnd.hp-hpid"},
|
884
|
+
{"hps", "application/vnd.hp-hps"},
|
885
|
+
{"hqx", "application/mac-binhex40"},
|
886
|
+
{"htke", "application/vnd.kenameaapp"},
|
887
|
+
{"htm", "text/html"},
|
888
|
+
{"html", "text/html"},
|
889
|
+
{"hvd", "application/vnd.yamaha.hv-dic"},
|
890
|
+
{"hvp", "application/vnd.yamaha.hv-voice"},
|
891
|
+
{"hvs", "application/vnd.yamaha.hv-script"},
|
892
|
+
{"i2g", "application/vnd.intergeo"},
|
893
|
+
{"icc", "application/vnd.iccprofile"},
|
894
|
+
{"ice", "x-conference/x-cooltalk"},
|
895
|
+
{"icm", "application/vnd.iccprofile"},
|
896
|
+
{"ico", "image/x-icon"},
|
897
|
+
{"ics", "text/calendar"},
|
898
|
+
{"ief", "image/ief"},
|
899
|
+
{"ifb", "text/calendar"},
|
900
|
+
{"ifm", "application/vnd.shana.informed.formdata"},
|
901
|
+
{"iges", "model/iges"},
|
902
|
+
{"igl", "application/vnd.igloader"},
|
903
|
+
{"igm", "application/vnd.insors.igm"},
|
904
|
+
{"igs", "model/iges"},
|
905
|
+
{"igx", "application/vnd.micrografx.igx"},
|
906
|
+
{"iif", "application/vnd.shana.informed.interchange"},
|
907
|
+
{"imp", "application/vnd.accpac.simply.imp"},
|
908
|
+
{"ims", "application/vnd.ms-ims"},
|
909
|
+
{"in", "text/plain"},
|
910
|
+
{"ink", "application/inkml+xml"},
|
911
|
+
{"inkml", "application/inkml+xml"},
|
912
|
+
{"install", "application/x-install-instructions"},
|
913
|
+
{"iota", "application/vnd.astraea-software.iota"},
|
914
|
+
{"ipfix", "application/ipfix"},
|
915
|
+
{"ipk", "application/vnd.shana.informed.package"},
|
916
|
+
{"irm", "application/vnd.ibm.rights-management"},
|
917
|
+
{"irp", "application/vnd.irepository.package+xml"},
|
918
|
+
{"iso", "application/x-iso9660-image"},
|
919
|
+
{"itp", "application/vnd.shana.informed.formtemplate"},
|
920
|
+
{"ivp", "application/vnd.immervision-ivp"},
|
921
|
+
{"ivu", "application/vnd.immervision-ivu"},
|
922
|
+
{"jad", "text/vnd.sun.j2me.app-descriptor"},
|
923
|
+
{"jam", "application/vnd.jam"},
|
924
|
+
{"jar", "application/java-archive"},
|
925
|
+
{"java", "text/x-java-source"},
|
926
|
+
{"jisp", "application/vnd.jisp"},
|
927
|
+
{"jlt", "application/vnd.hp-jlyt"},
|
928
|
+
{"jnlp", "application/x-java-jnlp-file"},
|
929
|
+
{"joda", "application/vnd.joost.joda-archive"},
|
930
|
+
{"jpe", "image/jpeg"},
|
931
|
+
{"jpeg", "image/jpeg"},
|
932
|
+
{"jpg", "image/jpeg"},
|
933
|
+
{"jpgm", "video/jpm"},
|
934
|
+
{"jpgv", "video/jpeg"},
|
935
|
+
{"jpm", "video/jpm"},
|
936
|
+
{"js", "application/javascript"},
|
937
|
+
{"json", "application/json"},
|
938
|
+
{"jsonml", "application/jsonml+json"},
|
939
|
+
{"kar", "audio/midi"},
|
940
|
+
{"karbon", "application/vnd.kde.karbon"},
|
941
|
+
{"kfo", "application/vnd.kde.kformula"},
|
942
|
+
{"kia", "application/vnd.kidspiration"},
|
943
|
+
{"kml", "application/vnd.google-earth.kml+xml"},
|
944
|
+
{"kmz", "application/vnd.google-earth.kmz"},
|
945
|
+
{"kne", "application/vnd.kinar"},
|
946
|
+
{"knp", "application/vnd.kinar"},
|
947
|
+
{"kon", "application/vnd.kde.kontour"},
|
948
|
+
{"kpr", "application/vnd.kde.kpresenter"},
|
949
|
+
{"kpt", "application/vnd.kde.kpresenter"},
|
950
|
+
{"kpxx", "application/vnd.ds-keypoint"},
|
951
|
+
{"ksp", "application/vnd.kde.kspread"},
|
952
|
+
{"ktr", "application/vnd.kahootz"},
|
953
|
+
{"ktx", "image/ktx"},
|
954
|
+
{"ktz", "application/vnd.kahootz"},
|
955
|
+
{"kwd", "application/vnd.kde.kword"},
|
956
|
+
{"kwt", "application/vnd.kde.kword"},
|
957
|
+
{"lasxml", "application/vnd.las.las+xml"},
|
958
|
+
{"latex", "application/x-latex"},
|
959
|
+
{"lbd", "application/vnd.llamagraphics.life-balance.desktop"},
|
960
|
+
{"lbe", "application/vnd.llamagraphics.life-balance.exchange+xml"},
|
961
|
+
{"les", "application/vnd.hhe.lesson-player"},
|
962
|
+
{"lha", "application/x-lzh-compressed"},
|
963
|
+
{"link66", "application/vnd.route66.link66+xml"},
|
964
|
+
{"list", "text/plain"},
|
965
|
+
{"list3820", "application/vnd.ibm.modcap"},
|
966
|
+
{"listafp", "application/vnd.ibm.modcap"},
|
967
|
+
{"lnk", "application/x-ms-shortcut"},
|
968
|
+
{"log", "text/plain"},
|
969
|
+
{"lostxml", "application/lost+xml"},
|
970
|
+
{"lrf", "application/octet-stream"},
|
971
|
+
{"lrm", "application/vnd.ms-lrm"},
|
972
|
+
{"ltf", "application/vnd.frogans.ltf"},
|
973
|
+
{"lvp", "audio/vnd.lucent.voice"},
|
974
|
+
{"lwp", "application/vnd.lotus-wordpro"},
|
975
|
+
{"lzh", "application/x-lzh-compressed"},
|
976
|
+
{"m13", "application/x-msmediaview"},
|
977
|
+
{"m14", "application/x-msmediaview"},
|
978
|
+
{"m1v", "video/mpeg"},
|
979
|
+
{"m21", "application/mp21"},
|
980
|
+
{"m2a", "audio/mpeg"},
|
981
|
+
{"m2v", "video/mpeg"},
|
982
|
+
{"m3a", "audio/mpeg"},
|
983
|
+
{"m3u", "audio/x-mpegurl"},
|
984
|
+
{"m3u8", "application/vnd.apple.mpegurl"},
|
985
|
+
{"m4a", "audio/mp4"},
|
986
|
+
{"m4u", "video/vnd.mpegurl"},
|
987
|
+
{"m4v", "video/x-m4v"},
|
988
|
+
{"ma", "application/mathematica"},
|
989
|
+
{"mads", "application/mads+xml"},
|
990
|
+
{"mag", "application/vnd.ecowin.chart"},
|
991
|
+
{"maker", "application/vnd.framemaker"},
|
992
|
+
{"man", "text/troff"},
|
993
|
+
{"mar", "application/octet-stream"},
|
994
|
+
{"mathml", "application/mathml+xml"},
|
995
|
+
{"mb", "application/mathematica"},
|
996
|
+
{"mbk", "application/vnd.mobius.mbk"},
|
997
|
+
{"mbox", "application/mbox"},
|
998
|
+
{"mc1", "application/vnd.medcalcdata"},
|
999
|
+
{"mcd", "application/vnd.mcd"},
|
1000
|
+
{"mcurl", "text/vnd.curl.mcurl"},
|
1001
|
+
{"mdb", "application/x-msaccess"},
|
1002
|
+
{"mdi", "image/vnd.ms-modi"},
|
1003
|
+
{"me", "text/troff"},
|
1004
|
+
{"mesh", "model/mesh"},
|
1005
|
+
{"meta4", "application/metalink4+xml"},
|
1006
|
+
{"metalink", "application/metalink+xml"},
|
1007
|
+
{"mets", "application/mets+xml"},
|
1008
|
+
{"mfm", "application/vnd.mfmp"},
|
1009
|
+
{"mft", "application/rpki-manifest"},
|
1010
|
+
{"mgp", "application/vnd.osgeo.mapguide.package"},
|
1011
|
+
{"mgz", "application/vnd.proteus.magazine"},
|
1012
|
+
{"mid", "audio/midi"},
|
1013
|
+
{"midi", "audio/midi"},
|
1014
|
+
{"mie", "application/x-mie"},
|
1015
|
+
{"mif", "application/vnd.mif"},
|
1016
|
+
{"mime", "message/rfc822"},
|
1017
|
+
{"mj2", "video/mj2"},
|
1018
|
+
{"mjp2", "video/mj2"},
|
1019
|
+
{"mk3d", "video/x-matroska"},
|
1020
|
+
{"mka", "audio/x-matroska"},
|
1021
|
+
{"mks", "video/x-matroska"},
|
1022
|
+
{"mkv", "video/x-matroska"},
|
1023
|
+
{"mlp", "application/vnd.dolby.mlp"},
|
1024
|
+
{"mmd", "application/vnd.chipnuts.karaoke-mmd"},
|
1025
|
+
{"mmf", "application/vnd.smaf"},
|
1026
|
+
{"mmr", "image/vnd.fujixerox.edmics-mmr"},
|
1027
|
+
{"mng", "video/x-mng"},
|
1028
|
+
{"mny", "application/x-msmoney"},
|
1029
|
+
{"mobi", "application/x-mobipocket-ebook"},
|
1030
|
+
{"mods", "application/mods+xml"},
|
1031
|
+
{"mov", "video/quicktime"},
|
1032
|
+
{"movie", "video/x-sgi-movie"},
|
1033
|
+
{"mp2", "audio/mpeg"},
|
1034
|
+
{"mp21", "application/mp21"},
|
1035
|
+
{"mp2a", "audio/mpeg"},
|
1036
|
+
{"mp3", "audio/mpeg"},
|
1037
|
+
{"mp4", "video/mp4"},
|
1038
|
+
{"mp4a", "audio/mp4"},
|
1039
|
+
{"mp4s", "application/mp4"},
|
1040
|
+
{"mp4v", "video/mp4"},
|
1041
|
+
{"mpc", "application/vnd.mophun.certificate"},
|
1042
|
+
{"mpe", "video/mpeg"},
|
1043
|
+
{"mpeg", "video/mpeg"},
|
1044
|
+
{"mpg", "video/mpeg"},
|
1045
|
+
{"mpg4", "video/mp4"},
|
1046
|
+
{"mpga", "audio/mpeg"},
|
1047
|
+
{"mpkg", "application/vnd.apple.installer+xml"},
|
1048
|
+
{"mpm", "application/vnd.blueice.multipass"},
|
1049
|
+
{"mpn", "application/vnd.mophun.application"},
|
1050
|
+
{"mpp", "application/vnd.ms-project"},
|
1051
|
+
{"mpt", "application/vnd.ms-project"},
|
1052
|
+
{"mpy", "application/vnd.ibm.minipay"},
|
1053
|
+
{"mqy", "application/vnd.mobius.mqy"},
|
1054
|
+
{"mrc", "application/marc"},
|
1055
|
+
{"mrcx", "application/marcxml+xml"},
|
1056
|
+
{"ms", "text/troff"},
|
1057
|
+
{"mscml", "application/mediaservercontrol+xml"},
|
1058
|
+
{"mseed", "application/vnd.fdsn.mseed"},
|
1059
|
+
{"mseq", "application/vnd.mseq"},
|
1060
|
+
{"msf", "application/vnd.epson.msf"},
|
1061
|
+
{"msh", "model/mesh"},
|
1062
|
+
{"msi", "application/x-msdownload"},
|
1063
|
+
{"msl", "application/vnd.mobius.msl"},
|
1064
|
+
{"msty", "application/vnd.muvee.style"},
|
1065
|
+
{"mts", "model/vnd.mts"},
|
1066
|
+
{"mus", "application/vnd.musician"},
|
1067
|
+
{"musicxml", "application/vnd.recordare.musicxml+xml"},
|
1068
|
+
{"mvb", "application/x-msmediaview"},
|
1069
|
+
{"mwf", "application/vnd.mfer"},
|
1070
|
+
{"mxf", "application/mxf"},
|
1071
|
+
{"mxl", "application/vnd.recordare.musicxml"},
|
1072
|
+
{"mxml", "application/xv+xml"},
|
1073
|
+
{"mxs", "application/vnd.triscape.mxs"},
|
1074
|
+
{"mxu", "video/vnd.mpegurl"},
|
1075
|
+
{"n-gage", "application/vnd.nokia.n-gage.symbian.install"},
|
1076
|
+
{"n3", "text/n3"},
|
1077
|
+
{"nb", "application/mathematica"},
|
1078
|
+
{"nbp", "application/vnd.wolfram.player"},
|
1079
|
+
{"nc", "application/x-netcdf"},
|
1080
|
+
{"ncx", "application/x-dtbncx+xml"},
|
1081
|
+
{"nfo", "text/x-nfo"},
|
1082
|
+
{"ngdat", "application/vnd.nokia.n-gage.data"},
|
1083
|
+
{"nitf", "application/vnd.nitf"},
|
1084
|
+
{"nlu", "application/vnd.neurolanguage.nlu"},
|
1085
|
+
{"nml", "application/vnd.enliven"},
|
1086
|
+
{"nnd", "application/vnd.noblenet-directory"},
|
1087
|
+
{"nns", "application/vnd.noblenet-sealer"},
|
1088
|
+
{"nnw", "application/vnd.noblenet-web"},
|
1089
|
+
{"npx", "image/vnd.net-fpx"},
|
1090
|
+
{"nsc", "application/x-conference"},
|
1091
|
+
{"nsf", "application/vnd.lotus-notes"},
|
1092
|
+
{"ntf", "application/vnd.nitf"},
|
1093
|
+
{"nzb", "application/x-nzb"},
|
1094
|
+
{"oa2", "application/vnd.fujitsu.oasys2"},
|
1095
|
+
{"oa3", "application/vnd.fujitsu.oasys3"},
|
1096
|
+
{"oas", "application/vnd.fujitsu.oasys"},
|
1097
|
+
{"obd", "application/x-msbinder"},
|
1098
|
+
{"obj", "application/x-tgif"},
|
1099
|
+
{"oda", "application/oda"},
|
1100
|
+
{"odb", "application/vnd.oasis.opendocument.database"},
|
1101
|
+
{"odc", "application/vnd.oasis.opendocument.chart"},
|
1102
|
+
{"odf", "application/vnd.oasis.opendocument.formula"},
|
1103
|
+
{"odft", "application/vnd.oasis.opendocument.formula-template"},
|
1104
|
+
{"odg", "application/vnd.oasis.opendocument.graphics"},
|
1105
|
+
{"odi", "application/vnd.oasis.opendocument.image"},
|
1106
|
+
{"odm", "application/vnd.oasis.opendocument.text-master"},
|
1107
|
+
{"odp", "application/vnd.oasis.opendocument.presentation"},
|
1108
|
+
{"ods", "application/vnd.oasis.opendocument.spreadsheet"},
|
1109
|
+
{"odt", "application/vnd.oasis.opendocument.text"},
|
1110
|
+
{"oga", "audio/ogg"},
|
1111
|
+
{"ogg", "audio/ogg"},
|
1112
|
+
{"ogv", "video/ogg"},
|
1113
|
+
{"ogx", "application/ogg"},
|
1114
|
+
{"omdoc", "application/omdoc+xml"},
|
1115
|
+
{"onepkg", "application/onenote"},
|
1116
|
+
{"onetmp", "application/onenote"},
|
1117
|
+
{"onetoc", "application/onenote"},
|
1118
|
+
{"onetoc2", "application/onenote"},
|
1119
|
+
{"opf", "application/oebps-package+xml"},
|
1120
|
+
{"opml", "text/x-opml"},
|
1121
|
+
{"oprc", "application/vnd.palm"},
|
1122
|
+
{"org", "application/vnd.lotus-organizer"},
|
1123
|
+
{"osf", "application/vnd.yamaha.openscoreformat"},
|
1124
|
+
{"osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml"},
|
1125
|
+
{"otc", "application/vnd.oasis.opendocument.chart-template"},
|
1126
|
+
{"otf", "application/x-font-otf"},
|
1127
|
+
{"otg", "application/vnd.oasis.opendocument.graphics-template"},
|
1128
|
+
{"oth", "application/vnd.oasis.opendocument.text-web"},
|
1129
|
+
{"oti", "application/vnd.oasis.opendocument.image-template"},
|
1130
|
+
{"otp", "application/vnd.oasis.opendocument.presentation-template"},
|
1131
|
+
{"ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
|
1132
|
+
{"ott", "application/vnd.oasis.opendocument.text-template"},
|
1133
|
+
{"oxps", "application/oxps"},
|
1134
|
+
{"oxt", "application/vnd.openofficeorg.extension"},
|
1135
|
+
{"p", "text/x-pascal"},
|
1136
|
+
{"p10", "application/pkcs10"},
|
1137
|
+
{"p12", "application/x-pkcs12"},
|
1138
|
+
{"p7b", "application/x-pkcs7-certificates"},
|
1139
|
+
{"p7c", "application/pkcs7-mime"},
|
1140
|
+
{"p7m", "application/pkcs7-mime"},
|
1141
|
+
{"p7r", "application/x-pkcs7-certreqresp"},
|
1142
|
+
{"p7s", "application/pkcs7-signature"},
|
1143
|
+
{"p8", "application/pkcs8"},
|
1144
|
+
{"pas", "text/x-pascal"},
|
1145
|
+
{"paw", "application/vnd.pawaafile"},
|
1146
|
+
{"pbd", "application/vnd.powerbuilder6"},
|
1147
|
+
{"pbm", "image/x-portable-bitmap"},
|
1148
|
+
{"pcap", "application/vnd.tcpdump.pcap"},
|
1149
|
+
{"pcf", "application/x-font-pcf"},
|
1150
|
+
{"pcl", "application/vnd.hp-pcl"},
|
1151
|
+
{"pclxl", "application/vnd.hp-pclxl"},
|
1152
|
+
{"pct", "image/x-pict"},
|
1153
|
+
{"pcurl", "application/vnd.curl.pcurl"},
|
1154
|
+
{"pcx", "image/x-pcx"},
|
1155
|
+
{"pdb", "application/vnd.palm"},
|
1156
|
+
{"pdf", "application/pdf"},
|
1157
|
+
{"pfa", "application/x-font-type1"},
|
1158
|
+
{"pfb", "application/x-font-type1"},
|
1159
|
+
{"pfm", "application/x-font-type1"},
|
1160
|
+
{"pfr", "application/font-tdpfr"},
|
1161
|
+
{"pfx", "application/x-pkcs12"},
|
1162
|
+
{"pgm", "image/x-portable-graymap"},
|
1163
|
+
{"pgn", "application/x-chess-pgn"},
|
1164
|
+
{"pgp", "application/pgp-encrypted"},
|
1165
|
+
{"pic", "image/x-pict"},
|
1166
|
+
{"pkg", "application/octet-stream"},
|
1167
|
+
{"pki", "application/pkixcmp"},
|
1168
|
+
{"pkipath", "application/pkix-pkipath"},
|
1169
|
+
{"plb", "application/vnd.3gpp.pic-bw-large"},
|
1170
|
+
{"plc", "application/vnd.mobius.plc"},
|
1171
|
+
{"plf", "application/vnd.pocketlearn"},
|
1172
|
+
{"pls", "application/pls+xml"},
|
1173
|
+
{"pml", "application/vnd.ctc-posml"},
|
1174
|
+
{"png", "image/png"},
|
1175
|
+
{"pnm", "image/x-portable-anymap"},
|
1176
|
+
{"portpkg", "application/vnd.macports.portpkg"},
|
1177
|
+
{"pot", "application/vnd.ms-powerpoint"},
|
1178
|
+
{"potm", "application/vnd.ms-powerpoint.template.macroenabled.12"},
|
1179
|
+
{"potx", "application/"
|
1180
|
+
"vnd.openxmlformats-officedocument.presentationml.template"},
|
1181
|
+
{"ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12"},
|
1182
|
+
{"ppd", "application/vnd.cups-ppd"},
|
1183
|
+
{"ppm", "image/x-portable-pixmap"},
|
1184
|
+
{"pps", "application/vnd.ms-powerpoint"},
|
1185
|
+
{"ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12"},
|
1186
|
+
{"ppsx", "application/"
|
1187
|
+
"vnd.openxmlformats-officedocument.presentationml.slideshow"},
|
1188
|
+
{"ppt", "application/vnd.ms-powerpoint"},
|
1189
|
+
{"pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12"},
|
1190
|
+
{"pqa", "application/vnd.palm"},
|
1191
|
+
{"prc", "application/x-mobipocket-ebook"},
|
1192
|
+
{"pre", "application/vnd.lotus-freelance"},
|
1193
|
+
{"prf", "application/pics-rules"},
|
1194
|
+
{"ps", "application/postscript"},
|
1195
|
+
{"psb", "application/vnd.3gpp.pic-bw-small"},
|
1196
|
+
{"psd", "image/vnd.adobe.photoshop"},
|
1197
|
+
{"psf", "application/x-font-linux-psf"},
|
1198
|
+
{"pskcxml", "application/pskc+xml"},
|
1199
|
+
{"ptid", "application/vnd.pvi.ptid1"},
|
1200
|
+
{"pub", "application/x-mspublisher"},
|
1201
|
+
{"pvb", "application/vnd.3gpp.pic-bw-var"},
|
1202
|
+
{"pwn", "application/vnd.3m.post-it-notes"},
|
1203
|
+
{"pya", "audio/vnd.ms-playready.media.pya"},
|
1204
|
+
{"pyv", "video/vnd.ms-playready.media.pyv"},
|
1205
|
+
{"qam", "application/vnd.epson.quickanime"},
|
1206
|
+
{"qbo", "application/vnd.intu.qbo"},
|
1207
|
+
{"qfx", "application/vnd.intu.qfx"},
|
1208
|
+
{"qps", "application/vnd.publishare-delta-tree"},
|
1209
|
+
{"qt", "video/quicktime"},
|
1210
|
+
{"qwd", "application/vnd.quark.quarkxpress"},
|
1211
|
+
{"qwt", "application/vnd.quark.quarkxpress"},
|
1212
|
+
{"qxb", "application/vnd.quark.quarkxpress"},
|
1213
|
+
{"qxd", "application/vnd.quark.quarkxpress"},
|
1214
|
+
{"qxl", "application/vnd.quark.quarkxpress"},
|
1215
|
+
{"qxt", "application/vnd.quark.quarkxpress"},
|
1216
|
+
{"ra", "audio/x-pn-realaudio"},
|
1217
|
+
{"ram", "audio/x-pn-realaudio"},
|
1218
|
+
{"rar", "application/x-rar-compressed"},
|
1219
|
+
{"ras", "image/x-cmu-raster"},
|
1220
|
+
{"rcprofile", "application/vnd.ipunplugged.rcprofile"},
|
1221
|
+
{"rdf", "application/rdf+xml"},
|
1222
|
+
{"rdz", "application/vnd.data-vision.rdz"},
|
1223
|
+
{"rep", "application/vnd.businessobjects"},
|
1224
|
+
{"res", "application/x-dtbresource+xml"},
|
1225
|
+
{"rgb", "image/x-rgb"},
|
1226
|
+
{"rif", "application/reginfo+xml"},
|
1227
|
+
{"rip", "audio/vnd.rip"},
|
1228
|
+
{"ris", "application/x-research-info-systems"},
|
1229
|
+
{"rl", "application/resource-lists+xml"},
|
1230
|
+
{"rlc", "image/vnd.fujixerox.edmics-rlc"},
|
1231
|
+
{"rld", "application/resource-lists-diff+xml"},
|
1232
|
+
{"rm", "application/vnd.rn-realmedia"},
|
1233
|
+
{"rmi", "audio/midi"},
|
1234
|
+
{"rmp", "audio/x-pn-realaudio-plugin"},
|
1235
|
+
{"rms", "application/vnd.jcp.javame.midlet-rms"},
|
1236
|
+
{"rmvb", "application/vnd.rn-realmedia-vbr"},
|
1237
|
+
{"rnc", "application/relax-ng-compact-syntax"},
|
1238
|
+
{"roa", "application/rpki-roa"},
|
1239
|
+
{"roff", "text/troff"},
|
1240
|
+
{"rp9", "application/vnd.cloanto.rp9"},
|
1241
|
+
{"rpss", "application/vnd.nokia.radio-presets"},
|
1242
|
+
{"rpst", "application/vnd.nokia.radio-preset"},
|
1243
|
+
{"rq", "application/sparql-query"},
|
1244
|
+
{"rs", "application/rls-services+xml"},
|
1245
|
+
{"rsd", "application/rsd+xml"},
|
1246
|
+
{"rss", "application/rss+xml"},
|
1247
|
+
{"rtf", "application/rtf"},
|
1248
|
+
{"rtx", "text/richtext"},
|
1249
|
+
{"s", "text/x-asm"},
|
1250
|
+
{"s3m", "audio/s3m"},
|
1251
|
+
{"saf", "application/vnd.yamaha.smaf-audio"},
|
1252
|
+
{"sbml", "application/sbml+xml"},
|
1253
|
+
{"sc", "application/vnd.ibm.secure-container"},
|
1254
|
+
{"scd", "application/x-msschedule"},
|
1255
|
+
{"scm", "application/vnd.lotus-screencam"},
|
1256
|
+
{"scq", "application/scvp-cv-request"},
|
1257
|
+
{"scs", "application/scvp-cv-response"},
|
1258
|
+
{"scurl", "text/vnd.curl.scurl"},
|
1259
|
+
{"sda", "application/vnd.stardivision.draw"},
|
1260
|
+
{"sdc", "application/vnd.stardivision.calc"},
|
1261
|
+
{"sdd", "application/vnd.stardivision.impress"},
|
1262
|
+
{"sdkd", "application/vnd.solent.sdkm+xml"},
|
1263
|
+
{"sdkm", "application/vnd.solent.sdkm+xml"},
|
1264
|
+
{"sdp", "application/sdp"},
|
1265
|
+
{"sdw", "application/vnd.stardivision.writer"},
|
1266
|
+
{"see", "application/vnd.seemail"},
|
1267
|
+
{"seed", "application/vnd.fdsn.seed"},
|
1268
|
+
{"sema", "application/vnd.sema"},
|
1269
|
+
{"semd", "application/vnd.semd"},
|
1270
|
+
{"semf", "application/vnd.semf"},
|
1271
|
+
{"ser", "application/java-serialized-object"},
|
1272
|
+
{"setpay", "application/set-payment-initiation"},
|
1273
|
+
{"setreg", "application/set-registration-initiation"},
|
1274
|
+
{"sfd-hdstx", "application/vnd.hydrostatix.sof-data"},
|
1275
|
+
{"sfs", "application/vnd.spotfire.sfs"},
|
1276
|
+
{"sfv", "text/x-sfv"},
|
1277
|
+
{"sgi", "image/sgi"},
|
1278
|
+
{"sgl", "application/vnd.stardivision.writer-global"},
|
1279
|
+
{"sgm", "text/sgml"},
|
1280
|
+
{"sgml", "text/sgml"},
|
1281
|
+
{"sh", "application/x-sh"},
|
1282
|
+
{"shar", "application/x-shar"},
|
1283
|
+
{"shf", "application/shf+xml"},
|
1284
|
+
{"sid", "image/x-mrsid-image"},
|
1285
|
+
{"sig", "application/pgp-signature"},
|
1286
|
+
{"sil", "audio/silk"},
|
1287
|
+
{"silo", "model/mesh"},
|
1288
|
+
{"sis", "application/vnd.symbian.install"},
|
1289
|
+
{"sisx", "application/vnd.symbian.install"},
|
1290
|
+
{"sit", "application/x-stuffit"},
|
1291
|
+
{"sitx", "application/x-stuffitx"},
|
1292
|
+
{"skd", "application/vnd.koan"},
|
1293
|
+
{"skm", "application/vnd.koan"},
|
1294
|
+
{"skp", "application/vnd.koan"},
|
1295
|
+
{"skt", "application/vnd.koan"},
|
1296
|
+
{"sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12"},
|
1297
|
+
{"sldx",
|
1298
|
+
"application/vnd.openxmlformats-officedocument.presentationml.slide"},
|
1299
|
+
{"slt", "application/vnd.epson.salt"},
|
1300
|
+
{"sm", "application/vnd.stepmania.stepchart"},
|
1301
|
+
{"smf", "application/vnd.stardivision.math"},
|
1302
|
+
{"smi", "application/smil+xml"},
|
1303
|
+
{"smil", "application/smil+xml"},
|
1304
|
+
{"smv", "video/x-smv"},
|
1305
|
+
{"smzip", "application/vnd.stepmania.package"},
|
1306
|
+
{"snd", "audio/basic"},
|
1307
|
+
{"snf", "application/x-font-snf"},
|
1308
|
+
{"so", "application/octet-stream"},
|
1309
|
+
{"spc", "application/x-pkcs7-certificates"},
|
1310
|
+
{"spf", "application/vnd.yamaha.smaf-phrase"},
|
1311
|
+
{"spl", "application/x-futuresplash"},
|
1312
|
+
{"spot", "text/vnd.in3d.spot"},
|
1313
|
+
{"spp", "application/scvp-vp-response"},
|
1314
|
+
{"spq", "application/scvp-vp-request"},
|
1315
|
+
{"spx", "audio/ogg"},
|
1316
|
+
{"sql", "application/x-sql"},
|
1317
|
+
{"src", "application/x-wais-source"},
|
1318
|
+
{"srt", "application/x-subrip"},
|
1319
|
+
{"sru", "application/sru+xml"},
|
1320
|
+
{"srx", "application/sparql-results+xml"},
|
1321
|
+
{"ssdl", "application/ssdl+xml"},
|
1322
|
+
{"sse", "application/vnd.kodak-descriptor"},
|
1323
|
+
{"ssf", "application/vnd.epson.ssf"},
|
1324
|
+
{"ssml", "application/ssml+xml"},
|
1325
|
+
{"st", "application/vnd.sailingtracker.track"},
|
1326
|
+
{"stc", "application/vnd.sun.xml.calc.template"},
|
1327
|
+
{"std", "application/vnd.sun.xml.draw.template"},
|
1328
|
+
{"stf", "application/vnd.wt.stf"},
|
1329
|
+
{"sti", "application/vnd.sun.xml.impress.template"},
|
1330
|
+
{"stk", "application/hyperstudio"},
|
1331
|
+
{"stl", "application/vnd.ms-pki.stl"},
|
1332
|
+
{"str", "application/vnd.pg.format"},
|
1333
|
+
{"stw", "application/vnd.sun.xml.writer.template"},
|
1334
|
+
{"sub", "image/vnd.dvb.subtitle"},
|
1335
|
+
{"sub", "text/vnd.dvb.subtitle"},
|
1336
|
+
{"sus", "application/vnd.sus-calendar"},
|
1337
|
+
{"susp", "application/vnd.sus-calendar"},
|
1338
|
+
{"sv4cpio", "application/x-sv4cpio"},
|
1339
|
+
{"sv4crc", "application/x-sv4crc"},
|
1340
|
+
{"svc", "application/vnd.dvb.service"},
|
1341
|
+
{"svd", "application/vnd.svd"},
|
1342
|
+
{"svg", "image/svg+xml"},
|
1343
|
+
{"svgz", "image/svg+xml"},
|
1344
|
+
{"swa", "application/x-director"},
|
1345
|
+
{"swf", "application/x-shockwave-flash"},
|
1346
|
+
{"swi", "application/vnd.aristanetworks.swi"},
|
1347
|
+
{"sxc", "application/vnd.sun.xml.calc"},
|
1348
|
+
{"sxd", "application/vnd.sun.xml.draw"},
|
1349
|
+
{"sxg", "application/vnd.sun.xml.writer.global"},
|
1350
|
+
{"sxi", "application/vnd.sun.xml.impress"},
|
1351
|
+
{"sxm", "application/vnd.sun.xml.math"},
|
1352
|
+
{"sxw", "application/vnd.sun.xml.writer"},
|
1353
|
+
{"t", "text/troff"},
|
1354
|
+
{"t3", "application/x-t3vm-image"},
|
1355
|
+
{"taglet", "application/vnd.mynfc"},
|
1356
|
+
{"tao", "application/vnd.tao.intent-module-archive"},
|
1357
|
+
{"tar", "application/x-tar"},
|
1358
|
+
{"tcap", "application/vnd.3gpp2.tcap"},
|
1359
|
+
{"tcl", "application/x-tcl"},
|
1360
|
+
{"teacher", "application/vnd.smart.teacher"},
|
1361
|
+
{"tei", "application/tei+xml"},
|
1362
|
+
{"teicorpus", "application/tei+xml"},
|
1363
|
+
{"tex", "application/x-tex"},
|
1364
|
+
{"texi", "application/x-texinfo"},
|
1365
|
+
{"texinfo", "application/x-texinfo"},
|
1366
|
+
{"text", "text/plain"},
|
1367
|
+
{"tfi", "application/thraud+xml"},
|
1368
|
+
{"tfm", "application/x-tex-tfm"},
|
1369
|
+
{"tga", "image/x-tga"},
|
1370
|
+
{"thmx", "application/vnd.ms-officetheme"},
|
1371
|
+
{"tif", "image/tiff"},
|
1372
|
+
{"tiff", "image/tiff"},
|
1373
|
+
{"tmo", "application/vnd.tmobile-livetv"},
|
1374
|
+
{"torrent", "application/x-bittorrent"},
|
1375
|
+
{"tpl", "application/vnd.groove-tool-template"},
|
1376
|
+
{"tpt", "application/vnd.trid.tpt"},
|
1377
|
+
{"tr", "text/troff"},
|
1378
|
+
{"tra", "application/vnd.trueapp"},
|
1379
|
+
{"trm", "application/x-msterminal"},
|
1380
|
+
{"tsd", "application/timestamped-data"},
|
1381
|
+
{"tsv", "text/tab-separated-values"},
|
1382
|
+
{"ttc", "application/x-font-ttf"},
|
1383
|
+
{"ttf", "application/x-font-ttf"},
|
1384
|
+
{"ttl", "text/turtle"},
|
1385
|
+
{"twd", "application/vnd.simtech-mindmapper"},
|
1386
|
+
{"twds", "application/vnd.simtech-mindmapper"},
|
1387
|
+
{"txd", "application/vnd.genomatix.tuxedo"},
|
1388
|
+
{"txf", "application/vnd.mobius.txf"},
|
1389
|
+
{"txt", "text/plain"},
|
1390
|
+
{"u32", "application/x-authorware-bin"},
|
1391
|
+
{"udeb", "application/x-debian-package"},
|
1392
|
+
{"ufd", "application/vnd.ufdl"},
|
1393
|
+
{"ufdl", "application/vnd.ufdl"},
|
1394
|
+
{"ulx", "application/x-glulx"},
|
1395
|
+
{"umj", "application/vnd.umajin"},
|
1396
|
+
{"unityweb", "application/vnd.unity"},
|
1397
|
+
{"uoml", "application/vnd.uoml+xml"},
|
1398
|
+
{"uri", "text/uri-list"},
|
1399
|
+
{"uris", "text/uri-list"},
|
1400
|
+
{"urls", "text/uri-list"},
|
1401
|
+
{"ustar", "application/x-ustar"},
|
1402
|
+
{"utz", "application/vnd.uiq.theme"},
|
1403
|
+
{"uu", "text/x-uuencode"},
|
1404
|
+
{"uva", "audio/vnd.dece.audio"},
|
1405
|
+
{"uvd", "application/vnd.dece.data"},
|
1406
|
+
{"uvf", "application/vnd.dece.data"},
|
1407
|
+
{"uvg", "image/vnd.dece.graphic"},
|
1408
|
+
{"uvh", "video/vnd.dece.hd"},
|
1409
|
+
{"uvi", "image/vnd.dece.graphic"},
|
1410
|
+
{"uvm", "video/vnd.dece.mobile"},
|
1411
|
+
{"uvp", "video/vnd.dece.pd"},
|
1412
|
+
{"uvs", "video/vnd.dece.sd"},
|
1413
|
+
{"uvt", "application/vnd.dece.ttml+xml"},
|
1414
|
+
{"uvu", "video/vnd.uvvu.mp4"},
|
1415
|
+
{"uvv", "video/vnd.dece.video"},
|
1416
|
+
{"uvva", "audio/vnd.dece.audio"},
|
1417
|
+
{"uvvd", "application/vnd.dece.data"},
|
1418
|
+
{"uvvf", "application/vnd.dece.data"},
|
1419
|
+
{"uvvg", "image/vnd.dece.graphic"},
|
1420
|
+
{"uvvh", "video/vnd.dece.hd"},
|
1421
|
+
{"uvvi", "image/vnd.dece.graphic"},
|
1422
|
+
{"uvvm", "video/vnd.dece.mobile"},
|
1423
|
+
{"uvvp", "video/vnd.dece.pd"},
|
1424
|
+
{"uvvs", "video/vnd.dece.sd"},
|
1425
|
+
{"uvvt", "application/vnd.dece.ttml+xml"},
|
1426
|
+
{"uvvu", "video/vnd.uvvu.mp4"},
|
1427
|
+
{"uvvv", "video/vnd.dece.video"},
|
1428
|
+
{"uvvx", "application/vnd.dece.unspecified"},
|
1429
|
+
{"uvvz", "application/vnd.dece.zip"},
|
1430
|
+
{"uvx", "application/vnd.dece.unspecified"},
|
1431
|
+
{"uvz", "application/vnd.dece.zip"},
|
1432
|
+
{"vcard", "text/vcard"},
|
1433
|
+
{"vcd", "application/x-cdlink"},
|
1434
|
+
{"vcf", "text/x-vcard"},
|
1435
|
+
{"vcg", "application/vnd.groove-vcard"},
|
1436
|
+
{"vcs", "text/x-vcalendar"},
|
1437
|
+
{"vcx", "application/vnd.vcx"},
|
1438
|
+
{"vis", "application/vnd.visionary"},
|
1439
|
+
{"viv", "video/vnd.vivo"},
|
1440
|
+
{"vob", "video/x-ms-vob"},
|
1441
|
+
{"vor", "application/vnd.stardivision.writer"},
|
1442
|
+
{"vox", "application/x-authorware-bin"},
|
1443
|
+
{"vrml", "model/vrml"},
|
1444
|
+
{"vsd", "application/vnd.visio"},
|
1445
|
+
{"vsf", "application/vnd.vsf"},
|
1446
|
+
{"vss", "application/vnd.visio"},
|
1447
|
+
{"vst", "application/vnd.visio"},
|
1448
|
+
{"vsw", "application/vnd.visio"},
|
1449
|
+
{"vtu", "model/vnd.vtu"},
|
1450
|
+
{"vxml", "application/voicexml+xml"},
|
1451
|
+
{"w3d", "application/x-director"},
|
1452
|
+
{"wad", "application/x-doom"},
|
1453
|
+
{"wav", "audio/x-wav"},
|
1454
|
+
{"wax", "audio/x-ms-wax"},
|
1455
|
+
{"wbmp", "image/vnd.wap.wbmp"},
|
1456
|
+
{"wbs", "application/vnd.criticaltools.wbs+xml"},
|
1457
|
+
{"wbxml", "application/vnd.wap.wbxml"},
|
1458
|
+
{"wcm", "application/vnd.ms-works"},
|
1459
|
+
{"wdb", "application/vnd.ms-works"},
|
1460
|
+
{"wdp", "image/vnd.ms-photo"},
|
1461
|
+
{"weba", "audio/webm"},
|
1462
|
+
{"webm", "video/webm"},
|
1463
|
+
{"webp", "image/webp"},
|
1464
|
+
{"wg", "application/vnd.pmi.widget"},
|
1465
|
+
{"wgt", "application/widget"},
|
1466
|
+
{"wks", "application/vnd.ms-works"},
|
1467
|
+
{"wm", "video/x-ms-wm"},
|
1468
|
+
{"wma", "audio/x-ms-wma"},
|
1469
|
+
{"wmd", "application/x-ms-wmd"},
|
1470
|
+
{"wmf", "application/x-msmetafile"},
|
1471
|
+
{"wml", "text/vnd.wap.wml"},
|
1472
|
+
{"wmlc", "application/vnd.wap.wmlc"},
|
1473
|
+
{"wmls", "text/vnd.wap.wmlscript"},
|
1474
|
+
{"wmlsc", "application/vnd.wap.wmlscriptc"},
|
1475
|
+
{"wmv", "video/x-ms-wmv"},
|
1476
|
+
{"wmx", "video/x-ms-wmx"},
|
1477
|
+
{"wmz", "application/x-ms-wmz"},
|
1478
|
+
{"wmz", "application/x-msmetafile"},
|
1479
|
+
{"woff", "application/font-woff"},
|
1480
|
+
{"wpd", "application/vnd.wordperfect"},
|
1481
|
+
{"wpl", "application/vnd.ms-wpl"},
|
1482
|
+
{"wps", "application/vnd.ms-works"},
|
1483
|
+
{"wqd", "application/vnd.wqd"},
|
1484
|
+
{"wri", "application/x-mswrite"},
|
1485
|
+
{"wrl", "model/vrml"},
|
1486
|
+
{"wsdl", "application/wsdl+xml"},
|
1487
|
+
{"wspolicy", "application/wspolicy+xml"},
|
1488
|
+
{"wtb", "application/vnd.webturbo"},
|
1489
|
+
{"wvx", "video/x-ms-wvx"},
|
1490
|
+
{"x32", "application/x-authorware-bin"},
|
1491
|
+
{"x3d", "model/x3d+xml"},
|
1492
|
+
{"x3db", "model/x3d+binary"},
|
1493
|
+
{"x3dbz", "model/x3d+binary"},
|
1494
|
+
{"x3dv", "model/x3d+vrml"},
|
1495
|
+
{"x3dvz", "model/x3d+vrml"},
|
1496
|
+
{"x3dz", "model/x3d+xml"},
|
1497
|
+
{"xaml", "application/xaml+xml"},
|
1498
|
+
{"xap", "application/x-silverlight-app"},
|
1499
|
+
{"xar", "application/vnd.xara"},
|
1500
|
+
{"xbap", "application/x-ms-xbap"},
|
1501
|
+
{"xbd", "application/vnd.fujixerox.docuworks.binder"},
|
1502
|
+
{"xbm", "image/x-xbitmap"},
|
1503
|
+
{"xdf", "application/xcap-diff+xml"},
|
1504
|
+
{"xdm", "application/vnd.syncml.dm+xml"},
|
1505
|
+
{"xdp", "application/vnd.adobe.xdp+xml"},
|
1506
|
+
{"xdssc", "application/dssc+xml"},
|
1507
|
+
{"xdw", "application/vnd.fujixerox.docuworks"},
|
1508
|
+
{"xenc", "application/xenc+xml"},
|
1509
|
+
{"xer", "application/patch-ops-error+xml"},
|
1510
|
+
{"xfdf", "application/vnd.adobe.xfdf"},
|
1511
|
+
{"xfdl", "application/vnd.xfdl"},
|
1512
|
+
{"xht", "application/xhtml+xml"},
|
1513
|
+
{"xhtml", "application/xhtml+xml"},
|
1514
|
+
{"xhvml", "application/xv+xml"},
|
1515
|
+
{"xif", "image/vnd.xiff"},
|
1516
|
+
{"xla", "application/vnd.ms-excel"},
|
1517
|
+
{"xlam", "application/vnd.ms-excel.addin.macroenabled.12"},
|
1518
|
+
{"xlc", "application/vnd.ms-excel"},
|
1519
|
+
{"xlf", "application/x-xliff+xml"},
|
1520
|
+
{"xlm", "application/vnd.ms-excel"},
|
1521
|
+
{"xls", "application/vnd.ms-excel"},
|
1522
|
+
{"xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12"},
|
1523
|
+
{"xlsm", "application/vnd.ms-excel.sheet.macroenabled.12"},
|
1524
|
+
{"xlsx",
|
1525
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
|
1526
|
+
{"xlt", "application/vnd.ms-excel"},
|
1527
|
+
{"xltm", "application/vnd.ms-excel.template.macroenabled.12"},
|
1528
|
+
{"xltx", "application/"
|
1529
|
+
"vnd.openxmlformats-officedocument.spreadsheetml.template"},
|
1530
|
+
{"xlw", "application/vnd.ms-excel"},
|
1531
|
+
{"xm", "audio/xm"},
|
1532
|
+
{"xml", "application/xml"},
|
1533
|
+
{"xo", "application/vnd.olpc-sugar"},
|
1534
|
+
{"xop", "application/xop+xml"},
|
1535
|
+
{"xpi", "application/x-xpinstall"},
|
1536
|
+
{"xpl", "application/xproc+xml"},
|
1537
|
+
{"xpm", "image/x-xpixmap"},
|
1538
|
+
{"xpr", "application/vnd.is-xpr"},
|
1539
|
+
{"xps", "application/vnd.ms-xpsdocument"},
|
1540
|
+
{"xpw", "application/vnd.intercon.formnet"},
|
1541
|
+
{"xpx", "application/vnd.intercon.formnet"},
|
1542
|
+
{"xsl", "application/xml"},
|
1543
|
+
{"xslt", "application/xslt+xml"},
|
1544
|
+
{"xsm", "application/vnd.syncml+xml"},
|
1545
|
+
{"xspf", "application/xspf+xml"},
|
1546
|
+
{"xul", "application/vnd.mozilla.xul+xml"},
|
1547
|
+
{"xvm", "application/xv+xml"},
|
1548
|
+
{"xvml", "application/xv+xml"},
|
1549
|
+
{"xwd", "image/x-xwindowdump"},
|
1550
|
+
{"xyz", "chemical/x-xyz"},
|
1551
|
+
{"xz", "application/x-xz"},
|
1552
|
+
{"yang", "application/yang"},
|
1553
|
+
{"yin", "application/yin+xml"},
|
1554
|
+
{"z1", "application/x-zmachine"},
|
1555
|
+
{"z2", "application/x-zmachine"},
|
1556
|
+
{"z3", "application/x-zmachine"},
|
1557
|
+
{"z4", "application/x-zmachine"},
|
1558
|
+
{"z5", "application/x-zmachine"},
|
1559
|
+
{"z6", "application/x-zmachine"},
|
1560
|
+
{"z7", "application/x-zmachine"},
|
1561
|
+
{"z8", "application/x-zmachine"},
|
1562
|
+
{"zaz", "application/vnd.zzazz.deck+xml"},
|
1563
|
+
{"zip", "application/zip"},
|
1564
|
+
{"zir", "application/vnd.zul"},
|
1565
|
+
{"zirz", "application/vnd.zul"},
|
1566
|
+
{"zmm", "application/vnd.handheld-entertainment+xml"},
|
1567
|
+
{{0}, NULL},
|
1568
|
+
};
|
1569
|
+
// Copy 8 bytes of the requested extension.
|
1570
|
+
// (8 byte comparison in enough to avoid collisions)
|
1571
|
+
uint64_t ext8byte = 0;
|
1572
|
+
char *extlow = (void *)(&ext8byte);
|
1573
|
+
// change the copy to lowercase
|
1574
|
+
size_t pos = 0;
|
1575
|
+
while (ext[pos] && pos < 8) {
|
1576
|
+
extlow[pos] =
|
1577
|
+
(ext[pos] >= 'A' && ext[pos] <= 'Z') ? (ext[pos] | 32) : ext[pos];
|
1578
|
+
++pos;
|
1579
|
+
}
|
1580
|
+
// optimize starting position
|
1581
|
+
uint8_t start = (uint8_t)extlow[0];
|
1582
|
+
// skip unnecessary reviews
|
1583
|
+
if (start >= 'u')
|
1584
|
+
pos = 800;
|
1585
|
+
else if (start >= 'r')
|
1586
|
+
pos = 640;
|
1587
|
+
else if (start >= 'n')
|
1588
|
+
pos = 499;
|
1589
|
+
else if (start >= 'm')
|
1590
|
+
pos = 400;
|
1591
|
+
else if (start >= 'i')
|
1592
|
+
pos = 300;
|
1593
|
+
else if (start >= 'e')
|
1594
|
+
pos = 190;
|
1595
|
+
else
|
1596
|
+
pos = 0;
|
1597
|
+
// check for 8 byte comparison - should be fast on 64 bit systems.
|
1598
|
+
uint64_t *lstext;
|
1599
|
+
while (List[pos].ext[0]) {
|
1600
|
+
lstext = (uint64_t *)List[pos].ext;
|
1601
|
+
if (ext8byte == *lstext)
|
1602
|
+
return List[pos].mime;
|
1603
|
+
pos++;
|
1604
|
+
}
|
1605
|
+
return NULL;
|
1606
|
+
}
|