Changeset 64 in code
- Timestamp:
- Dec 21, 2016, 5:10:56 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/morty.go
r63 r64 11 11 "io" 12 12 "log" 13 "mime" 13 14 "net/url" 15 "path/filepath" 14 16 "regexp" 15 17 "strings" … … 37 39 var CSS_URL_REGEXP *regexp.Regexp = regexp.MustCompile("url\\((['\"]?)[ \\t\\f]*([\u0009\u0021\u0023-\u0026\u0028\u002a-\u007E]+)(['\"]?)\\)?") 38 40 39 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types 40 // https://www.w3.org/TR/2009/WD-MathML3-20090604/mathml.pdf 41 // http://planetsvg.com/tools/mime.php 42 var FORBIDDEN_CONTENTTYPE_FILTER contenttype.Filter = contenttype.NewFilterOr([]contenttype.Filter{ 43 // javascript44 contenttype.NewFilter Contains("javascript"),45 contenttype.NewFilterContains("ecmascript"),46 contenttype.NewFilterEquals(" application", "js", "*"),47 // no xml (can contain xhtml or css)48 contenttype.NewFilterEquals(" text", "xml", "*"),49 contenttype.NewFilterEquals(" text", "xml-external-parsed-entity", "*"),50 contenttype.NewFilterEquals(" application", "xml", "*"),51 contenttype.NewFilterEquals(" application", "xml-external-parsed-entity", "*"),52 contenttype.NewFilterEquals(" application", "xslt", "xml"),53 // no mathml54 contenttype.NewFilterEquals(" application", "mathml", "xml"),55 contenttype.NewFilterEquals("application", "mathml-presentation", "xml"),56 contenttype.NewFilterEquals("application", " mathml-content", "xml"),57 // no svg58 contenttype.NewFilterEquals(" image", "svg", "xml"),59 contenttype.NewFilterEquals(" image", "svg-xml", "*"),60 // no cache 61 contenttype.NewFilterEquals("text", "cache-manifest", "*"), 62 // no multipart 63 contenttype.NewFilterEquals("multipart", "*", "*"),64 // no xul65 contenttype.NewFilterEquals(" application", "vnd.mozilla.xul", "xml"),66 // no htc67 contenttype.NewFilterEquals("text", "x-component", "*"),68 // no flash69 contenttype.NewFilterEquals("application", "x-shockwave-flash", "*"),70 contenttype.NewFilterEquals(" video", "x-flv", ""),71 contenttype.NewFilterEquals(" video", "vnd.sealed-swf", ""),72 // no know format to have issues73 contenttype.NewFilterEquals(" image", "wmf", "*"),74 contenttype.NewFilterEquals(" image", "emf", "*"),75 // some of the microsoft and IE mime types76 contenttype.NewFilterEquals("text", "vbs", "*"),77 contenttype.NewFilterEquals(" text", "vbscript", "*"),78 contenttype.NewFilterEquals(" text", "scriptlet", "*"),79 contenttype.NewFilterEquals("application", "x- vbs", "*"),80 contenttype.NewFilterEquals("application", " olescript", "*"),81 contenttype.NewFilterEquals("application", "x- msmetafile", "*"),82 // no css (sometime, rendering depend on the browser)83 contenttype.NewFilterEquals("application", " x-pointplus", "*"),41 var ALLOWED_CONTENTTYPE_FILTER contenttype.Filter = contenttype.NewFilterOr([]contenttype.Filter{ 42 // html 43 contenttype.NewFilterEquals("text", "html", ""), 44 contenttype.NewFilterEquals("application", "xhtml", "xml"), 45 // css 46 contenttype.NewFilterEquals("text", "css", ""), 47 // images 48 contenttype.NewFilterEquals("image", "gif", ""), 49 contenttype.NewFilterEquals("image", "png", ""), 50 contenttype.NewFilterEquals("image", "jpeg", ""), 51 contenttype.NewFilterEquals("image", "pjpeg", ""), 52 contenttype.NewFilterEquals("image", "webp", ""), 53 contenttype.NewFilterEquals("image", "tiff", ""), 54 contenttype.NewFilterEquals("image", "vnd.microsoft.icon", ""), 55 contenttype.NewFilterEquals("image", "bmp", ""), 56 contenttype.NewFilterEquals("image", "x-ms-bmp", ""), 57 // fonts 58 contenttype.NewFilterEquals("application", "font-otf", ""), 59 contenttype.NewFilterEquals("application", "font-ttf", ""), 60 contenttype.NewFilterEquals("application", "font-woff", ""), 61 contenttype.NewFilterEquals("application", "vnd.ms-fontobject", ""), 62 }) 63 64 var ALLOWED_CONTENTTYPE_ATTACHMENT_FILTER contenttype.Filter = contenttype.NewFilterOr([]contenttype.Filter{ 65 // texts 66 contenttype.NewFilterEquals("text", "csv", ""), 67 contenttype.NewFilterEquals("text", "tab-separated-value", ""), 68 contenttype.NewFilterEquals("text", "plain", ""), 69 // API 70 contenttype.NewFilterEquals("application", "json", ""), 71 // Documents 72 contenttype.NewFilterEquals("application", "x-latex", ""), 73 contenttype.NewFilterEquals("application", "pdf", ""), 74 contenttype.NewFilterEquals("application", "vnd.oasis.opendocument.text", ""), 75 contenttype.NewFilterEquals("application", "vnd.oasis.opendocument.spreadsheet", ""), 76 contenttype.NewFilterEquals("application", "vnd.oasis.opendocument.presentation", ""), 77 contenttype.NewFilterEquals("application", "vnd.oasis.opendocument.graphics", ""), 78 // Compressed archives 79 contenttype.NewFilterEquals("application", "zip", ""), 80 contenttype.NewFilterEquals("application", "gzip", ""), 81 contenttype.NewFilterEquals("application", "x-compressed", ""), 82 contenttype.NewFilterEquals("application", "x-gtar", ""), 83 contenttype.NewFilterEquals("application", "x-compress", ""), 84 // Generic binary 85 contenttype.NewFilterEquals("application", "octet-stream", ""), 84 86 }) 85 87 … … 323 325 } 324 326 325 // deny access to forbidden content type 326 if FORBIDDEN_CONTENTTYPE_FILTER(contentType) { 327 // HTTP status code 403 : Forbidden 328 p.serveMainPage(ctx, 403, errors.New("forbidden content type")) 329 return 327 // content-disposition 328 contentDispositionBytes := ctx.Request.Header.Peek("Content-Disposition") 329 330 // check content type 331 if !ALLOWED_CONTENTTYPE_FILTER(contentType) { 332 // it is not a usual content type 333 if ALLOWED_CONTENTTYPE_ATTACHMENT_FILTER(contentType) { 334 // force attachment for allowed content type 335 contentDispositionBytes = contentDispositionForceAttachment(contentDispositionBytes, parsedURI) 336 } else { 337 // deny access to forbidden content type 338 // HTTP status code 403 : Forbidden 339 p.serveMainPage(ctx, 403, errors.New("forbidden content type")) 340 return 341 } 330 342 } 331 343 … … 364 376 ctx.SetContentType(contentType.String()) 365 377 378 // output according to MIME type 366 379 switch { 367 380 case contentType.SubType == "css" && contentType.Suffix == "": … … 370 383 sanitizeHTML(&RequestConfig{Key: p.Key, BaseURL: parsedURI}, ctx, responseBody) 371 384 default: 372 if c tx.Request.Header.Peek("Content-Disposition")!= nil {373 ctx.Response.Header.AddBytesV("Content-Disposition", c tx.Request.Header.Peek("Content-Disposition"))385 if contentDispositionBytes != nil { 386 ctx.Response.Header.AddBytesV("Content-Disposition", contentDispositionBytes) 374 387 } 375 388 ctx.Write(responseBody) 376 389 } 390 } 391 392 // force content-disposition to attachment 393 func contentDispositionForceAttachment(contentDispositionBytes []byte, url *url.URL) []byte { 394 var contentDispositionParams map[string]string 395 396 if contentDispositionBytes != nil { 397 var err error 398 _, contentDispositionParams, err = mime.ParseMediaType(string(contentDispositionBytes)) 399 if err != nil { 400 contentDispositionParams = make(map[string]string) 401 } 402 } else { 403 contentDispositionParams = make(map[string]string) 404 } 405 406 _, fileNameDefined := contentDispositionParams["filename"] 407 if !fileNameDefined { 408 // TODO : sanitize filename 409 contentDispositionParams["fileName"] = filepath.Base(url.Path) 410 } 411 412 return []byte(mime.FormatMediaType("attachment", contentDispositionParams)) 377 413 } 378 414
Note:
See TracChangeset
for help on using the changeset viewer.