Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Class to manage the custom filetypes list that is stored in a config variable. 19 * 20 * @package core 21 * @copyright 2014 The Open University 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 require_once($CFG->libdir . '/filelib.php'); 28 29 /** 30 * Class to manage the custom filetypes list that is stored in a config variable. 31 * 32 * @copyright 2014 The Open University 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 abstract class core_filetypes { 36 /** @var array Cached MIME types for current request */ 37 protected static $cachedtypes; 38 39 /** 40 * Gets default MIME types that are included as standard. 41 * 42 * Note: Use the function get_mimetypes_array to access this data including 43 * any customisations the user might have made. 44 * 45 * @return array Default (pre-installed) MIME type information 46 */ 47 protected static function get_default_types() { 48 return array( 49 'xxx' => array('type' => 'document/unknown', 'icon' => 'unknown'), 50 '3gp' => array('type' => 'video/quicktime', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 51 '7z' => array('type' => 'application/x-7z-compressed', 'icon' => 'archive', 52 'groups' => array('archive'), 'string' => 'archive'), 53 'aac' => array('type' => 'audio/aac', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 54 'string' => 'audio'), 55 'accdb' => array('type' => 'application/msaccess', 'icon' => 'base'), 56 'ai' => array('type' => 'application/postscript', 'icon' => 'eps', 'groups' => array('image'), 'string' => 'image'), 57 'aif' => array('type' => 'audio/x-aiff', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 58 'aiff' => array('type' => 'audio/x-aiff', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 59 'aifc' => array('type' => 'audio/x-aiff', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 60 'applescript' => array('type' => 'text/plain', 'icon' => 'text'), 61 'asc' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 62 'asm' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 63 'au' => array('type' => 'audio/au', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 64 'avi' => array('type' => 'video/x-ms-wm', 'icon' => 'avi', 65 'groups' => array('video', 'web_video'), 'string' => 'video'), 66 'bmp' => array('type' => 'image/bmp', 'icon' => 'bmp', 'groups' => array('image'), 'string' => 'image'), 67 'c' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 68 'cct' => array('type' => 'shockwave/director', 'icon' => 'flash'), 69 'cpp' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 70 'cs' => array('type' => 'application/x-csh', 'icon' => 'sourcecode'), 71 'css' => array('type' => 'text/css', 'icon' => 'text', 'groups' => array('web_file')), 72 'csv' => array('type' => 'text/csv', 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 73 'dv' => array('type' => 'video/x-dv', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 74 'dmg' => array('type' => 'application/octet-stream', 'icon' => 'unknown'), 75 76 'doc' => array('type' => 'application/msword', 'icon' => 'document', 'groups' => array('document')), 77 'bdoc' => array('type' => 'application/x-digidoc', 'icon' => 'document', 'groups' => array('archive')), 78 'cdoc' => array('type' => 'application/x-digidoc', 'icon' => 'document', 'groups' => array('archive')), 79 'ddoc' => array('type' => 'application/x-digidoc', 'icon' => 'document', 'groups' => array('archive')), 80 'docx' => array('type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 81 'icon' => 'document', 'groups' => array('document')), 82 'docm' => array('type' => 'application/vnd.ms-word.document.macroEnabled.12', 'icon' => 'document'), 83 'dotx' => array('type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 84 'icon' => 'document'), 85 'dotm' => array('type' => 'application/vnd.ms-word.template.macroEnabled.12', 'icon' => 'document'), 86 87 'dcr' => array('type' => 'application/x-director', 'icon' => 'flash'), 88 'dif' => array('type' => 'video/x-dv', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 89 'dir' => array('type' => 'application/x-director', 'icon' => 'flash'), 90 'dxr' => array('type' => 'application/x-director', 'icon' => 'flash'), 91 'eps' => array('type' => 'application/postscript', 'icon' => 'eps'), 92 'epub' => array('type' => 'application/epub+zip', 'icon' => 'epub', 'groups' => array('document')), 93 'fdf' => array('type' => 'application/vnd.fdf', 'icon' => 'pdf'), 94 'flac' => array('type' => 'audio/flac', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 95 'string' => 'audio'), 96 'flv' => array('type' => 'video/x-flv', 'icon' => 'flash', 97 'groups' => array('video', 'web_video'), 'string' => 'video'), 98 'f4v' => array('type' => 'video/mp4', 'icon' => 'flash', 'groups' => array('video', 'web_video'), 'string' => 'video'), 99 'fmp4' => array('type' => 'video/mp4', 'icon' => 'mpeg', 'groups' => array('html_video', 'video', 'web_video'), 100 'string' => 'video'), 101 'gallery' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 102 'galleryitem' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 103 'gallerycollection' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 104 'gdraw' => array('type' => 'application/vnd.google-apps.drawing', 'icon' => 'image', 'groups' => array('image')), 105 'gdoc' => array('type' => 'application/vnd.google-apps.document', 'icon' => 'document', 'groups' => array('document')), 106 'gsheet' => array('type' => 'application/vnd.google-apps.spreadsheet', 'icon' => 'spreadsheet', 107 'groups' => array('spreadsheet')), 108 'gslides' => array('type' => 'application/vnd.google-apps.presentation', 'icon' => 'powerpoint', 109 'groups' => array('presentation')), 110 'gif' => array('type' => 'image/gif', 'icon' => 'gif', 'groups' => array('image', 'web_image', 'optimised_image'), 111 'string' => 'image'), 112 'gtar' => array('type' => 'application/x-gtar', 'icon' => 'archive', 113 'groups' => array('archive'), 'string' => 'archive'), 114 'tgz' => array('type' => 'application/g-zip', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive'), 115 'gz' => array('type' => 'application/g-zip', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive'), 116 'gzip' => array('type' => 'application/g-zip', 'icon' => 'archive', 117 'groups' => array('archive'), 'string' => 'archive'), 118 'h' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 119 'h5p' => array('type' => 'application/zip.h5p', 'icon' => 'h5p', 'string' => 'archive'), 120 'hpp' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 121 'hqx' => array('type' => 'application/mac-binhex40', 'icon' => 'archive', 122 'groups' => array('archive'), 'string' => 'archive'), 123 'htc' => array('type' => 'text/x-component', 'icon' => 'markup'), 124 'html' => array('type' => 'text/html', 'icon' => 'html', 'groups' => array('web_file')), 125 'xhtml' => array('type' => 'application/xhtml+xml', 'icon' => 'html', 'groups' => array('web_file')), 126 'htm' => array('type' => 'text/html', 'icon' => 'html', 'groups' => array('web_file')), 127 'ico' => array('type' => 'image/vnd.microsoft.icon', 'icon' => 'image', 128 'groups' => array('image'), 'string' => 'image'), 129 'ics' => array('type' => 'text/calendar', 'icon' => 'text'), 130 'isf' => array('type' => 'application/inspiration', 'icon' => 'isf'), 131 'ist' => array('type' => 'application/inspiration.template', 'icon' => 'isf'), 132 'java' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 133 'jar' => array('type' => 'application/java-archive', 'icon' => 'archive'), 134 'jcb' => array('type' => 'text/xml', 'icon' => 'markup'), 135 'jcl' => array('type' => 'text/xml', 'icon' => 'markup'), 136 'jcw' => array('type' => 'text/xml', 'icon' => 'markup'), 137 'jmt' => array('type' => 'text/xml', 'icon' => 'markup'), 138 'jmx' => array('type' => 'text/xml', 'icon' => 'markup'), 139 'jnlp' => array('type' => 'application/x-java-jnlp-file', 'icon' => 'markup'), 140 'jpe' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image', 'optimised_image'), 141 'string' => 'image'), 142 'jpeg' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image', 'optimised_image'), 143 'string' => 'image'), 144 'jpg' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image', 'optimised_image'), 145 'string' => 'image'), 146 'jqz' => array('type' => 'text/xml', 'icon' => 'markup'), 147 'js' => array('type' => 'application/x-javascript', 'icon' => 'text', 'groups' => array('web_file')), 148 'json' => array('type' => 'application/json', 'icon' => 'text'), 149 'latex' => array('type' => 'application/x-latex', 'icon' => 'text'), 150 'm' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 151 'mbz' => array('type' => 'application/vnd.moodle.backup', 'icon' => 'moodle'), 152 'mdb' => array('type' => 'application/x-msaccess', 'icon' => 'base'), 153 'mht' => array('type' => 'message/rfc822', 'icon' => 'archive'), 154 'mhtml' => array('type' => 'message/rfc822', 'icon' => 'archive'), 155 'mov' => array('type' => 'video/quicktime', 'icon' => 'quicktime', 156 'groups' => array('video', 'web_video', 'html_video'), 'string' => 'video'), 157 'movie' => array('type' => 'video/x-sgi-movie', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 158 'mw' => array('type' => 'application/maple', 'icon' => 'math'), 159 'mws' => array('type' => 'application/maple', 'icon' => 'math'), 160 'm3u' => array('type' => 'audio/x-mpegurl', 'icon' => 'mp3', 'groups' => array('audio'), 'string' => 'audio'), 161 'm3u8' => array('type' => 'application/x-mpegURL', 'icon' => 'mpeg', 'groups' => array('media_source')), 162 'mp3' => array('type' => 'audio/mp3', 'icon' => 'mp3', 'groups' => array('audio', 'html_audio', 'web_audio'), 163 'string' => 'audio'), 164 'mp4' => array('type' => 'video/mp4', 'icon' => 'mpeg', 'groups' => array('html_video', 'video', 'web_video'), 165 'string' => 'video'), 166 'm4v' => array('type' => 'video/mp4', 'icon' => 'mpeg', 'groups' => array('html_video', 'video', 'web_video'), 167 'string' => 'video'), 168 'm4a' => array('type' => 'audio/mp4', 'icon' => 'mp3', 'groups' => array('audio', 'html_audio', 'web_audio'), 169 'string' => 'audio'), 170 'mpeg' => array('type' => 'video/mpeg', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 171 'string' => 'video'), 172 'mpd' => array('type' => 'application/dash+xml', 'icon' => 'mpeg', 'groups' => array('media_source')), 173 'mpe' => array('type' => 'video/mpeg', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 174 'string' => 'video'), 175 'mpg' => array('type' => 'video/mpeg', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 176 'string' => 'video'), 177 'mpr' => array('type' => 'application/vnd.moodle.profiling', 'icon' => 'moodle'), 178 179 'nbk' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 180 'notebook' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 181 182 'odt' => array('type' => 'application/vnd.oasis.opendocument.text', 'icon' => 'writer', 'groups' => array('document')), 183 'ott' => array('type' => 'application/vnd.oasis.opendocument.text-template', 184 'icon' => 'writer', 'groups' => array('document')), 185 'oth' => array('type' => 'application/vnd.oasis.opendocument.text-web', 'icon' => 'oth', 'groups' => array('document')), 186 'odm' => array('type' => 'application/vnd.oasis.opendocument.text-master', 'icon' => 'writer'), 187 'odg' => array('type' => 'application/vnd.oasis.opendocument.graphics', 'icon' => 'draw'), 188 'otg' => array('type' => 'application/vnd.oasis.opendocument.graphics-template', 'icon' => 'draw'), 189 'odp' => array('type' => 'application/vnd.oasis.opendocument.presentation', 'icon' => 'impress', 190 'groups' => array('presentation')), 191 'otp' => array('type' => 'application/vnd.oasis.opendocument.presentation-template', 'icon' => 'impress', 192 'groups' => array('presentation')), 193 'ods' => array('type' => 'application/vnd.oasis.opendocument.spreadsheet', 194 'icon' => 'calc', 'groups' => array('spreadsheet')), 195 'ots' => array('type' => 'application/vnd.oasis.opendocument.spreadsheet-template', 196 'icon' => 'calc', 'groups' => array('spreadsheet')), 197 'odc' => array('type' => 'application/vnd.oasis.opendocument.chart', 'icon' => 'chart'), 198 'odf' => array('type' => 'application/vnd.oasis.opendocument.formula', 'icon' => 'math'), 199 'odb' => array('type' => 'application/vnd.oasis.opendocument.database', 'icon' => 'base'), 200 'odi' => array('type' => 'application/vnd.oasis.opendocument.image', 'icon' => 'draw'), 201 'oga' => array('type' => 'audio/ogg', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 202 'string' => 'audio'), 203 'ogg' => array('type' => 'audio/ogg', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 204 'string' => 'audio'), 205 'ogv' => array('type' => 'video/ogg', 'icon' => 'video', 'groups' => array('html_video', 'video', 'web_video'), 206 'string' => 'video'), 207 208 'pct' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 209 'pdf' => array('type' => 'application/pdf', 'icon' => 'pdf', 'groups' => array('document')), 210 'php' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 211 'pic' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 212 'pict' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 213 'png' => array('type' => 'image/png', 'icon' => 'png', 'groups' => array('image', 'web_image', 'optimised_image'), 214 'string' => 'image'), 215 'pps' => array('type' => 'application/vnd.ms-powerpoint', 'icon' => 'powerpoint', 'groups' => array('presentation')), 216 'ppt' => array('type' => 'application/vnd.ms-powerpoint', 'icon' => 'powerpoint', 'groups' => array('presentation')), 217 'pptx' => array('type' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 218 'icon' => 'powerpoint', 'groups' => array('presentation')), 219 'pptm' => array('type' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'icon' => 'powerpoint', 220 'groups' => array('presentation')), 221 'potx' => array('type' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 222 'icon' => 'powerpoint', 'groups' => array('presentation')), 223 'potm' => array('type' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', 'icon' => 'powerpoint', 224 'groups' => array('presentation')), 225 'ppam' => array('type' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'icon' => 'powerpoint', 226 'groups' => array('presentation')), 227 'ppsx' => array('type' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 228 'icon' => 'powerpoint', 'groups' => array('presentation')), 229 'ppsm' => array('type' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'icon' => 'powerpoint', 230 'groups' => array('presentation')), 231 'ps' => array('type' => 'application/postscript', 'icon' => 'pdf'), 232 'pub' => array('type' => 'application/x-mspublisher', 'icon' => 'publisher', 'groups' => array('presentation')), 233 234 'qt' => array('type' => 'video/quicktime', 'icon' => 'quicktime', 235 'groups' => array('video', 'web_video'), 'string' => 'video'), 236 'ra' => array('type' => 'audio/x-realaudio-plugin', 'icon' => 'audio', 237 'groups' => array('audio', 'web_audio'), 'string' => 'audio'), 238 'ram' => array('type' => 'audio/x-pn-realaudio-plugin', 'icon' => 'audio', 239 'groups' => array('audio'), 'string' => 'audio'), 240 'rar' => array('type' => 'application/x-rar-compressed', 'icon' => 'archive', 241 'groups' => array('archive'), 'string' => 'archive'), 242 'rhb' => array('type' => 'text/xml', 'icon' => 'markup'), 243 'rm' => array('type' => 'audio/x-pn-realaudio-plugin', 'icon' => 'audio', 244 'groups' => array('audio'), 'string' => 'audio'), 245 'rmvb' => array('type' => 'application/vnd.rn-realmedia-vbr', 'icon' => 'video', 246 'groups' => array('video'), 'string' => 'video'), 247 'rtf' => array('type' => 'text/rtf', 'icon' => 'text', 'groups' => array('document')), 248 'rtx' => array('type' => 'text/richtext', 'icon' => 'text'), 249 'rv' => array('type' => 'audio/x-pn-realaudio-plugin', 'icon' => 'audio', 250 'groups' => array('video'), 'string' => 'video'), 251 'scss' => array('type' => 'text/x-scss', 'icon' => 'text', 'groups' => array('web_file')), 252 'sh' => array('type' => 'application/x-sh', 'icon' => 'sourcecode'), 253 'sit' => array('type' => 'application/x-stuffit', 'icon' => 'archive', 254 'groups' => array('archive'), 'string' => 'archive'), 255 'smi' => array('type' => 'application/smil', 'icon' => 'text'), 256 'smil' => array('type' => 'application/smil', 'icon' => 'text'), 257 'sqt' => array('type' => 'text/xml', 'icon' => 'markup'), 258 'svg' => array('type' => 'image/svg+xml', 'icon' => 'image', 259 'groups' => array('image', 'web_image'), 'string' => 'image'), 260 'svgz' => array('type' => 'image/svg+xml', 'icon' => 'image', 261 'groups' => array('image', 'web_image'), 'string' => 'image'), 262 'swa' => array('type' => 'application/x-director', 'icon' => 'flash'), 263 'swf' => array('type' => 'application/x-shockwave-flash', 'icon' => 'flash', 'groups' => array('video', 'web_video')), 264 'swfl' => array('type' => 'application/x-shockwave-flash', 'icon' => 'flash', 'groups' => array('video', 'web_video')), 265 266 'sxw' => array('type' => 'application/vnd.sun.xml.writer', 'icon' => 'writer'), 267 'stw' => array('type' => 'application/vnd.sun.xml.writer.template', 'icon' => 'writer'), 268 'sxc' => array('type' => 'application/vnd.sun.xml.calc', 'icon' => 'calc'), 269 'stc' => array('type' => 'application/vnd.sun.xml.calc.template', 'icon' => 'calc'), 270 'sxd' => array('type' => 'application/vnd.sun.xml.draw', 'icon' => 'draw'), 271 'std' => array('type' => 'application/vnd.sun.xml.draw.template', 'icon' => 'draw'), 272 'sxi' => array('type' => 'application/vnd.sun.xml.impress', 'icon' => 'impress', 'groups' => array('presentation')), 273 'sti' => array('type' => 'application/vnd.sun.xml.impress.template', 'icon' => 'impress', 274 'groups' => array('presentation')), 275 'sxg' => array('type' => 'application/vnd.sun.xml.writer.global', 'icon' => 'writer'), 276 'sxm' => array('type' => 'application/vnd.sun.xml.math', 'icon' => 'math'), 277 278 'tar' => array('type' => 'application/x-tar', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive'), 279 'tif' => array('type' => 'image/tiff', 'icon' => 'tiff', 'groups' => array('image'), 'string' => 'image'), 280 'tiff' => array('type' => 'image/tiff', 'icon' => 'tiff', 'groups' => array('image'), 'string' => 'image'), 281 'tex' => array('type' => 'application/x-tex', 'icon' => 'text'), 282 'texi' => array('type' => 'application/x-texinfo', 'icon' => 'text'), 283 'texinfo' => array('type' => 'application/x-texinfo', 'icon' => 'text'), 284 'ts' => array('type' => 'video/MP2T', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 285 'string' => 'video'), 286 'tsv' => array('type' => 'text/tab-separated-values', 'icon' => 'text'), 287 'txt' => array('type' => 'text/plain', 'icon' => 'text', 'defaulticon' => true), 288 'vtt' => array('type' => 'text/vtt', 'icon' => 'text', 'groups' => array('html_track')), 289 'wav' => array('type' => 'audio/wav', 'icon' => 'wav', 'groups' => array('audio', 'html_audio', 'web_audio'), 290 'string' => 'audio'), 291 'webm' => array('type' => 'video/webm', 'icon' => 'video', 'groups' => array('html_video', 'video', 'web_video'), 292 'string' => 'video'), 293 'wmv' => array('type' => 'video/x-ms-wmv', 'icon' => 'wmv', 'groups' => array('video'), 'string' => 'video'), 294 'asf' => array('type' => 'video/x-ms-asf', 'icon' => 'wmv', 'groups' => array('video'), 'string' => 'video'), 295 'wma' => array('type' => 'audio/x-ms-wma', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 296 297 'xbk' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 298 'xdp' => array('type' => 'application/vnd.adobe.xdp+xml', 'icon' => 'pdf'), 299 'xfd' => array('type' => 'application/vnd.xfdl', 'icon' => 'pdf'), 300 'xfdf' => array('type' => 'application/vnd.adobe.xfdf', 'icon' => 'pdf'), 301 302 'xls' => array('type' => 'application/vnd.ms-excel', 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 303 'xlsx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'icon' => 'spreadsheet', 304 'groups' => array('spreadsheet')), 305 'xlsm' => array('type' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 306 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 307 'xltx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 308 'icon' => 'spreadsheet'), 309 'xltm' => array('type' => 'application/vnd.ms-excel.template.macroEnabled.12', 'icon' => 'spreadsheet'), 310 'xlsb' => array('type' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'icon' => 'spreadsheet'), 311 'xlam' => array('type' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'icon' => 'spreadsheet'), 312 313 'xml' => array('type' => 'application/xml', 'icon' => 'markup'), 314 'xsl' => array('type' => 'text/xml', 'icon' => 'markup'), 315 316 'zip' => array('type' => 'application/zip', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive') 317 ); 318 } 319 320 /** 321 * Given a mimetype - return a valid file extension for it. 322 * 323 * @param $mimetype string 324 * @return string|bool False if the mimetype was not known, a string indicating a valid file extension otherwise. It may not 325 * be the only valid file extension - just the first one found. 326 */ 327 public static function get_file_extension($mimetype) { 328 $types = self::get_types(); 329 foreach ($types as $extension => $info) { 330 if ($info['type'] == $mimetype) { 331 return $extension; 332 } 333 } 334 return false; 335 } 336 337 /** 338 * Gets all the current types. 339 * 340 * @return array Associative array from extension to array of data about type 341 */ 342 public static function &get_types() { 343 // If it was already done in this request, use cache. 344 if (self::$cachedtypes) { 345 return self::$cachedtypes; 346 } 347 348 // Get defaults. 349 $mimetypes = self::get_default_types(); 350 351 // Get custom file types. 352 $custom = self::get_custom_types(); 353 354 // Check value is an array. 355 if (!is_array($custom)) { 356 debugging('Invalid $CFG->customfiletypes (not array)', DEBUG_DEVELOPER); 357 $custom = array(); 358 } 359 360 foreach ($custom as $customentry) { 361 // Each entry is a stdClass object similar to the array values above. 362 if (empty($customentry->extension)) { 363 debugging('Invalid $CFG->customfiletypes entry (extension field required)', 364 DEBUG_DEVELOPER); 365 continue; 366 } 367 368 // To delete a standard entry, set 'deleted' to true. 369 if (!empty($customentry->deleted)) { 370 unset($mimetypes[$customentry->extension]); 371 continue; 372 } 373 374 // Check required fields. 375 if (empty($customentry->type) || empty($customentry->icon)) { 376 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 377 ' (type and icon fields required)', DEBUG_DEVELOPER); 378 continue; 379 } 380 381 // Build result array. 382 $result = array('type' => $customentry->type, 'icon' => $customentry->icon); 383 if (!empty($customentry->groups)) { 384 if (!is_array($customentry->groups)) { 385 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 386 ' (groups field not array)', DEBUG_DEVELOPER); 387 continue; 388 } 389 $result['groups'] = $customentry->groups; 390 } 391 if (!empty($customentry->string)) { 392 if (!is_string($customentry->string)) { 393 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 394 ' (string field not string)', DEBUG_DEVELOPER); 395 continue; 396 } 397 $result['string'] = $customentry->string; 398 } 399 if (!empty($customentry->defaulticon)) { 400 if (!is_bool($customentry->defaulticon)) { 401 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 402 ' (defaulticon field not bool)', DEBUG_DEVELOPER); 403 continue; 404 } 405 $result['defaulticon'] = $customentry->defaulticon; 406 } 407 if (!empty($customentry->customdescription)) { 408 if (!is_string($customentry->customdescription)) { 409 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 410 ' (customdescription field not string)', DEBUG_DEVELOPER); 411 continue; 412 } 413 // As the name suggests, this field is used only for custom entries. 414 $result['customdescription'] = $customentry->customdescription; 415 } 416 417 // Track whether it is a custom filetype or a modified existing 418 // filetype. 419 if (array_key_exists($customentry->extension, $mimetypes)) { 420 $result['modified'] = true; 421 } else { 422 $result['custom'] = true; 423 } 424 425 // Add result array to list. 426 $mimetypes[$customentry->extension] = $result; 427 } 428 429 self::$cachedtypes = $mimetypes; 430 return self::$cachedtypes; 431 } 432 433 /** 434 * Gets custom types from config variable, after decoding the JSON if required. 435 * 436 * @return array Array of custom types (empty array if none) 437 */ 438 protected static function get_custom_types() { 439 global $CFG; 440 if (!empty($CFG->customfiletypes)) { 441 if (is_array($CFG->customfiletypes)) { 442 // You can define this as an array in config.php... 443 return $CFG->customfiletypes; 444 } else { 445 // Or as a JSON string in the config table. 446 return json_decode($CFG->customfiletypes); 447 } 448 } else { 449 return array(); 450 } 451 } 452 453 /** 454 * Sets the custom types into config variable, encoding into JSON. 455 * 456 * @param array $types Array of custom types 457 * @throws coding_exception If the custom types are fixed in config.php. 458 */ 459 protected static function set_custom_types(array $types) { 460 global $CFG; 461 // Check the setting hasn't been forced. 462 if (array_key_exists('customfiletypes', $CFG->config_php_settings)) { 463 throw new coding_exception('Cannot set custom filetypes because they ' . 464 'are defined in config.php'); 465 } 466 if (empty($types)) { 467 unset_config('customfiletypes'); 468 } else { 469 set_config('customfiletypes', json_encode(array_values($types))); 470 } 471 472 // Clear the cached type list. 473 self::reset_caches(); 474 } 475 476 /** 477 * Clears the type cache. This is not needed in normal use as the 478 * set_custom_types function automatically clears the cache. Intended for 479 * use in unit tests. 480 */ 481 public static function reset_caches() { 482 self::$cachedtypes = null; 483 } 484 485 /** 486 * Gets the default types that have been deleted. Returns an array containing 487 * the defaults of all those types. 488 * 489 * @return array Array (same format as get_mimetypes_array) 490 */ 491 public static function get_deleted_types() { 492 $defaults = self::get_default_types(); 493 $deleted = array(); 494 foreach (self::get_custom_types() as $customentry) { 495 if (!empty($customentry->deleted)) { 496 $deleted[$customentry->extension] = $defaults[$customentry->extension]; 497 } 498 } 499 return $deleted; 500 } 501 502 /** 503 * Adds a new entry to the list of custom filetypes. 504 * 505 * @param string $extension File extension without dot, e.g. 'doc' 506 * @param string $mimetype MIME type e.g. 'application/msword' 507 * @param string $coreicon Core icon to use e.g. 'document' 508 * @param array $groups Array of group strings that this type belongs to 509 * @param string $corestring Custom lang string name in mimetypes.php 510 * @param string $customdescription Custom description (plain text/multilang) 511 * @param bool $defaulticon True if this should be the default icon for the type 512 * @throws coding_exception If the extension already exists, or otherwise invalid 513 */ 514 public static function add_type($extension, $mimetype, $coreicon, 515 array $groups = array(), $corestring = '', $customdescription = '', 516 $defaulticon = false) { 517 // Check for blank extensions or incorrectly including the dot. 518 $extension = (string)$extension; 519 if ($extension === '' || $extension[0] === '.') { 520 throw new coding_exception('Invalid extension .' . $extension); 521 } 522 523 // Check extension not already used. 524 $mimetypes = get_mimetypes_array(); 525 if (array_key_exists($extension, $mimetypes)) { 526 throw new coding_exception('Extension ' . $extension . ' already exists'); 527 } 528 529 // For default icon, check there isn't already something with default icon 530 // set for that MIME type. 531 if ($defaulticon) { 532 foreach ($mimetypes as $type) { 533 if ($type['type'] === $mimetype && !empty($type['defaulticon'])) { 534 throw new coding_exception('MIME type ' . $mimetype . 535 ' already has a default icon set'); 536 } 537 } 538 } 539 540 // Get existing custom filetype list. 541 $customs = self::get_custom_types(); 542 543 // Check if there's a 'deleted' entry for the extension, if so then get 544 // rid of it. 545 foreach ($customs as $key => $custom) { 546 if ($custom->extension === $extension) { 547 unset($customs[$key]); 548 } 549 } 550 551 // Set up config record for new type. 552 $newtype = self::create_config_record($extension, $mimetype, $coreicon, $groups, 553 $corestring, $customdescription, $defaulticon); 554 555 // See if there's a default value with this extension. 556 $needsadding = true; 557 $defaults = self::get_default_types(); 558 if (array_key_exists($extension, $defaults)) { 559 // If it has the same values, we don't need to add it. 560 $defaultvalue = $defaults[$extension]; 561 $modified = (array)$newtype; 562 unset($modified['extension']); 563 ksort($defaultvalue); 564 ksort($modified); 565 if ($modified === $defaultvalue) { 566 $needsadding = false; 567 } 568 } 569 570 // Add to array and set in config. 571 if ($needsadding) { 572 $customs[] = $newtype; 573 } 574 self::set_custom_types($customs); 575 } 576 577 /** 578 * Updates an entry in the list of filetypes in config. 579 * 580 * @param string $extension File extension without dot, e.g. 'doc' 581 * @param string $newextension New file extension (same if not changing) 582 * @param string $mimetype MIME type e.g. 'application/msword' 583 * @param string $coreicon Core icon to use e.g. 'document' 584 * @param array $groups Array of group strings that this type belongs to 585 * @param string $corestring Custom lang string name in mimetypes.php 586 * @param string $customdescription Custom description (plain text/multilang) 587 * @param bool $defaulticon True if this should be the default icon for the type 588 * @throws coding_exception If the new extension already exists, or otherwise invalid 589 */ 590 public static function update_type($extension, $newextension, $mimetype, $coreicon, 591 array $groups = array(), $corestring = '', $customdescription = '', 592 $defaulticon = false) { 593 594 // Extension must exist. 595 $extension = (string)$extension; 596 $mimetypes = get_mimetypes_array(); 597 if (!array_key_exists($extension, $mimetypes)) { 598 throw new coding_exception('Extension ' . $extension . ' not found'); 599 } 600 601 // If there's a new extension then this must not exist. 602 $newextension = (string)$newextension; 603 if ($newextension !== $extension) { 604 if ($newextension === '' || $newextension[0] === '.') { 605 throw new coding_exception('Invalid extension .' . $newextension); 606 } 607 if (array_key_exists($newextension, $mimetypes)) { 608 throw new coding_exception('Extension ' . $newextension . ' already exists'); 609 } 610 } 611 612 // For default icon, check there isn't already something with default icon 613 // set for that MIME type (unless it's this). 614 if ($defaulticon) { 615 foreach ($mimetypes as $ext => $type) { 616 if ($ext !== $extension && $type['type'] === $mimetype && 617 !empty($type['defaulticon'])) { 618 throw new coding_exception('MIME type ' . $mimetype . 619 ' already has a default icon set'); 620 } 621 } 622 } 623 624 // Delete the old extension and then add the new one (may be same). This 625 // will correctly handle cases when a default type is involved. 626 self::delete_type($extension); 627 self::add_type($newextension, $mimetype, $coreicon, $groups, $corestring, 628 $customdescription, $defaulticon); 629 } 630 631 /** 632 * Deletes a file type from the config list (or, for a standard one, marks it 633 * as deleted). 634 * 635 * @param string $extension File extension without dot, e.g. 'doc' 636 * @throws coding_exception If the extension does not exist, or otherwise invalid 637 */ 638 public static function delete_type($extension) { 639 // Extension must exist. 640 $mimetypes = get_mimetypes_array(); 641 if (!array_key_exists($extension, $mimetypes)) { 642 throw new coding_exception('Extension ' . $extension . ' not found'); 643 } 644 645 // Get existing custom filetype list. 646 $customs = self::get_custom_types(); 647 648 // Remove any entries for this extension. 649 foreach ($customs as $key => $custom) { 650 if ($custom->extension === $extension && empty($custom->deleted)) { 651 unset($customs[$key]); 652 } 653 } 654 655 // If it was a standard entry (doesn't have 'custom' set) then add a 656 // deleted marker. 657 if (empty($mimetypes[$extension]['custom'])) { 658 $customs[] = (object)array('extension' => $extension, 'deleted' => true); 659 } 660 661 // Save and reset cache. 662 self::set_custom_types($customs); 663 } 664 665 /** 666 * Reverts a file type to the default. May only be called on types that have 667 * default values. This will undelete the type if necessary or set its values. 668 * If the type is already at default values, does nothing. 669 * 670 * @param string $extension File extension without dot, e.g. 'doc' 671 * @return bool True if anything was changed, false if it was already default 672 * @throws coding_exception If the extension is not a default type. 673 */ 674 public static function revert_type_to_default($extension) { 675 $extension = (string)$extension; 676 677 // Check it actually is a default type. 678 $defaults = self::get_default_types(); 679 if (!array_key_exists($extension, $defaults)) { 680 throw new coding_exception('Extension ' . $extension . ' is not a default type'); 681 } 682 683 // Loop through all the custom settings. 684 $changed = false; 685 $customs = self::get_custom_types(); 686 foreach ($customs as $key => $customentry) { 687 if ($customentry->extension === $extension) { 688 unset($customs[$key]); 689 $changed = true; 690 } 691 } 692 693 // Save changes if any. 694 if ($changed) { 695 self::set_custom_types($customs); 696 } 697 return $changed; 698 } 699 700 /** 701 * Converts function parameters into a record for storing in the JSON value. 702 * 703 * @param string $extension File extension without dot, e.g. 'doc' 704 * @param string $mimetype MIME type e.g. 'application/msword' 705 * @param string $coreicon Core icon to use e.g. 'document' 706 * @param array $groups Array of group strings that this type belongs to 707 * @param string $corestring Custom lang string name in mimetypes.php 708 * @param string $customdescription Custom description (plain text/multilang) 709 * @param bool $defaulticon True if this should be the default icon for the type 710 * @return stdClass Record matching the parameters 711 */ 712 protected static function create_config_record($extension, $mimetype, 713 $coreicon, array $groups, $corestring, $customdescription, $defaulticon) { 714 // Construct new entry. 715 $newentry = (object)array('extension' => (string)$extension, 'type' => (string)$mimetype, 716 'icon' => (string)$coreicon); 717 if ($groups) { 718 if (!is_array($groups)) { 719 throw new coding_exception('Groups must be an array'); 720 } 721 foreach ($groups as $group) { 722 if (!is_string($group)) { 723 throw new coding_exception('Groups must be an array of strings'); 724 } 725 } 726 $newentry->groups = $groups; 727 } 728 if ($corestring) { 729 $newentry->string = (string)$corestring; 730 } 731 if ($customdescription) { 732 $newentry->customdescription = (string)$customdescription; 733 } 734 if ($defaulticon) { 735 $newentry->defaulticon = true; 736 } 737 return $newentry; 738 } 739 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body