1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.util.MimeType; 13 14 import hunt.util.AcceptMimeType; 15 16 import hunt.collection; 17 import hunt.logging; 18 import hunt.io.ByteBuffer; 19 import hunt.io.BufferUtils; 20 21 import hunt.text.Charset; 22 import hunt.text.Common; 23 import hunt.Exceptions; 24 import hunt.util.ObjectUtils; 25 26 import std.algorithm; 27 import std.array; 28 import std.container.array; 29 import std.conv; 30 import std.file; 31 import std.path; 32 import std.range; 33 import std.stdio; 34 import std.string; 35 import std.uni; 36 37 class MimeType { 38 /** 39 * A string equivalent of {@link MimeType#ALL}. 40 */ 41 enum string ALL_VALUE = "*/*"; 42 43 /** 44 * A string equivalent of {@link MimeType#APPLICATION_JSON}. 45 */ 46 enum string APPLICATION_JSON_VALUE = "application/json"; 47 48 /** 49 * A string equivalent of {@link MimeType#APPLICATION_OCTET_STREAM}. 50 */ 51 enum string APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream"; 52 53 /** 54 * A string equivalent of {@link MimeType#APPLICATION_XML}. 55 */ 56 enum string APPLICATION_XML_VALUE = "application/xml"; 57 58 /** 59 * 60 */ 61 enum string APPLICATION_X_WWW_FORM_VALUE = "application/x-www-form-urlencoded"; 62 63 /** 64 * A string equivalent of {@link MimeType#IMAGE_GIF}. 65 */ 66 enum string IMAGE_GIF_VALUE = "image/gif"; 67 68 /** 69 * A string equivalent of {@link MimeType#IMAGE_JPEG}. 70 */ 71 enum string IMAGE_JPEG_VALUE = "image/jpeg"; 72 73 /** 74 * A string equivalent of {@link MimeType#IMAGE_PNG}. 75 */ 76 enum string IMAGE_PNG_VALUE = "image/png"; 77 78 /** 79 * A string equivalent of {@link MimeType#TEXT_HTML}. 80 */ 81 enum string TEXT_HTML_VALUE = "text/html"; 82 83 /** 84 * A string equivalent of {@link MimeType#TEXT_PLAIN}. 85 */ 86 enum string TEXT_PLAIN_VALUE = "text/plain"; 87 88 /** 89 * A string equivalent of {@link MimeType#TEXT_XML}. 90 */ 91 enum string TEXT_XML_VALUE = "text/xml"; 92 93 /** 94 * 95 */ 96 enum string TEXT_JSON_VALUE = "text/json"; 97 98 /** 99 * The "mixed" subtype of "multipart" is intended for use when the body parts are independent and 100 * need to be bundled in a particular order. Any "multipart" subtypes that an implementation does 101 * not recognize must be treated as being of subtype "mixed". 102 */ 103 enum string MULTIPART_MIXED_VALUE = "multipart/mixed"; 104 105 /** 106 * The "multipart/alternative" type is syntactically identical to "multipart/mixed", but the 107 * semantics are different. In particular, each of the body parts is an "alternative" version of 108 * the same information. 109 */ 110 enum string MULTIPART_ALTERNATIVE_VALUE = "multipart/alternative"; 111 112 /** 113 * This type is syntactically identical to "multipart/mixed", but the semantics are different. In 114 * particular, in a digest, the default {@code Content-Type} value for a body part is changed from 115 * "text/plain" to "message/rfc822". 116 */ 117 enum string MULTIPART_DIGEST_VALUE = "multipart/digest"; 118 119 /** 120 * This type is syntactically identical to "multipart/mixed", but the semantics are different. In 121 * particular, in a parallel entity, the order of body parts is not significant. 122 */ 123 enum string MULTIPART_PARALLEL_VALUE = "multipart/parallel"; 124 125 /** 126 * The media-type multipart/form-data follows the rules of all multipart MIME data streams as 127 * outlined in RFC 2046. In forms, there are a series of fields to be supplied by the user who 128 * fills out the form. Each field has a name. Within a given form, the names are unique. 129 */ 130 enum string MULTIPART_FORM_VALUE = "multipart/form-data"; 131 132 /** 133 * Public constant mime type that includes all media ranges (i.e. "*/*"). 134 */ 135 __gshared MimeType ALL; 136 __gshared MimeType APPLICATION_JSON; 137 __gshared MimeType APPLICATION_XML; 138 __gshared MimeType APPLICATION_JSON_8859_1; 139 __gshared MimeType APPLICATION_JSON_UTF_8; 140 __gshared MimeType APPLICATION_OCTET_STREAM; 141 __gshared MimeType APPLICATION_X_WWW_FORM; 142 143 __gshared MimeType FORM_ENCODED; 144 145 __gshared MimeType IMAGE_GIF; 146 __gshared MimeType IMAGE_JPEG; 147 __gshared MimeType IMAGE_PNG; 148 149 __gshared MimeType MESSAGE_HTTP; 150 __gshared MimeType MULTIPART_BYTERANGES; 151 152 __gshared MimeType TEXT_HTML; 153 __gshared MimeType TEXT_PLAIN; 154 __gshared MimeType TEXT_XML; 155 __gshared MimeType TEXT_JSON; 156 157 __gshared MimeType TEXT_HTML_8859_1; 158 __gshared MimeType TEXT_HTML_UTF_8; 159 160 __gshared MimeType TEXT_PLAIN_8859_1; 161 __gshared MimeType TEXT_PLAIN_UTF_8; 162 163 __gshared MimeType TEXT_XML_8859_1; 164 __gshared MimeType TEXT_XML_UTF_8; 165 166 __gshared MimeType TEXT_JSON_8859_1; 167 __gshared MimeType TEXT_JSON_UTF_8; 168 169 __gshared MimeType MULTIPART_MIXED; 170 __gshared MimeType MULTIPART_ALTERNATIVE; 171 __gshared MimeType MULTIPART_DIGEST; 172 __gshared MimeType MULTIPART_PARALLEL; 173 __gshared MimeType MULTIPART_FORM; 174 175 __gshared Array!MimeType values; 176 177 shared static this() { 178 179 ALL = new MimeType(ALL_VALUE); 180 181 APPLICATION_JSON = new MimeType(APPLICATION_JSON_VALUE, StandardCharsets.UTF_8); 182 APPLICATION_JSON_8859_1 = new MimeType("application/json;charset=iso-8859-1", APPLICATION_JSON); 183 APPLICATION_JSON_UTF_8 = new MimeType("application/json;charset=utf-8", APPLICATION_JSON); 184 APPLICATION_OCTET_STREAM = new MimeType(APPLICATION_OCTET_STREAM_VALUE); 185 APPLICATION_XML = new MimeType(APPLICATION_XML_VALUE, StandardCharsets.UTF_8); 186 APPLICATION_X_WWW_FORM = new MimeType(APPLICATION_X_WWW_FORM_VALUE); 187 188 IMAGE_GIF = new MimeType(IMAGE_GIF_VALUE); 189 IMAGE_JPEG = new MimeType(IMAGE_JPEG_VALUE); 190 IMAGE_PNG = new MimeType(IMAGE_PNG_VALUE); 191 192 MESSAGE_HTTP = new MimeType("message/http"); 193 MULTIPART_BYTERANGES = new MimeType("multipart/byteranges"); 194 195 TEXT_HTML = new MimeType(TEXT_HTML_VALUE); 196 TEXT_PLAIN = new MimeType(TEXT_PLAIN_VALUE); 197 TEXT_XML = new MimeType(TEXT_XML_VALUE); 198 TEXT_JSON = new MimeType(TEXT_JSON_VALUE, StandardCharsets.UTF_8); 199 200 TEXT_HTML_8859_1 = new MimeType("text/html;charset=iso-8859-1", TEXT_HTML); 201 TEXT_HTML_UTF_8 = new MimeType("text/html;charset=utf-8", TEXT_HTML); 202 203 TEXT_PLAIN_8859_1 = new MimeType("text/plain;charset=iso-8859-1", TEXT_PLAIN); 204 TEXT_PLAIN_UTF_8 = new MimeType("text/plain;charset=utf-8", TEXT_PLAIN); 205 206 TEXT_XML_8859_1 = new MimeType("text/xml;charset=iso-8859-1", TEXT_XML); 207 TEXT_XML_UTF_8 = new MimeType("text/xml;charset=utf-8", TEXT_XML); 208 209 TEXT_JSON_8859_1 = new MimeType("text/json;charset=iso-8859-1", TEXT_JSON); 210 TEXT_JSON_UTF_8 = new MimeType("text/json;charset=utf-8", TEXT_JSON); 211 212 MULTIPART_MIXED = new MimeType(MULTIPART_MIXED_VALUE); 213 MULTIPART_ALTERNATIVE = new MimeType(MULTIPART_ALTERNATIVE_VALUE); 214 MULTIPART_DIGEST = new MimeType(MULTIPART_DIGEST_VALUE); 215 MULTIPART_PARALLEL = new MimeType(MULTIPART_PARALLEL_VALUE); 216 MULTIPART_FORM = new MimeType(MULTIPART_FORM_VALUE); 217 218 values.insertBack(ALL); 219 values.insertBack(APPLICATION_JSON); 220 values.insertBack(APPLICATION_XML); 221 values.insertBack(APPLICATION_JSON_8859_1); 222 values.insertBack(APPLICATION_JSON_UTF_8); 223 values.insertBack(APPLICATION_OCTET_STREAM); 224 values.insertBack(APPLICATION_X_WWW_FORM); 225 226 values.insertBack(IMAGE_GIF); 227 values.insertBack(IMAGE_JPEG); 228 values.insertBack(IMAGE_PNG); 229 230 values.insertBack(MESSAGE_HTTP); 231 values.insertBack(MULTIPART_BYTERANGES); 232 233 values.insertBack(TEXT_HTML); 234 values.insertBack(TEXT_PLAIN); 235 values.insertBack(TEXT_XML); 236 values.insertBack(TEXT_JSON); 237 values.insertBack(TEXT_HTML_8859_1); 238 values.insertBack(TEXT_HTML_UTF_8); 239 values.insertBack(TEXT_PLAIN_8859_1); 240 values.insertBack(TEXT_PLAIN_UTF_8); 241 values.insertBack(TEXT_XML_8859_1); 242 values.insertBack(TEXT_XML_UTF_8); 243 values.insertBack(TEXT_JSON_8859_1); 244 values.insertBack(TEXT_JSON_UTF_8); 245 246 values.insertBack(MULTIPART_MIXED); 247 values.insertBack(MULTIPART_ALTERNATIVE); 248 values.insertBack(MULTIPART_DIGEST); 249 values.insertBack(MULTIPART_PARALLEL); 250 values.insertBack(MULTIPART_FORM); 251 } 252 253 254 private string _string; 255 private MimeType _base; 256 private ByteBuffer _buffer; 257 private Charset _charset; 258 private string _charsetString; 259 private bool _assumedCharset; 260 261 this(string s) { 262 _string = s; 263 _buffer = BufferUtils.toBuffer(s); 264 _base = this; 265 266 ptrdiff_t i = s.indexOf(";charset="); 267 // _charset = Charset.forName(s.substring(i + 9)); 268 if(i == -1) 269 i = s.indexOf("; charset="); 270 271 if(i == -1) { 272 _charsetString = null; 273 _assumedCharset = true; 274 } else { 275 _charsetString = s[i + 9 .. $].toLower(); 276 _assumedCharset = false; 277 } 278 _charset = _charsetString; 279 } 280 281 this(string s, MimeType base) { 282 this(s); 283 _base = base; 284 } 285 286 this(string s, string charset) { 287 _string = s; 288 _base = this; 289 _buffer = BufferUtils.toBuffer(s); 290 _charset = charset; 291 _charsetString = charset.toLower(); 292 _assumedCharset = false; 293 } 294 295 // ByteBuffer asBuffer() { 296 // return _buffer.asReadOnlyBuffer(); 297 // } 298 299 Charset getCharset() { 300 return _charset; 301 } 302 303 string getCharsetString() { 304 return _charsetString; 305 } 306 307 bool isSame(string s) { 308 return _string.equalsIgnoreCase(s); 309 } 310 311 string asString() { 312 return _string; 313 } 314 315 override 316 string toString() { 317 return _string; 318 } 319 320 bool isCharsetAssumed() { 321 return _assumedCharset; 322 } 323 324 MimeType getBaseType() { 325 return _base; 326 } 327 } 328