      1: <?php
      2:
      3: /**
      4:  * A utility class for carrying out various file system tasks
      5:  *
      6:  * @package alpha::util
      7:  * @since 1.0
      8:  * @author John Collins <dev@alphaframework.org>
      9:  * @version $Id: AlphaFileUtils.inc 1602 2012-12-10 12:04:46Z alphadevx $
     10:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
     11:  * @copyright Copyright (c) 2012, John Collins (founder of Alpha Framework).
     12:  * All rights reserved.
     13:  *
     14:  * <pre>
     15:  * Redistribution and use in source and binary forms, with or
     16:  * without modification, are permitted provided that the
     17:  * following conditions are met:
     18:  *
     19:  * * Redistributions of source code must retain the above
     20:  *   copyright notice, this list of conditions and the
     21:  *   following disclaimer.
     22:  * * Redistributions in binary form must reproduce the above
     23:  *   copyright notice, this list of conditions and the
     24:  *   following disclaimer in the documentation and/or other
     25:  *   materials provided with the distribution.
     26:  * * Neither the name of the Alpha Framework nor the names
     27:  *   of its contributors may be used to endorse or promote
     28:  *   products derived from this software without specific
     29:  *   prior written permission.
     30:  *
     31:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     32:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     33:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     34:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     35:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     36:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     37:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     38:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     39:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     41:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     42:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     43:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     44:  * </pre>
     45:  *
     46:  */
     47: class AlphaFileUtils {
     48:
     49:     /**
     50:      * A hash array for mapping file extensions to MIME types.
     51:      *
     52:      * @var array
     53:      * @since 1.0
     54:      */
     55:     private static $extensionToMIMEMappings = array (
     56:         '3dm' => 'x-world/x-3dmf',
     57:         '3dmf' => 'x-world/x-3dmf',
     58:         'a' => 'application/octet-stream',
     59:         'aab' => 'application/x-authorware-bin',
     60:         'aam' => 'application/x-authorware-map',
     61:         'aas' => 'application/x-authorware-seg',
     62:         'abc' => 'text/vnd.abc',
     63:         'acgi' => 'text/html',
     64:         'afl' => 'video/animaflex',
     65:         'ai' => 'application/postscript',
     66:         'aif' => 'audio/aiff',
     67:         'aifc' => 'audio/aiff',
     68:         'aiff' => 'audio/aiff',
     69:         'aim' => 'application/x-aim',
     70:         'aip' => 'text/x-audiosoft-intra',
     71:         'ani' => 'application/x-navi-animation',
     72:         'aos' => 'application/x-nokia-9000-communicator-add-on-software',
     73:         'aps' => 'application/mime',
     74:         'arc' => 'application/octet-stream',
     75:         'arj' => 'application/arj',
     76:         'art' => 'image/x-jg',
     77:         'asf' => 'video/x-ms-asf',
     78:         'asm' => 'text/x-asm',
     79:         'asp' => 'text/asp',
     80:         'asx' => 'application/x-mplayer2',
     81:         'au' => 'audio/basic',
     82:         'avi' => 'application/x-troff-msvideo',
     83:         'avs' => 'video/avs-video',
     84:         'bcpio' => 'application/x-bcpio',
     85:         'bin' => 'application/octet-stream',
     86:         'bm' => 'image/bmp',
     87:         'bmp' => 'image/bmp',
     88:         'boo' => 'application/book',
     89:         'book' => 'application/book',
     90:         'boz' => 'application/x-bzip2',
     91:         'bsh' => 'application/x-bsh',
     92:         'bz' => 'application/x-bzip',
     93:         'bz2' => 'application/x-bzip2',
     94:         'c' => 'text/plain',
     95:         'c++' => 'text/plain',
     96:         'cat' => 'application/vnd.ms-pki.seccat',
     97:         'cc' => 'text/plain',
     98:         'ccad' => 'application/clariscad',
     99:         'cco' => 'application/x-cocoa',
    100:         'cdf' => 'application/cdf',
    101:         'cer' => 'application/pkix-cert',
    102:         'cha' => 'application/x-chat',
    103:         'chat' => 'application/x-chat',
    104:         'class' => 'application/java',
    105:         'com' => 'application/octet-stream',
    106:         'conf' => 'text/plain',
    107:         'cpio' => 'application/x-cpio',
    108:         'cpp' => 'text/x-c',
    109:         'cpt' => 'application/mac-compactpro',
    110:         'crl' => 'application/pkcs-crl',
    111:         'crt' => 'application/pkix-cert',
    112:         'csh' => 'application/x-csh',
    113:         'css' => 'application/x-pointplus',
    114:         'cxx' => 'text/plain',
    115:         'dcr' => 'application/x-director',
    116:         'deepv' => 'application/x-deepv',
    117:         'def' => 'text/plain',
    118:         'der' => 'application/x-x509-ca-cert',
    119:         'dif' => 'video/x-dv',
    120:         'dir' => 'application/x-director',
    121:         'dl' => 'video/dl',
    122:         'doc' => 'application/msword',
    123:         'dot' => 'application/msword',
    124:         'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    125:         'dp' => 'application/commonground',
    126:         'drw' => 'application/drafting',
    127:         'dump' => 'application/octet-stream',
    128:         'dv' => 'video/x-dv',
    129:         'dvi' => 'application/x-dvi',
    130:         'dwf' => 'drawing/x-dwf (old)',
    131:         'dwg' => 'application/acad',
    132:         'dxf' => 'application/dxf',
    133:         'dxr' => 'application/x-director',
    134:         'el' => 'text/x-script.elisp',
    135:         'elc' => 'application/x-bytecode.elisp (compiled elisp)',
    136:         'env' => 'application/x-envoy',
    137:         'eps' => 'application/postscript',
    138:         'es' => 'application/x-esrehber',
    139:         'etx' => 'text/x-setext',
    140:         'evy' => 'application/envoy',
    141:         'exe' => 'application/octet-stream',
    142:         'f' => 'text/plain',
    143:         'f77' => 'text/x-fortran',
    144:         'f90' => 'text/plain',
    145:         'fdf' => 'application/vnd.fdf',
    146:         'fif' => 'application/fractals',
    147:         'fli' => 'video/fli',
    148:         'flo' => 'image/florian',
    149:         'flx' => 'text/vnd.fmi.flexstor',
    150:         'fmf' => 'video/x-atomic3d-feature',
    151:         'for' => 'text/plain',
    152:         'fpx' => 'image/vnd.fpx',
    153:         'frl' => 'application/freeloader',
    154:         'funk' => 'audio/make',
    155:         'g' => 'text/plain',
    156:         'g3' => 'image/g3fax',
    157:         'gif' => 'image/gif',
    158:         'gl' => 'video/gl',
    159:         'gsd' => 'audio/x-gsm',
    160:         'gsm' => 'audio/x-gsm',
    161:         'gsp' => 'application/x-gsp',
    162:         'gss' => 'application/x-gss',
    163:         'gtar' => 'application/x-gtar',
    164:         'gz' => 'application/x-compressed',
    165:         'gzip' => 'application/x-gzip',
    166:         'h' => 'text/plain',
    167:         'hdf' => 'application/x-hdf',
    168:         'help' => 'application/x-helpfile',
    169:         'hgl' => 'application/vnd.hp-hpgl',
    170:         'hh' => 'text/plain',
    171:         'hlb' => 'text/x-script',
    172:         'hlp' => 'application/hlp',
    173:         'hpg' => 'application/vnd.hp-hpgl',
    174:         'hpgl' => 'application/vnd.hp-hpgl',
    175:         'hqx' => 'application/binhex',
    176:         'hta' => 'application/hta',
    177:         'htc' => 'text/x-component',
    178:         'htm' => 'text/html',
    179:         'html' => 'text/html',
    180:         'htmls' => 'text/html',
    181:         'htt' => 'text/webviewhtml',
    182:         'htx' => 'text/html',
    183:         'ice' => 'x-conference/x-cooltalk',
    184:         'ico' => 'image/x-icon',
    185:         'idc' => 'text/plain',
    186:         'ief' => 'image/ief',
    187:         'iefs' => 'image/ief',
    188:         'iges' => 'application/iges',
    189:         'igs' => 'application/iges',
    190:         'ima' => 'application/x-ima',
    191:         'imap' => 'application/x-httpd-imap',
    192:         'inf' => 'application/inf',
    193:         'ins' => 'application/x-internett-signup',
    194:         'ip' => 'application/x-ip2',
    195:         'isu' => 'video/x-isvideo',
    196:         'it' => 'audio/it',
    197:         'iv' => 'application/x-inventor',
    198:         'ivr' => 'i-world/i-vrml',
    199:         'ivy' => 'application/x-livescreen',
    200:         'jam' => 'audio/x-jam',
    201:         'jav' => 'text/plain',
    202:         'java' => 'text/plain',
    203:         'jcm' => 'application/x-java-commerce',
    204:         'jfif' => 'image/jpeg',
    205:         'jfif-tbnl' => 'image/jpeg',
    206:         'jpe' => 'image/jpeg',
    207:         'jpeg' => 'image/jpeg',
    208:         'jpg' => 'image/jpeg',
    209:         'jps' => 'image/x-jps',
    210:         'js' => 'application/x-javascript',
    211:         'jut' => 'image/jutvision',
    212:         'kar' => 'audio/midi',
    213:         'ksh' => 'application/x-ksh',
    214:         'la' => 'audio/nspaudio',
    215:         'lam' => 'audio/x-liveaudio',
    216:         'latex' => 'application/x-latex',
    217:         'lha' => 'application/lha',
    218:         'lhx' => 'application/octet-stream',
    219:         'list' => 'text/plain',
    220:         'lma' => 'audio/nspaudio',
    221:         'log' => 'text/plain',
    222:         'lsp' => 'application/x-lisp',
    223:         'lst' => 'text/plain',
    224:         'lsx' => 'text/x-la-asf',
    225:         'ltx' => 'application/x-latex',
    226:         'lzh' => 'application/octet-stream',
    227:         'lzx' => 'application/lzx',
    228:         'm' => 'text/plain',
    229:         'm1v' => 'video/mpeg',
    230:         'm2a' => 'audio/mpeg',
    231:         'm2v' => 'video/mpeg',
    232:         'm3u' => 'audio/x-mpequrl',
    233:         'man' => 'application/x-troff-man',
    234:         'map' => 'application/x-navimap',
    235:         'mar' => 'text/plain',
    236:         'mbd' => 'application/mbedlet',
    237:         'mc$' => 'application/x-magic-cap-package-1.0',
    238:         'mcd' => 'application/mcad',
    239:         'mcf' => 'image/vasa',
    240:         'mcp' => 'application/netmc',
    241:         'me' => 'application/x-troff-me',
    242:         'mht' => 'message/rfc822',
    243:         'mhtml' => 'message/rfc822',
    244:         'mid' => 'application/x-midi',
    245:         'midi' => 'application/x-midi',
    246:         'mif' => 'application/x-frame',
    247:         'mime' => 'message/rfc822',
    248:         'mjf' => 'audio/x-vnd.audioexplosion.mjuicemediafile',
    249:         'mjpg' => 'video/x-motion-jpeg',
    250:         'mm' => 'application/base64',
    251:         'mme' => 'application/base64',
    252:         'mod' => 'audio/mod',
    253:         'moov' => 'video/quicktime',
    254:         'mov' => 'video/quicktime',
    255:         'movie' => 'video/x-sgi-movie',
    256:         'mp2' => 'audio/mpeg',
    257:         'mp3' => 'audio/mpeg3',
    258:         'mpa' => 'audio/mpeg',
    259:         'mpc' => 'application/x-project',
    260:         'mpe' => 'video/mpeg',
    261:         'mpeg' => 'video/mpeg',
    262:         'mpg' => 'audio/mpeg',
    263:         'mpga' => 'audio/mpeg',
    264:         'mpp' => 'application/vnd.ms-project',
    265:         'mpt' => 'application/x-project',
    266:         'mpv' => 'application/x-project',
    267:         'mpx' => 'application/x-project',
    268:         'mrc' => 'application/marc',
    269:         'ms' => 'application/x-troff-ms',
    270:         'mv' => 'video/x-sgi-movie',
    271:         'my' => 'audio/make',
    272:         'mzz' => 'application/x-vnd.audioexplosion.mzz',
    273:         'nap' => 'image/naplps',
    274:         'naplps' => 'image/naplps',
    275:         'nc' => 'application/x-netcdf',
    276:         'ncm' => 'application/vnd.nokia.configuration-message',
    277:         'nif' => 'image/x-niff',
    278:         'niff' => 'image/x-niff',
    279:         'nix' => 'application/x-mix-transfer',
    280:         'nsc' => 'application/x-conference',
    281:         'nvd' => 'application/x-navidoc',
    282:         'o' => 'application/octet-stream',
    283:         'oda' => 'application/oda',
    284:         'omc' => 'application/x-omc',
    285:         'omcd' => 'application/x-omcdatamaker',
    286:         'omcr' => 'application/x-omcregerator',
    287:         'p' => 'text/x-pascal',
    288:         'p10' => 'application/pkcs10',
    289:         'p12' => 'application/pkcs-12',
    290:         'p7a' => 'application/x-pkcs7-signature',
    291:         'p7c' => 'application/pkcs7-mime',
    292:         'p7m' => 'application/pkcs7-mime',
    293:         'p7r' => 'application/x-pkcs7-certreqresp',
    294:         'p7s' => 'application/pkcs7-signature',
    295:         'part' => 'application/pro_eng',
    296:         'pas' => 'text/pascal',
    297:         'pbm' => 'image/x-portable-bitmap',
    298:         'pcl' => 'application/vnd.hp-pcl',
    299:         'pct' => 'image/x-pict',
    300:         'pcx' => 'image/x-pcx',
    301:         'pdb' => 'chemical/x-pdb',
    302:         'pdf' => 'application/pdf',
    303:         'pfunk' => 'audio/make',
    304:         'pgm' => 'image/x-portable-graymap',
    305:         'pic' => 'image/pict',
    306:         'pict' => 'image/pict',
    307:         'pkg' => 'application/x-newton-compatible-pkg',
    308:         'pko' => 'application/vnd.ms-pki.pko',
    309:         'pl' => 'text/plain',
    310:         'plx' => 'application/x-pixclscript',
    311:         'pm' => 'image/x-xpixmap',
    312:         'pm4' => 'application/x-pagemaker',
    313:         'pm5' => 'application/x-pagemaker',
    314:         'png' => 'image/png',
    315:         'pnm' => 'application/x-portable-anymap',
    316:         'pot' => 'application/mspowerpoint',
    317:         'pov' => 'model/x-pov',
    318:         'ppa' => 'application/vnd.ms-powerpoint',
    319:         'ppm' => 'image/x-portable-pixmap',
    320:         'pps' => 'application/mspowerpoint',
    321:         'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
    322:         'ppt' => 'application/mspowerpoint',
    323:         'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    324:         'ppz' => 'application/mspowerpoint',
    325:         'pre' => 'application/x-freelance',
    326:         'prt' => 'application/pro_eng',
    327:         'ps' => 'application/postscript',
    328:         'psd' => 'application/octet-stream',
    329:         'pvu' => 'paleovu/x-pv',
    330:         'pwz' => 'application/vnd.ms-powerpoint',
    331:         'py' => 'text/x-script.phyton',
    332:         'pyc' => 'applicaiton/x-bytecode.python',
    333:         'qcp' => 'audio/vnd.qcelp',
    334:         'qd3' => 'x-world/x-3dmf',
    335:         'qd3d' => 'x-world/x-3dmf',
    336:         'qif' => 'image/x-quicktime',
    337:         'qt' => 'video/quicktime',
    338:         'qtc' => 'video/x-qtc',
    339:         'qti' => 'image/x-quicktime',
    340:         'qtif' => 'image/x-quicktime',
    341:         'ra' => 'audio/x-pn-realaudio',
    342:         'ram' => 'audio/x-pn-realaudio',
    343:         'ras' => 'application/x-cmu-raster',
    344:         'rast' => 'image/cmu-raster',
    345:         'rexx' => 'text/x-script.rexx',
    346:         'rf' => 'image/vnd.rn-realflash',
    347:         'rgb' => 'image/x-rgb',
    348:         'rm' => 'application/vnd.rn-realmedia',
    349:         'rmi' => 'audio/mid',
    350:         'rmm' => 'audio/x-pn-realaudio',
    351:         'rmp' => 'audio/x-pn-realaudio',
    352:         'rng' => 'application/ringing-tones',
    353:         'rnx' => 'application/vnd.rn-realplayer',
    354:         'roff' => 'application/x-troff',
    355:         'rp' => 'image/vnd.rn-realpix',
    356:         'rpm' => 'audio/x-pn-realaudio-plugin',
    357:         'rt' => 'text/richtext',
    358:         'rtf' => 'application/rtf',
    359:         'rtx' => 'application/rtf',
    360:         'rv' => 'video/vnd.rn-realvideo',
    361:         's' => 'text/x-asm',
    362:         's3m' => 'audio/s3m',
    363:         'saveme' => 'application/octet-stream',
    364:         'sbk' => 'application/x-tbook',
    365:         'scm' => 'application/x-lotusscreencam',
    366:         'sdml' => 'text/plain',
    367:         'sdp' => 'application/sdp',
    368:         'sdr' => 'application/sounder',
    369:         'sea' => 'application/sea',
    370:         'set' => 'application/set',
    371:         'sgm' => 'text/sgml',
    372:         'sgml' => 'text/sgml',
    373:         'sh' => 'application/x-bsh',
    374:         'shar' => 'application/x-bsh',
    375:         'shtml' => 'text/html',
    376:         'sid' => 'audio/x-psid',
    377:         'sit' => 'application/x-sit',
    378:         'skd' => 'application/x-koan',
    379:         'skm' => 'application/x-koan',
    380:         'skp' => 'application/x-koan',
    381:         'skt' => 'application/x-koan',
    382:         'sl' => 'application/x-seelogo',
    383:         'smi' => 'application/smil',
    384:         'smil' => 'application/smil',
    385:         'snd' => 'audio/basic',
    386:         'sol' => 'application/solids',
    387:         'spc' => 'application/x-pkcs7-certificates',
    388:         'spl' => 'application/futuresplash',
    389:         'spr' => 'application/x-sprite',
    390:         'sprite' => 'application/x-sprite',
    391:         'src' => 'application/x-wais-source',
    392:         'ssi' => 'text/x-server-parsed-html',
    393:         'ssm' => 'application/streamingmedia',
    394:         'sst' => 'application/vnd.ms-pki.certstore',
    395:         'step' => 'application/step',
    396:         'stl' => 'application/sla',
    397:         'stp' => 'application/step',
    398:         'sv4cpio' => 'application/x-sv4cpio',
    399:         'sv4crc' => 'application/x-sv4crc',
    400:         'svf' => 'image/vnd.dwg',
    401:         'svr' => 'application/x-world',
    402:         'swf' => 'application/x-shockwave-flash',
    403:         't' => 'application/x-troff',
    404:         'talk' => 'text/x-speech',
    405:         'tar' => 'application/x-tar',
    406:         'tbk' => 'application/toolbook',
    407:         'tcl' => 'application/x-tcl',
    408:         'tcsh' => 'text/x-script.tcsh',
    409:         'tex' => 'application/x-tex',
    410:         'texi' => 'application/x-texinfo',
    411:         'texinfo' => 'application/x-texinfo',
    412:         'text' => 'application/plain',
    413:         'tgz' => 'application/gnutar',
    414:         'tif' => 'image/tiff',
    415:         'tiff' => 'image/tiff',
    416:         'tr' => 'application/x-troff',
    417:         'tsi' => 'audio/tsp-audio',
    418:         'tsp' => 'application/dsptype',
    419:         'tsv' => 'text/tab-separated-values',
    420:         'turbot' => 'image/florian',
    421:         'txt' => 'text/plain',
    422:         'uil' => 'text/x-uil',
    423:         'uni' => 'text/uri-list',
    424:         'unis' => 'text/uri-list',
    425:         'unv' => 'application/i-deas',
    426:         'uri' => 'text/uri-list',
    427:         'uris' => 'text/uri-list',
    428:         'ustar' => 'application/x-ustar',
    429:         'uu' => 'application/octet-stream',
    430:         'uue' => 'text/x-uuencode',
    431:         'vcd' => 'application/x-cdlink',
    432:         'vcs' => 'text/x-vcalendar',
    433:         'vda' => 'application/vda',
    434:         'vdo' => 'video/vdo',
    435:         'vew' => 'application/groupwise',
    436:         'viv' => 'video/vivo',
    437:         'vivo' => 'video/vivo',
    438:         'vmd' => 'application/vocaltec-media-desc',
    439:         'vmf' => 'application/vocaltec-media-file',
    440:         'voc' => 'audio/voc',
    441:         'vos' => 'video/vosaic',
    442:         'vox' => 'audio/voxware',
    443:         'vqe' => 'audio/x-twinvq-plugin',
    444:         'vqf' => 'audio/x-twinvq',
    445:         'vql' => 'audio/x-twinvq-plugin',
    446:         'vrml' => 'application/x-vrml',
    447:         'vrt' => 'x-world/x-vrt',
    448:         'vsd' => 'application/x-visio',
    449:         'vst' => 'application/x-visio',
    450:         'vsw' => 'application/x-visio',
    451:         'w60' => 'application/wordperfect6.0',
    452:         'w61' => 'application/wordperfect6.1',
    453:         'w6w' => 'application/msword',
    454:         'wav' => 'audio/wav',
    455:         'wb1' => 'application/x-qpro',
    456:         'wbmp' => 'image/vnd.wap.wbmp',
    457:         'web' => 'application/vnd.xara',
    458:         'wiz' => 'application/msword',
    459:         'wk1' => 'application/x-123',
    460:         'wmf' => 'windows/metafile',
    461:         'wml' => 'text/vnd.wap.wml',
    462:         'wmlc' => 'application/vnd.wap.wmlc',
    463:         'wmls' => 'text/vnd.wap.wmlscript',
    464:         'wmlsc' => 'application/vnd.wap.wmlscriptc',
    465:         'word' => 'application/msword',
    466:         'wp' => 'application/wordperfect',
    467:         'wp5' => 'application/wordperfect',
    468:         'wp6' => 'application/wordperfect',
    469:         'wpd' => 'application/wordperfect',
    470:         'wq1' => 'application/x-lotus',
    471:         'wri' => 'application/mswrite',
    472:         'wrl' => 'application/x-world',
    473:         'wrz' => 'model/vrml',
    474:         'wsc' => 'text/scriplet',
    475:         'wsrc' => 'application/x-wais-source',
    476:         'wtk' => 'application/x-wintalk',
    477:         'xbm' => 'image/x-xbitmap',
    478:         'xdr' => 'video/x-amt-demorun',
    479:         'xgz' => 'xgl/drawing',
    480:         'xif' => 'image/vnd.xiff',
    481:         'xl' => 'application/excel',
    482:         'xla' => 'application/excel',
    483:         'xlb' => 'application/excel',
    484:         'xlc' => 'application/excel',
    485:         'xld' => 'application/excel',
    486:         'xlk' => 'application/excel',
    487:         'xll' => 'application/excel',
    488:         'xlm' => 'application/excel',
    489:         'xls' => 'application/excel',
    490:         'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    491:         'xlt' => 'application/excel',
    492:         'xlv' => 'application/excel',
    493:         'xlw' => 'application/excel',
    494:         'xm' => 'audio/xm',
    495:         'xml' => 'application/xml',
    496:         'xmz' => 'xgl/movie',
    497:         'xpix' => 'application/x-vnd.ls-xpix',
    498:         'xpm' => 'image/x-xpixmap',
    499:         'x-png' => 'image/png',
    500:         'xsr' => 'video/x-amt-showrun',
    501:         'xwd' => 'image/x-xwd',
    502:         'xyz' => 'chemical/x-pdb',
    503:         'z' => 'application/x-compress',
    504:         'zip' => 'application/x-compressed',
    505:         'zoo' => 'application/octet-stream',
    506:         'zsh' => 'text/x-script.zsh',
    507:     );
    508:
    509:     /**
    510:      * Method that allows you to determine a MIME type for a file which you provide the extension for.
    511:      *
    512:      * @param string $ext The file extension.
    513:      * @return string
    514:      * @throws IllegalArguementException
    515:      * @since 1.0
    516:      */
    517:     public static function getMIMETypeByExtension($ext) {
    518:         $ext = strtolower($ext);
    519:         if (!isset(AlphaFileUtils::$extensionToMIMEMappings[$ext]))
    520:             throw new IllegalArguementException('Unable to determine the MIME type for the extension ['.$ext.']');
    521:
    522:
    523:         return AlphaFileUtils::$extensionToMIMEMappings[$ext];
    524:     }
    525:
    526:     /**
    527:      * Renders the contents of the directory as a HTML list.
    528:      *
    529:      * @param string $sourceDir The path to the source directory.
    530:      * @param integer $fileCount The current file count (used in recursive calls).
    531:      * @param array $excludeFiles An array of file names to exclude from the list rendered.
    532:      * @return integer The current filecount for the directory.
    533:      * @throws AlphaException
    534:      * @since 1.0
    535:      */
    536:     public static function listDirectoryContents($sourceDir, $fileCount=0, $excludeFiles = array()) {
    537:         try
    538:         {
    539:             $dir = new DirectoryIterator($sourceDir);
    540:             $fileCount = 0;
    541:
    542:             echo '<ul>';
    543:             foreach ($dir as $file) {
    544:                 if(!in_array($file->getFilename(), $excludeFiles)) {
    545:                     if($file->isDir() && !$file->isDot()) {
    546:                         echo '<li><em>'.$file->getPathname().'</em></li>';
    547:                         $fileCount += AlphaFileUtils::listDirectoryContents($file->getPathname(), $fileCount, $excludeFiles);
    548:                     }elseif(!$file->isDot()){
    549:                         $fileName = $file->getFilename();
    550:                         $fileCount++;
    551:                         echo '<li>'.$fileName.'</li>';
    552:                     }
    553:                 }
    554:             }
    555:             echo '</ul>';
    556:
    557:             return $fileCount;
    558:         }catch (Exception $e) {
    559:             throw new AlphaException('Failed list files in the ['.$sourceDir.'] directory, error is ['.$e->getMessage().']');
    560:         }
    561:     }
    562:
    563:     /**
    564:      * Recursively deletes the contents of the directory indicated.
    565:      *
    566:      * @param string $sourceDir The path to the source directory.
    567:      * @param array $excludeFiles An array of file names to exclude from the deletion.
    568:      * @throws AlphaException
    569:      * @since 1.0
    570:      */
    571:     public static function deleteDirectoryContents($sourceDir, $excludeFiles = array()) {
    572:
    573:         try {
    574:             $dir = new DirectoryIterator($sourceDir);
    575:
    576:             foreach ($dir as $file) {
    577:                 if(!in_array($file->getFilename(), $excludeFiles)) {
    578:                     if($file->isDir() && !$file->isDot()) {
    579:                         if(count(scandir($file->getPathname())) == 2) // remove an empty directory
    580:                             rmdir($file->getPathname());
    581:                         else
    582:                             AlphaFileUtils::deleteDirectoryContents($file->getPathname(), $excludeFiles);
    583:                     }elseif(!$file->isDot()){
    584:                         unlink($file->getPathname());
    585:                     }
    586:                 }
    587:             }
    588:         }catch (Exception $e) {
    589:             throw new AlphaException('Failed to delete files files in the ['.$sourceDir.'] directory, error is ['.$e->getMessage().']');
    590:         }
    591:     }
    592:
    593:     /**
    594:      * Recursively copies the indicated folder, or single file, to the desintation location
    595:      *
    596:      * @param string $source The path to the source directory or file.
    597:      * @param string $dest The destination source directory or file.
    598:      * @throws AlphaException
    599:      * @since 1.1
    600:      */
    601:     public static function copy($source, $dest) {
    602:
    603:         if (is_file($source)) {
    604:             if(!copy($source, $dest))
    605:                 throw new AlphaException("Error copying the file [$source] to [$dest].");
    606:             return;
    607:         }
    608:
    609:         // Make destination directory if it does not already exist
    610:         if (!file_exists($dest) && !is_dir($dest)) {
    611:             if(!mkdir($dest))
    612:                 throw new AlphaException("Error creating the destination directory [$dest].");
    613:         }
    614:
    615:         $dir = dir($source);
    616:         while (false !== $entry = $dir->read()) {
    617:             if ($entry == '.' || $entry == '..') {
    618:                 continue;
    619:             }
    620:
    621:             if ($dest !== "$source/$entry") {
    622:                 self::copy("$source/$entry", "$dest/$entry");
    623:             }
    624:         }
    625:
    626:         $dir->close();
    627:     }
    628:
    629:     /**
    630:      * Recursively compresses the contens of the source directory indicated to the desintation zip archive
    631:      *
    632:      * @param string $source The path to the source directory or file.
    633:      * @param string $dest The destination zip file file.
    634:      * @throws AlphaException
    635:      * @since 1.1
    636:      */
    637:     public static function zip($source, $dest) {
    638:         if (extension_loaded('zip') === true) {
    639:
    640:             if (file_exists($source) === true) {
    641:                 $zip = new ZipArchive();
    642:
    643:                 if ($zip->open($dest, ZIPARCHIVE::CREATE) === true) {
    644:                     $source = realpath($source);
    645:
    646:                     if(is_dir($source) === true) {
    647:                         $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
    648:
    649:                         foreach ($files as $file) {
    650:                             $file = realpath($file);
    651:
    652:                             if(is_dir($file) === true) {
    653:                                 $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
    654:                             }
    655:
    656:                             if(is_file($file) === true) {
    657:                                 $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
    658:                             }
    659:                         }
    660:                     }
    661:
    662:                     if(is_file($source) === true) {
    663:                         $zip->addFromString(basename($source), file_get_contents($source));
    664:                     }
    665:                 }
    666:
    667:                 $zip->close();
    668:             }
    669:         }else{
    670:                 throw new AlphaException('Unable to create the zip file ['.$dest.'] as the zip extension is unavailable!');
    671:         }
    672:     }
    673: }
    674:
    675: ?>