iodine 0.4.19 → 0.5.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.

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