| 
									
										
										
										
											2020-02-14 13:17:26 +01:00
										 |  |  |  | /*
 | 
					
						
							|  |  |  |  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-02-14 13:17:26 +01:00
										 |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #include <AK/StringBuilder.h>
 | 
					
						
							|  |  |  |  | #include <LibCore/MimeData.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace Core { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Vector<String> MimeData::formats() const | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     Vector<String> mime_types; | 
					
						
							|  |  |  |  |     mime_types.ensure_capacity(m_data.size()); | 
					
						
							|  |  |  |  |     for (auto it : m_data) | 
					
						
							|  |  |  |  |         mime_types.unchecked_append(it.key); | 
					
						
							|  |  |  |  |     return mime_types; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Vector<URL> MimeData::urls() const | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     auto it = m_data.find("text/uri-list"); | 
					
						
							|  |  |  |  |     if (it == m_data.end()) | 
					
						
							|  |  |  |  |         return {}; | 
					
						
							|  |  |  |  |     Vector<URL> urls; | 
					
						
							|  |  |  |  |     for (auto& line : StringView(it->value).split_view('\n')) { | 
					
						
							|  |  |  |  |         urls.append(URL(line)); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |     return urls; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void MimeData::set_urls(const Vector<URL>& urls) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |  |     for (auto& url : urls) { | 
					
						
							|  |  |  |  |         builder.append(url.to_string()); | 
					
						
							|  |  |  |  |         builder.append('\n'); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |     set_data("text/uri-list", builder.to_byte_buffer()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | String MimeData::text() const | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     return String::copy(m_data.get("text/plain").value_or({})); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void MimeData::set_text(const String& text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     set_data("text/plain", text.to_byte_buffer()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  | String guess_mime_type_based_on_filename(const StringView& path) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".pbm", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/x‑portable‑bitmap"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".pgm", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/x‑portable‑graymap"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".png", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/png"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".ppm", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/x‑portable‑pixmap"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".gif", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/gif"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".bmp", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/bmp"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".jpg", CaseSensitivity::CaseInsensitive) || path.ends_with(".jpeg", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "image/jpeg"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".svg", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-09-07 19:45:14 +02:00
										 |  |  |  |         return "image/svg+xml"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".md", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "text/markdown"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with(".html", CaseSensitivity::CaseInsensitive) || path.ends_with(".htm", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "text/html"; | 
					
						
							| 
									
										
										
										
											2020-10-21 21:14:16 +02:00
										 |  |  |  |     if (path.ends_with("/", CaseSensitivity::CaseInsensitive)) | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |         return "text/html"; | 
					
						
							| 
									
										
										
										
											2020-11-23 16:16:27 +03:30
										 |  |  |  |     if (path.ends_with(".csv", CaseSensitivity::CaseInsensitive)) | 
					
						
							|  |  |  |  |         return "text/csv"; | 
					
						
							| 
									
										
										
										
											2020-07-27 19:49:43 +02:00
										 |  |  |  |     return "text/plain"; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 21:48:21 +03:00
										 |  |  |  | #define ENUMERATE_HEADER_CONTENTS                                                                                                 \
 | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(bmp, "image/bmp", 2, 'B', 'M')                                                                   \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(bzip2, "application/x-bzip2", 3, 'B', 'Z', 'h')                                                  \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(elf, "extra/elf", 4, 0x7F, 'E', 'L', 'F')                                                        \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(gif_87, "image/gif", 6, 'G', 'I', 'F', '8', '7', 'a')                                            \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(gif_89, "image/gif", 6, 'G', 'I', 'F', '8', '9', 'a')                                            \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(gzip, "extra/gzip", 2, 0x1F, 0x8B)                                                               \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(jpeg, "image/jpeg", 4, 0xFF, 0xD8, 0xFF, 0xDB)                                                   \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(jpeg_huh, "image/jpeg", 4, 0xFF, 0xD8, 0xFF, 0xEE)                                               \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(jpeg_jfif, "image/jpeg", 12, 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F', 0x00, 0x01) \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(pbm, "image/x-portable-bitmap", 3, 0x50, 0x31, 0x0A)                                             \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(pgm, "image/x-portable-graymap", 3, 0x50, 0x32, 0x0A)                                            \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(png, "image/png", 8, 0x89, 'P', 'N', 'G', 0x0D, 0x0A, 0x1A, 0x0A)                                \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(ppm, "image/x-portable-pixmap", 3, 0x50, 0x33, 0x0A)                                             \ | 
					
						
							|  |  |  |  |     __ENUMERATE_MIME_TYPE_HEADER(shell, "text/x-shellscript", 10, '#', '!', '/', 'b', 'i', 'n', '/', 's', 'h', '\n') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #define __ENUMERATE_MIME_TYPE_HEADER(var_name, mime_type, pattern_size, ...) \
 | 
					
						
							|  |  |  |  |     static const u8 var_name##_arr[pattern_size] = { __VA_ARGS__ };          \ | 
					
						
							|  |  |  |  |     static constexpr ReadonlyBytes var_name = ReadonlyBytes { var_name##_arr, pattern_size }; | 
					
						
							|  |  |  |  | ENUMERATE_HEADER_CONTENTS | 
					
						
							|  |  |  |  | #undef __ENUMERATE_MIME_TYPE_HEADER
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Optional<String> guess_mime_type_based_on_sniffed_bytes(const ReadonlyBytes& bytes) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | #define __ENUMERATE_MIME_TYPE_HEADER(var_name, mime_type, pattern_size, ...) \
 | 
					
						
							|  |  |  |  |     if (bytes.starts_with(var_name))                                         \ | 
					
						
							|  |  |  |  |         return mime_type; | 
					
						
							|  |  |  |  |     ENUMERATE_HEADER_CONTENTS; | 
					
						
							|  |  |  |  | #undef __ENUMERATE_MIME_TYPE_HEADER
 | 
					
						
							|  |  |  |  |     return {}; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-14 13:17:26 +01:00
										 |  |  |  | } |