| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php //$Id: filelib.php,v 1.50.2.23 2008/10/09 07:11:19 scyrma Exp $ 2 3 define('BYTESERVING_BOUNDARY', 's1k2o3d4a5k6s7'); //unique string constant 4 5 function get_file_url($path, $options=null, $type='coursefile') { 6 global $CFG, $HTTPSPAGEREQUIRED; 7 8 $path = str_replace('//', '/', $path); 9 $path = trim($path, '/'); // no leading and trailing slashes 10 11 // type of file 12 switch ($type) { 13 case 'questionfile': 14 $url = $CFG->wwwroot."/question/exportfile.php"; 15 break; 16 case 'rssfile': 17 $url = $CFG->wwwroot."/rss/file.php"; 18 break; 19 case 'user': 20 if (!empty($HTTPSPAGEREQUIRED)) { 21 $wwwroot = $CFG->httpswwwroot; 22 } 23 else { 24 $wwwroot = $CFG->wwwroot; 25 } 26 $url = $wwwroot."/user/pix.php"; 27 break; 28 case 'usergroup': 29 $url = $CFG->wwwroot."/user/pixgroup.php"; 30 break; 31 case 'httpscoursefile': 32 $url = $CFG->httpswwwroot."/file.php"; 33 break; 34 case 'coursefile': 35 default: 36 $url = $CFG->wwwroot."/file.php"; 37 } 38 39 if ($CFG->slasharguments) { 40 $parts = explode('/', $path); 41 $parts = array_map('rawurlencode', $parts); 42 $path = implode('/', $parts); 43 $ffurl = $url.'/'.$path; 44 $separator = '?'; 45 } else { 46 $path = rawurlencode('/'.$path); 47 $ffurl = $url.'?file='.$path; 48 $separator = '&'; 49 } 50 51 if ($options) { 52 foreach ($options as $name=>$value) { 53 $ffurl = $ffurl.$separator.$name.'='.$value; 54 $separator = '&'; 55 } 56 } 57 58 return $ffurl; 59 } 60 61 /** 62 * Fetches content of file from Internet (using proxy if defined). Uses cURL extension if present. 63 * Due to security concerns only downloads from http(s) sources are supported. 64 * 65 * @param string $url file url starting with http(s):// 66 * @param array $headers http headers, null if none. If set, should be an 67 * associative array of header name => value pairs. 68 * @param array $postdata array means use POST request with given parameters 69 * @param bool $fullresponse return headers, responses, etc in a similar way snoopy does 70 * (if false, just returns content) 71 * @param int $timeout timeout for complete download process including all file transfer 72 * (default 5 minutes) 73 * @param int $connecttimeout timeout for connection to server; this is the timeout that 74 * usually happens if the remote server is completely down (default 20 seconds); 75 * may not work when using proxy 76 * @param bool $skipcertverify If true, the peer's SSL certificate will not be checked. Only use this when already in a trusted location. 77 * @return mixed false if request failed or content of the file as string if ok. 78 */ 79 function download_file_content($url, $headers=null, $postdata=null, $fullresponse=false, $timeout=300, $connecttimeout=20, $skipcertverify=false) { 80 global $CFG; 81 82 // some extra security 83 $newlines = array("\r", "\n"); 84 if (is_array($headers) ) { 85 foreach ($headers as $key => $value) { 86 $headers[$key] = str_replace($newlines, '', $value); 87 } 88 } 89 $url = str_replace($newlines, '', $url); 90 if (!preg_match('|^https?://|i', $url)) { 91 if ($fullresponse) { 92 $response = new object(); 93 $response->status = 0; 94 $response->headers = array(); 95 $response->response_code = 'Invalid protocol specified in url'; 96 $response->results = ''; 97 $response->error = 'Invalid protocol specified in url'; 98 return $response; 99 } else { 100 return false; 101 } 102 } 103 104 105 if (!extension_loaded('curl') or ($ch = curl_init($url)) === false) { 106 require_once($CFG->libdir.'/snoopy/Snoopy.class.inc'); 107 $snoopy = new Snoopy(); 108 $snoopy->read_timeout = $timeout; 109 $snoopy->_fp_timeout = $connecttimeout; 110 $snoopy->proxy_host = $CFG->proxyhost; 111 $snoopy->proxy_port = $CFG->proxyport; 112 if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) { 113 // this will probably fail, but let's try it anyway 114 $snoopy->proxy_user = $CFG->proxyuser; 115 $snoopy->proxy_password = $CFG->proxypassword; 116 } 117 if (is_array($headers) ) { 118 $client->rawheaders = $headers; 119 } 120 121 if (is_array($postdata)) { 122 $fetch = @$snoopy->fetch($url, $postdata); // use more specific debug code bellow 123 } else { 124 $fetch = @$snoopy->fetch($url); // use more specific debug code bellow 125 } 126 127 if ($fetch) { 128 if ($fullresponse) { 129 //fix header line endings 130 foreach ($snoopy->headers as $key=>$unused) { 131 $snoopy->headers[$key] = trim($snoopy->headers[$key]); 132 } 133 $response = new object(); 134 $response->status = $snoopy->status; 135 $response->headers = $snoopy->headers; 136 $response->response_code = trim($snoopy->response_code); 137 $response->results = $snoopy->results; 138 $response->error = $snoopy->error; 139 return $response; 140 141 } else if ($snoopy->status != 200) { 142 debugging("Snoopy request for \"$url\" failed, http response code: ".$snoopy->response_code, DEBUG_ALL); 143 return false; 144 145 } else { 146 return $snoopy->results; 147 } 148 } else { 149 if ($fullresponse) { 150 $response = new object(); 151 $response->status = $snoopy->status; 152 $response->headers = array(); 153 $response->response_code = $snoopy->response_code; 154 $response->results = ''; 155 $response->error = $snoopy->error; 156 return $response; 157 } else { 158 debugging("Snoopy request for \"$url\" failed with: ".$snoopy->error, DEBUG_ALL); 159 return false; 160 } 161 } 162 } 163 164 // set extra headers 165 if (is_array($headers) ) { 166 $headers2 = array(); 167 foreach ($headers as $key => $value) { 168 $headers2[] = "$key: $value"; 169 } 170 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers2); 171 } 172 173 174 if ($skipcertverify) { 175 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 176 } 177 178 // use POST if requested 179 if (is_array($postdata)) { 180 foreach ($postdata as $k=>$v) { 181 $postdata[$k] = urlencode($k).'='.urlencode($v); 182 } 183 $postdata = implode('&', $postdata); 184 curl_setopt($ch, CURLOPT_POST, true); 185 curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); 186 } 187 188 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 189 curl_setopt($ch, CURLOPT_HEADER, true); 190 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connecttimeout); 191 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 192 if (!ini_get('open_basedir') and !ini_get('safe_mode')) { 193 // TODO: add version test for '7.10.5' 194 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 195 curl_setopt($ch, CURLOPT_MAXREDIRS, 5); 196 } 197 198 if (!empty($CFG->proxyhost)) { 199 // SOCKS supported in PHP5 only 200 if (!empty($CFG->proxytype) and ($CFG->proxytype == 'SOCKS5')) { 201 if (defined('CURLPROXY_SOCKS5')) { 202 curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); 203 } else { 204 curl_close($ch); 205 if ($fullresponse) { 206 $response = new object(); 207 $response->status = '0'; 208 $response->headers = array(); 209 $response->response_code = 'SOCKS5 proxy is not supported in PHP4'; 210 $response->results = ''; 211 $response->error = 'SOCKS5 proxy is not supported in PHP4'; 212 return $response; 213 } else { 214 debugging("SOCKS5 proxy is not supported in PHP4.", DEBUG_ALL); 215 return false; 216 } 217 } 218 } 219 220 curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false); 221 222 if (empty($CFG->proxyport)) { 223 curl_setopt($ch, CURLOPT_PROXY, $CFG->proxyhost); 224 } else { 225 curl_setopt($ch, CURLOPT_PROXY, $CFG->proxyhost.':'.$CFG->proxyport); 226 } 227 228 if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) { 229 curl_setopt($ch, CURLOPT_PROXYUSERPWD, $CFG->proxyuser.':'.$CFG->proxypassword); 230 if (defined('CURLOPT_PROXYAUTH')) { 231 // any proxy authentication if PHP 5.1 232 curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC | CURLAUTH_NTLM); 233 } 234 } 235 } 236 237 $data = curl_exec($ch); 238 239 // try to detect encoding problems 240 if ((curl_errno($ch) == 23 or curl_errno($ch) == 61) and defined('CURLOPT_ENCODING')) { 241 curl_setopt($ch, CURLOPT_ENCODING, 'none'); 242 $data = curl_exec($ch); 243 } 244 245 if (curl_errno($ch)) { 246 $error = curl_error($ch); 247 $error_no = curl_errno($ch); 248 curl_close($ch); 249 250 if ($fullresponse) { 251 $response = new object(); 252 if ($error_no == 28) { 253 $response->status = '-100'; // mimic snoopy 254 } else { 255 $response->status = '0'; 256 } 257 $response->headers = array(); 258 $response->response_code = $error; 259 $response->results = ''; 260 $response->error = $error; 261 return $response; 262 } else { 263 debugging("cURL request for \"$url\" failed with: $error ($error_no)", DEBUG_ALL); 264 return false; 265 } 266 267 } else { 268 $info = curl_getinfo($ch); 269 curl_close($ch); 270 271 if (empty($info['http_code'])) { 272 // for security reasons we support only true http connections (Location: file:// exploit prevention) 273 $response = new object(); 274 $response->status = '0'; 275 $response->headers = array(); 276 $response->response_code = 'Unknown cURL error'; 277 $response->results = ''; // do NOT change this! 278 $response->error = 'Unknown cURL error'; 279 280 } else { 281 // strip redirect headers and get headers array and content 282 $data = explode("\r\n\r\n", $data, $info['redirect_count'] + 2); 283 $results = array_pop($data); 284 $headers = array_pop($data); 285 $headers = explode("\r\n", trim($headers)); 286 287 $response = new object();; 288 $response->status = (string)$info['http_code']; 289 $response->headers = $headers; 290 $response->response_code = $headers[0]; 291 $response->results = $results; 292 $response->error = ''; 293 } 294 295 if ($fullresponse) { 296 return $response; 297 } else if ($info['http_code'] != 200) { 298 debugging("cURL request for \"$url\" failed, HTTP response code: ".$response->response_code, DEBUG_ALL); 299 return false; 300 } else { 301 return $response->results; 302 } 303 } 304 } 305 306 /** 307 * @return List of information about file types based on extensions. 308 * Associative array of extension (lower-case) to associative array 309 * from 'element name' to data. Current element names are 'type' and 'icon'. 310 * Unknown types should use the 'xxx' entry which includes defaults. 311 */ 312 function get_mimetypes_array() { 313 return array ( 314 'xxx' => array ('type'=>'document/unknown', 'icon'=>'unknown.gif'), 315 '3gp' => array ('type'=>'video/quicktime', 'icon'=>'video.gif'), 316 'ai' => array ('type'=>'application/postscript', 'icon'=>'image.gif'), 317 'aif' => array ('type'=>'audio/x-aiff', 'icon'=>'audio.gif'), 318 'aiff' => array ('type'=>'audio/x-aiff', 'icon'=>'audio.gif'), 319 'aifc' => array ('type'=>'audio/x-aiff', 'icon'=>'audio.gif'), 320 'applescript' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 321 'asc' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 322 'asm' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 323 'au' => array ('type'=>'audio/au', 'icon'=>'audio.gif'), 324 'avi' => array ('type'=>'video/x-ms-wm', 'icon'=>'avi.gif'), 325 'bmp' => array ('type'=>'image/bmp', 'icon'=>'image.gif'), 326 'c' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 327 'cct' => array ('type'=>'shockwave/director', 'icon'=>'flash.gif'), 328 'cpp' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 329 'cs' => array ('type'=>'application/x-csh', 'icon'=>'text.gif'), 330 'css' => array ('type'=>'text/css', 'icon'=>'text.gif'), 331 'csv' => array ('type'=>'text/csv', 'icon'=>'excel.gif'), 332 'dv' => array ('type'=>'video/x-dv', 'icon'=>'video.gif'), 333 'dmg' => array ('type'=>'application/octet-stream', 'icon'=>'dmg.gif'), 334 'doc' => array ('type'=>'application/msword', 'icon'=>'word.gif'), 335 'docx' => array ('type'=>'application/msword', 'icon'=>'docx.gif'), 336 'docm' => array ('type'=>'application/msword', 'icon'=>'docm.gif'), 337 'dotx' => array ('type'=>'application/msword', 'icon'=>'dotx.gif'), 338 'dcr' => array ('type'=>'application/x-director', 'icon'=>'flash.gif'), 339 'dif' => array ('type'=>'video/x-dv', 'icon'=>'video.gif'), 340 'dir' => array ('type'=>'application/x-director', 'icon'=>'flash.gif'), 341 'dxr' => array ('type'=>'application/x-director', 'icon'=>'flash.gif'), 342 'eps' => array ('type'=>'application/postscript', 'icon'=>'pdf.gif'), 343 'fdf' => array ('type'=>'application/pdf', 'icon'=>'pdf.gif'), 344 'flv' => array ('type'=>'video/x-flv', 'icon'=>'video.gif'), 345 'gif' => array ('type'=>'image/gif', 'icon'=>'image.gif'), 346 'gtar' => array ('type'=>'application/x-gtar', 'icon'=>'zip.gif'), 347 'tgz' => array ('type'=>'application/g-zip', 'icon'=>'zip.gif'), 348 'gz' => array ('type'=>'application/g-zip', 'icon'=>'zip.gif'), 349 'gzip' => array ('type'=>'application/g-zip', 'icon'=>'zip.gif'), 350 'h' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 351 'hpp' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 352 'hqx' => array ('type'=>'application/mac-binhex40', 'icon'=>'zip.gif'), 353 'htc' => array ('type'=>'text/x-component', 'icon'=>'text.gif'), 354 'html' => array ('type'=>'text/html', 'icon'=>'html.gif'), 355 'xhtml'=> array ('type'=>'application/xhtml+xml', 'icon'=>'html.gif'), 356 'htm' => array ('type'=>'text/html', 'icon'=>'html.gif'), 357 'ico' => array ('type'=>'image/vnd.microsoft.icon', 'icon'=>'image.gif'), 358 'ics' => array ('type'=>'text/calendar', 'icon'=>'text.gif'), 359 'isf' => array ('type'=>'application/inspiration', 'icon'=>'isf.gif'), 360 'ist' => array ('type'=>'application/inspiration.template', 'icon'=>'isf.gif'), 361 'java' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 362 'jcb' => array ('type'=>'text/xml', 'icon'=>'jcb.gif'), 363 'jcl' => array ('type'=>'text/xml', 'icon'=>'jcl.gif'), 364 'jcw' => array ('type'=>'text/xml', 'icon'=>'jcw.gif'), 365 'jmt' => array ('type'=>'text/xml', 'icon'=>'jmt.gif'), 366 'jmx' => array ('type'=>'text/xml', 'icon'=>'jmx.gif'), 367 'jpe' => array ('type'=>'image/jpeg', 'icon'=>'image.gif'), 368 'jpeg' => array ('type'=>'image/jpeg', 'icon'=>'image.gif'), 369 'jpg' => array ('type'=>'image/jpeg', 'icon'=>'image.gif'), 370 'jqz' => array ('type'=>'text/xml', 'icon'=>'jqz.gif'), 371 'js' => array ('type'=>'application/x-javascript', 'icon'=>'text.gif'), 372 'latex'=> array ('type'=>'application/x-latex', 'icon'=>'text.gif'), 373 'm' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 374 'mov' => array ('type'=>'video/quicktime', 'icon'=>'video.gif'), 375 'movie'=> array ('type'=>'video/x-sgi-movie', 'icon'=>'video.gif'), 376 'm3u' => array ('type'=>'audio/x-mpegurl', 'icon'=>'audio.gif'), 377 'mp3' => array ('type'=>'audio/mp3', 'icon'=>'audio.gif'), 378 'mp4' => array ('type'=>'video/mp4', 'icon'=>'video.gif'), 379 'mpeg' => array ('type'=>'video/mpeg', 'icon'=>'video.gif'), 380 'mpe' => array ('type'=>'video/mpeg', 'icon'=>'video.gif'), 381 'mpg' => array ('type'=>'video/mpeg', 'icon'=>'video.gif'), 382 383 'odt' => array ('type'=>'application/vnd.oasis.opendocument.text', 'icon'=>'odt.gif'), 384 'ott' => array ('type'=>'application/vnd.oasis.opendocument.text-template', 'icon'=>'odt.gif'), 385 'oth' => array ('type'=>'application/vnd.oasis.opendocument.text-web', 'icon'=>'odt.gif'), 386 'odm' => array ('type'=>'application/vnd.oasis.opendocument.text-master', 'icon'=>'odm.gif'), 387 'odg' => array ('type'=>'application/vnd.oasis.opendocument.graphics', 'icon'=>'odg.gif'), 388 'otg' => array ('type'=>'application/vnd.oasis.opendocument.graphics-template', 'icon'=>'odg.gif'), 389 'odp' => array ('type'=>'application/vnd.oasis.opendocument.presentation', 'icon'=>'odp.gif'), 390 'otp' => array ('type'=>'application/vnd.oasis.opendocument.presentation-template', 'icon'=>'odp.gif'), 391 'ods' => array ('type'=>'application/vnd.oasis.opendocument.spreadsheet', 'icon'=>'ods.gif'), 392 'ots' => array ('type'=>'application/vnd.oasis.opendocument.spreadsheet-template', 'icon'=>'ods.gif'), 393 'odc' => array ('type'=>'application/vnd.oasis.opendocument.chart', 'icon'=>'odc.gif'), 394 'odf' => array ('type'=>'application/vnd.oasis.opendocument.formula', 'icon'=>'odf.gif'), 395 'odb' => array ('type'=>'application/vnd.oasis.opendocument.database', 'icon'=>'odb.gif'), 396 'odi' => array ('type'=>'application/vnd.oasis.opendocument.image', 'icon'=>'odi.gif'), 397 398 'pct' => array ('type'=>'image/pict', 'icon'=>'image.gif'), 399 'pdf' => array ('type'=>'application/pdf', 'icon'=>'pdf.gif'), 400 'php' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 401 'pic' => array ('type'=>'image/pict', 'icon'=>'image.gif'), 402 'pict' => array ('type'=>'image/pict', 'icon'=>'image.gif'), 403 'png' => array ('type'=>'image/png', 'icon'=>'image.gif'), 404 'pps' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'powerpoint.gif'), 405 'ppt' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'powerpoint.gif'), 406 'pptx' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'pptx.gif'), 407 'pptm' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'pptm.gif'), 408 'potx' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'potx.gif'), 409 'potm' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'potm.gif'), 410 'ppam' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'ppam.gif'), 411 'ppsx' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'ppsx.gif'), 412 'ppsm' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'ppsm.gif'), 413 'ps' => array ('type'=>'application/postscript', 'icon'=>'pdf.gif'), 414 'qt' => array ('type'=>'video/quicktime', 'icon'=>'video.gif'), 415 'ra' => array ('type'=>'audio/x-realaudio', 'icon'=>'audio.gif'), 416 'ram' => array ('type'=>'audio/x-pn-realaudio', 'icon'=>'audio.gif'), 417 'rhb' => array ('type'=>'text/xml', 'icon'=>'xml.gif'), 418 'rm' => array ('type'=>'audio/x-pn-realaudio', 'icon'=>'audio.gif'), 419 'rtf' => array ('type'=>'text/rtf', 'icon'=>'text.gif'), 420 'rtx' => array ('type'=>'text/richtext', 'icon'=>'text.gif'), 421 'sh' => array ('type'=>'application/x-sh', 'icon'=>'text.gif'), 422 'sit' => array ('type'=>'application/x-stuffit', 'icon'=>'zip.gif'), 423 'smi' => array ('type'=>'application/smil', 'icon'=>'text.gif'), 424 'smil' => array ('type'=>'application/smil', 'icon'=>'text.gif'), 425 'sqt' => array ('type'=>'text/xml', 'icon'=>'xml.gif'), 426 'svg' => array ('type'=>'image/svg+xml', 'icon'=>'image.gif'), 427 'svgz' => array ('type'=>'image/svg+xml', 'icon'=>'image.gif'), 428 'swa' => array ('type'=>'application/x-director', 'icon'=>'flash.gif'), 429 'swf' => array ('type'=>'application/x-shockwave-flash', 'icon'=>'flash.gif'), 430 'swfl' => array ('type'=>'application/x-shockwave-flash', 'icon'=>'flash.gif'), 431 432 'sxw' => array ('type'=>'application/vnd.sun.xml.writer', 'icon'=>'odt.gif'), 433 'stw' => array ('type'=>'application/vnd.sun.xml.writer.template', 'icon'=>'odt.gif'), 434 'sxc' => array ('type'=>'application/vnd.sun.xml.calc', 'icon'=>'odt.gif'), 435 'stc' => array ('type'=>'application/vnd.sun.xml.calc.template', 'icon'=>'odt.gif'), 436 'sxd' => array ('type'=>'application/vnd.sun.xml.draw', 'icon'=>'odt.gif'), 437 'std' => array ('type'=>'application/vnd.sun.xml.draw.template', 'icon'=>'odt.gif'), 438 'sxi' => array ('type'=>'application/vnd.sun.xml.impress', 'icon'=>'odt.gif'), 439 'sti' => array ('type'=>'application/vnd.sun.xml.impress.template', 'icon'=>'odt.gif'), 440 'sxg' => array ('type'=>'application/vnd.sun.xml.writer.global', 'icon'=>'odt.gif'), 441 'sxm' => array ('type'=>'application/vnd.sun.xml.math', 'icon'=>'odt.gif'), 442 443 'tar' => array ('type'=>'application/x-tar', 'icon'=>'zip.gif'), 444 'tif' => array ('type'=>'image/tiff', 'icon'=>'image.gif'), 445 'tiff' => array ('type'=>'image/tiff', 'icon'=>'image.gif'), 446 'tex' => array ('type'=>'application/x-tex', 'icon'=>'text.gif'), 447 'texi' => array ('type'=>'application/x-texinfo', 'icon'=>'text.gif'), 448 'texinfo' => array ('type'=>'application/x-texinfo', 'icon'=>'text.gif'), 449 'tsv' => array ('type'=>'text/tab-separated-values', 'icon'=>'text.gif'), 450 'txt' => array ('type'=>'text/plain', 'icon'=>'text.gif'), 451 'wav' => array ('type'=>'audio/wav', 'icon'=>'audio.gif'), 452 'wmv' => array ('type'=>'video/x-ms-wmv', 'icon'=>'avi.gif'), 453 'asf' => array ('type'=>'video/x-ms-asf', 'icon'=>'avi.gif'), 454 'xdp' => array ('type'=>'application/pdf', 'icon'=>'pdf.gif'), 455 'xfd' => array ('type'=>'application/pdf', 'icon'=>'pdf.gif'), 456 'xfdf' => array ('type'=>'application/pdf', 'icon'=>'pdf.gif'), 457 'xls' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'excel.gif'), 458 'xlsx' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'xlsx.gif'), 459 'xlsm' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'xlsm.gif'), 460 'xltx' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'xltx.gif'), 461 'xltm' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'xltm.gif'), 462 'xlsb' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'xlsb.gif'), 463 'xlam' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'xlam.gif'), 464 'xml' => array ('type'=>'application/xml', 'icon'=>'xml.gif'), 465 'xsl' => array ('type'=>'text/xml', 'icon'=>'xml.gif'), 466 'zip' => array ('type'=>'application/zip', 'icon'=>'zip.gif') 467 ); 468 } 469 470 /** 471 * Obtains information about a filetype based on its extension. Will 472 * use a default if no information is present about that particular 473 * extension. 474 * @param string $element Desired information (usually 'icon' 475 * for icon filename or 'type' for MIME type) 476 * @param string $filename Filename we're looking up 477 * @return string Requested piece of information from array 478 */ 479 function mimeinfo($element, $filename) { 480 static $mimeinfo = null; 481 if (is_null($mimeinfo)) { 482 $mimeinfo = get_mimetypes_array(); 483 } 484 485 if (eregi('\.([a-z0-9]+)$', $filename, $match)) { 486 if (isset($mimeinfo[strtolower($match[1])][$element])) { 487 return $mimeinfo[strtolower($match[1])][$element]; 488 } else { 489 return $mimeinfo['xxx'][$element]; // By default 490 } 491 } else { 492 return $mimeinfo['xxx'][$element]; // By default 493 } 494 } 495 496 /** 497 * Obtains information about a filetype based on the MIME type rather than 498 * the other way around. 499 * @param string $element Desired information (usually 'icon') 500 * @param string $mimetype MIME type we're looking up 501 * @return string Requested piece of information from array 502 */ 503 function mimeinfo_from_type($element, $mimetype) { 504 static $mimeinfo; 505 $mimeinfo=get_mimetypes_array(); 506 507 foreach($mimeinfo as $values) { 508 if($values['type']==$mimetype) { 509 if(isset($values[$element])) { 510 return $values[$element]; 511 } 512 break; 513 } 514 } 515 return $mimeinfo['xxx'][$element]; // Default 516 } 517 518 /** 519 * Get information about a filetype based on the icon file. 520 * @param string $element Desired information (usually 'icon') 521 * @param string $icon Icon file path. 522 * @return string Requested piece of information from array 523 */ 524 function mimeinfo_from_icon($element, $icon) { 525 static $mimeinfo; 526 $mimeinfo=get_mimetypes_array(); 527 528 if (preg_match("/\/(.*)/", $icon, $matches)) { 529 $icon = $matches[1]; 530 } 531 $info = $mimeinfo['xxx'][$element]; // Default 532 foreach($mimeinfo as $values) { 533 if($values['icon']==$icon) { 534 if(isset($values[$element])) { 535 $info = $values[$element]; 536 } 537 //No break, for example for 'excel.gif' we don't want 'csv'! 538 } 539 } 540 return $info; 541 } 542 543 /** 544 * Obtains descriptions for file types (e.g. 'Microsoft Word document') from the 545 * mimetypes.php language file. 546 * @param string $mimetype MIME type (can be obtained using the mimeinfo function) 547 * @param bool $capitalise If true, capitalises first character of result 548 * @return string Text description 549 */ 550 function get_mimetype_description($mimetype,$capitalise=false) { 551 $result=get_string($mimetype,'mimetypes'); 552 // Surrounded by square brackets indicates that there isn't a string for that 553 // (maybe there is a better way to find this out?) 554 if(strpos($result,'[')===0) { 555 $result=get_string('document/unknown','mimetypes'); 556 } 557 if($capitalise) { 558 $result=ucfirst($result); 559 } 560 return $result; 561 } 562 563 /** 564 * Handles the sending of temporary file to user, download is forced. 565 * File is deleted after abort or succesful sending. 566 * @param string $path path to file, preferably from moodledata/temp/something; or content of file itself 567 * @param string $filename proposed file name when saving file 568 * @param bool $path is content of file 569 */ 570 function send_temp_file($path, $filename, $pathisstring=false) { 571 global $CFG; 572 573 // close session - not needed anymore 574 @session_write_close(); 575 576 if (!$pathisstring) { 577 if (!file_exists($path)) { 578 header('HTTP/1.0 404 not found'); 579 error(get_string('filenotfound', 'error'), $CFG->wwwroot.'/'); 580 } 581 // executed after normal finish or abort 582 @register_shutdown_function('send_temp_file_finished', $path); 583 } 584 585 //IE compatibiltiy HACK! 586 if (ini_get('zlib.output_compression')) { 587 ini_set('zlib.output_compression', 'Off'); 588 } 589 590 // if user is using IE, urlencode the filename so that multibyte file name will show up correctly on popup 591 if (check_browser_version('MSIE')) { 592 $filename = urlencode($filename); 593 } 594 595 $filesize = $pathisstring ? strlen($path) : filesize($path); 596 597 @header('Content-Disposition: attachment; filename='.$filename); 598 @header('Content-Length: '.$filesize); 599 if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431 600 @header('Cache-Control: max-age=10'); 601 @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); 602 @header('Pragma: '); 603 } else { //normal http - prevent caching at all cost 604 @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); 605 @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); 606 @header('Pragma: no-cache'); 607 } 608 @header('Accept-Ranges: none'); // Do not allow byteserving 609 610 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 611 if ($pathisstring) { 612 echo $path; 613 } else { 614 readfile_chunked($path); 615 } 616 617 die; //no more chars to output 618 } 619 620 /** 621 * Internal callnack function used by send_temp_file() 622 */ 623 function send_temp_file_finished($path) { 624 if (file_exists($path)) { 625 @unlink($path); 626 } 627 } 628 629 /** 630 * Handles the sending of file data to the user's browser, including support for 631 * byteranges etc. 632 * @param string $path Path of file on disk (including real filename), or actual content of file as string 633 * @param string $filename Filename to send 634 * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) 635 * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only 636 * @param bool $pathisstring If true (default false), $path is the content to send and not the pathname 637 * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin 638 * @param string $mimetype Include to specify the MIME type; leave blank to have it guess the type from $filename 639 */ 640 function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathisstring=false, $forcedownload=false, $mimetype='') { 641 global $CFG, $COURSE; 642 643 // MDL-11789, apply $CFG->filelifetime here 644 if ($lifetime === 'default') { 645 if (!empty($CFG->filelifetime)) { 646 $filetime = $CFG->filelifetime; 647 } else { 648 $filetime = 86400; 649 } 650 } 651 652 // Use given MIME type if specified, otherwise guess it using mimeinfo. 653 // IE, Konqueror and Opera open html file directly in browser from web even when directed to save it to disk :-O 654 // only Firefox saves all files locally before opening when content-disposition: attachment stated 655 $isFF = check_browser_version('Firefox', '1.5'); // only FF > 1.5 properly tested 656 $mimetype = ($forcedownload and !$isFF) ? 'application/x-forcedownload' : 657 ($mimetype ? $mimetype : mimeinfo('type', $filename)); 658 $lastmodified = $pathisstring ? time() : filemtime($path); 659 $filesize = $pathisstring ? strlen($path) : filesize($path); 660 661 /* - MDL-13949 662 //Adobe Acrobat Reader XSS prevention 663 if ($mimetype=='application/pdf' or mimeinfo('type', $filename)=='application/pdf') { 664 //please note that it prevents opening of pdfs in browser when http referer disabled 665 //or file linked from another site; browser caching of pdfs is now disabled too 666 if (!empty($_SERVER['HTTP_RANGE'])) { 667 //already byteserving 668 $lifetime = 1; // >0 needed for byteserving 669 } else if (empty($_SERVER['HTTP_REFERER']) or strpos($_SERVER['HTTP_REFERER'], $CFG->wwwroot)!==0) { 670 $mimetype = 'application/x-forcedownload'; 671 $forcedownload = true; 672 $lifetime = 0; 673 } else { 674 $lifetime = 1; // >0 needed for byteserving 675 } 676 } 677 */ 678 679 //IE compatibiltiy HACK! 680 if (ini_get('zlib.output_compression')) { 681 ini_set('zlib.output_compression', 'Off'); 682 } 683 684 //try to disable automatic sid rewrite in cookieless mode 685 @ini_set("session.use_trans_sid", "false"); 686 687 //do not put '@' before the next header to detect incorrect moodle configurations, 688 //error should be better than "weird" empty lines for admins/users 689 //TODO: should we remove all those @ before the header()? Are all of the values supported on all servers? 690 header('Last-Modified: '. gmdate('D, d M Y H:i:s', $lastmodified) .' GMT'); 691 692 // if user is using IE, urlencode the filename so that multibyte file name will show up correctly on popup 693 if (check_browser_version('MSIE')) { 694 $filename = rawurlencode($filename); 695 } 696 697 if ($forcedownload) { 698 @header('Content-Disposition: attachment; filename="'.$filename.'"'); 699 } else { 700 @header('Content-Disposition: inline; filename="'.$filename.'"'); 701 } 702 703 if ($lifetime > 0) { 704 @header('Cache-Control: max-age='.$lifetime); 705 @header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); 706 @header('Pragma: '); 707 708 if (empty($CFG->disablebyteserving) && !$pathisstring && $mimetype != 'text/plain' && $mimetype != 'text/html') { 709 710 @header('Accept-Ranges: bytes'); 711 712 if (!empty($_SERVER['HTTP_RANGE']) && strpos($_SERVER['HTTP_RANGE'],'bytes=') !== FALSE) { 713 // byteserving stuff - for acrobat reader and download accelerators 714 // see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 715 // inspired by: http://www.coneural.org/florian/papers/04_byteserving.php 716 $ranges = false; 717 if (preg_match_all('/(\d*)-(\d*)/', $_SERVER['HTTP_RANGE'], $ranges, PREG_SET_ORDER)) { 718 foreach ($ranges as $key=>$value) { 719 if ($ranges[$key][1] == '') { 720 //suffix case 721 $ranges[$key][1] = $filesize - $ranges[$key][2]; 722 $ranges[$key][2] = $filesize - 1; 723 } else if ($ranges[$key][2] == '' || $ranges[$key][2] > $filesize - 1) { 724 //fix range length 725 $ranges[$key][2] = $filesize - 1; 726 } 727 if ($ranges[$key][2] != '' && $ranges[$key][2] < $ranges[$key][1]) { 728 //invalid byte-range ==> ignore header 729 $ranges = false; 730 break; 731 } 732 //prepare multipart header 733 $ranges[$key][0] = "\r\n--".BYTESERVING_BOUNDARY."\r\nContent-Type: $mimetype\r\n"; 734 $ranges[$key][0] .= "Content-Range: bytes {$ranges[$key][1]}-{$ranges[$key][2]}/$filesize\r\n\r\n"; 735 } 736 } else { 737 $ranges = false; 738 } 739 if ($ranges) { 740 byteserving_send_file($path, $mimetype, $ranges); 741 } 742 } 743 } else { 744 /// Do not byteserve (disabled, strings, text and html files). 745 @header('Accept-Ranges: none'); 746 } 747 } else { // Do not cache files in proxies and browsers 748 if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431 749 @header('Cache-Control: max-age=10'); 750 @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); 751 @header('Pragma: '); 752 } else { //normal http - prevent caching at all cost 753 @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); 754 @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); 755 @header('Pragma: no-cache'); 756 } 757 @header('Accept-Ranges: none'); // Do not allow byteserving when caching disabled 758 } 759 760 if (empty($filter)) { 761 if ($mimetype == 'text/html' && !empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) { 762 //cookieless mode - rewrite links 763 @header('Content-Type: text/html'); 764 $path = $pathisstring ? $path : implode('', file($path)); 765 $path = sid_ob_rewrite($path); 766 $filesize = strlen($path); 767 $pathisstring = true; 768 } else if ($mimetype == 'text/plain') { 769 @header('Content-Type: Text/plain; charset=utf-8'); //add encoding 770 } else { 771 @header('Content-Type: '.$mimetype); 772 } 773 @header('Content-Length: '.$filesize); 774 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 775 if ($pathisstring) { 776 echo $path; 777 } else { 778 readfile_chunked($path); 779 } 780 } else { // Try to put the file through filters 781 if ($mimetype == 'text/html') { 782 $options = new object(); 783 $options->noclean = true; 784 $options->nocache = true; // temporary workaround for MDL-5136 785 $text = $pathisstring ? $path : implode('', file($path)); 786 787 $text = file_modify_html_header($text); 788 $output = format_text($text, FORMAT_HTML, $options, $COURSE->id); 789 if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) { 790 //cookieless mode - rewrite links 791 $output = sid_ob_rewrite($output); 792 } 793 794 @header('Content-Length: '.strlen($output)); 795 @header('Content-Type: text/html'); 796 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 797 echo $output; 798 // only filter text if filter all files is selected 799 } else if (($mimetype == 'text/plain') and ($filter == 1)) { 800 $options = new object(); 801 $options->newlines = false; 802 $options->noclean = true; 803 $text = htmlentities($pathisstring ? $path : implode('', file($path))); 804 $output = '<pre>'. format_text($text, FORMAT_MOODLE, $options, $COURSE->id) .'</pre>'; 805 if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) { 806 //cookieless mode - rewrite links 807 $output = sid_ob_rewrite($output); 808 } 809 810 @header('Content-Length: '.strlen($output)); 811 @header('Content-Type: text/html; charset=utf-8'); //add encoding 812 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 813 echo $output; 814 } else { // Just send it out raw 815 @header('Content-Length: '.$filesize); 816 @header('Content-Type: '.$mimetype); 817 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 818 if ($pathisstring) { 819 echo $path; 820 }else { 821 readfile_chunked($path); 822 } 823 } 824 } 825 die; //no more chars to output!!! 826 } 827 828 function get_records_csv($file, $table) { 829 global $CFG, $db; 830 831 if (!$metacolumns = $db->MetaColumns($CFG->prefix . $table)) { 832 return false; 833 } 834 835 if(!($handle = @fopen($file, 'r'))) { 836 error('get_records_csv failed to open '.$file); 837 } 838 839 $fieldnames = fgetcsv($handle, 4096); 840 if(empty($fieldnames)) { 841 fclose($handle); 842 return false; 843 } 844 845 $columns = array(); 846 847 foreach($metacolumns as $metacolumn) { 848 $ord = array_search($metacolumn->name, $fieldnames); 849 if(is_int($ord)) { 850 $columns[$metacolumn->name] = $ord; 851 } 852 } 853 854 $rows = array(); 855 856 while (($data = fgetcsv($handle, 4096)) !== false) { 857 $item = new stdClass; 858 foreach($columns as $name => $ord) { 859 $item->$name = $data[$ord]; 860 } 861 $rows[] = $item; 862 } 863 864 fclose($handle); 865 return $rows; 866 } 867 868 function put_records_csv($file, $records, $table = NULL) { 869 global $CFG, $db; 870 871 if (empty($records)) { 872 return true; 873 } 874 875 $metacolumns = NULL; 876 if ($table !== NULL && !$metacolumns = $db->MetaColumns($CFG->prefix . $table)) { 877 return false; 878 } 879 880 echo "x"; 881 882 if(!($fp = @fopen($CFG->dataroot.'/temp/'.$file, 'w'))) { 883 error('put_records_csv failed to open '.$file); 884 } 885 886 $proto = reset($records); 887 if(is_object($proto)) { 888 $fields_records = array_keys(get_object_vars($proto)); 889 } 890 else if(is_array($proto)) { 891 $fields_records = array_keys($proto); 892 } 893 else { 894 return false; 895 } 896 echo "x"; 897 898 if(!empty($metacolumns)) { 899 $fields_table = array_map(create_function('$a', 'return $a->name;'), $metacolumns); 900 $fields = array_intersect($fields_records, $fields_table); 901 } 902 else { 903 $fields = $fields_records; 904 } 905 906 fwrite($fp, implode(',', $fields)); 907 fwrite($fp, "\r\n"); 908 909 foreach($records as $record) { 910 $array = (array)$record; 911 $values = array(); 912 foreach($fields as $field) { 913 if(strpos($array[$field], ',')) { 914 $values[] = '"'.str_replace('"', '\"', $array[$field]).'"'; 915 } 916 else { 917 $values[] = $array[$field]; 918 } 919 } 920 fwrite($fp, implode(',', $values)."\r\n"); 921 } 922 923 fclose($fp); 924 return true; 925 } 926 927 928 /** 929 * Recursively delete the file or folder with path $location. That is, 930 * if it is a file delete it. If it is a folder, delete all its content 931 * then delete it. If $location does not exist to start, that is not 932 * considered an error. 933 * 934 * @param $location the path to remove. 935 */ 936 function fulldelete($location) { 937 if (is_dir($location)) { 938 $currdir = opendir($location); 939 while (false !== ($file = readdir($currdir))) { 940 if ($file <> ".." && $file <> ".") { 941 $fullfile = $location."/".$file; 942 if (is_dir($fullfile)) { 943 if (!fulldelete($fullfile)) { 944 return false; 945 } 946 } else { 947 if (!unlink($fullfile)) { 948 return false; 949 } 950 } 951 } 952 } 953 closedir($currdir); 954 if (! rmdir($location)) { 955 return false; 956 } 957 958 } else if (file_exists($location)) { 959 if (!unlink($location)) { 960 return false; 961 } 962 } 963 return true; 964 } 965 966 /** 967 * Improves memory consumptions and works around buggy readfile() in PHP 5.0.4 (2MB readfile limit). 968 */ 969 function readfile_chunked($filename, $retbytes=true) { 970 $chunksize = 1*(1024*1024); // 1MB chunks - must be less than 2MB! 971 $buffer = ''; 972 $cnt =0; 973 $handle = fopen($filename, 'rb'); 974 if ($handle === false) { 975 return false; 976 } 977 978 while (!feof($handle)) { 979 @set_time_limit(60*60); //reset time limit to 60 min - should be enough for 1 MB chunk 980 $buffer = fread($handle, $chunksize); 981 echo $buffer; 982 flush(); 983 if ($retbytes) { 984 $cnt += strlen($buffer); 985 } 986 } 987 $status = fclose($handle); 988 if ($retbytes && $status) { 989 return $cnt; // return num. bytes delivered like readfile() does. 990 } 991 return $status; 992 } 993 994 /** 995 * Send requested byterange of file. 996 */ 997 function byteserving_send_file($filename, $mimetype, $ranges) { 998 $chunksize = 1*(1024*1024); // 1MB chunks - must be less than 2MB! 999 $handle = fopen($filename, 'rb'); 1000 if ($handle === false) { 1001 die; 1002 } 1003 if (count($ranges) == 1) { //only one range requested 1004 $length = $ranges[0][2] - $ranges[0][1] + 1; 1005 @header('HTTP/1.1 206 Partial content'); 1006 @header('Content-Length: '.$length); 1007 @header('Content-Range: bytes '.$ranges[0][1].'-'.$ranges[0][2].'/'.filesize($filename)); 1008 @header('Content-Type: '.$mimetype); 1009 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 1010 $buffer = ''; 1011 fseek($handle, $ranges[0][1]); 1012 while (!feof($handle) && $length > 0) { 1013 @set_time_limit(60*60); //reset time limit to 60 min - should be enough for 1 MB chunk 1014 $buffer = fread($handle, ($chunksize < $length ? $chunksize : $length)); 1015 echo $buffer; 1016 flush(); 1017 $length -= strlen($buffer); 1018 } 1019 fclose($handle); 1020 die; 1021 } else { // multiple ranges requested - not tested much 1022 $totallength = 0; 1023 foreach($ranges as $range) { 1024 $totallength += strlen($range[0]) + $range[2] - $range[1] + 1; 1025 } 1026 $totallength += strlen("\r\n--".BYTESERVING_BOUNDARY."--\r\n"); 1027 @header('HTTP/1.1 206 Partial content'); 1028 @header('Content-Length: '.$totallength); 1029 @header('Content-Type: multipart/byteranges; boundary='.BYTESERVING_BOUNDARY); 1030 //TODO: check if "multipart/x-byteranges" is more compatible with current readers/browsers/servers 1031 while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite 1032 foreach($ranges as $range) { 1033 $length = $range[2] - $range[1] + 1; 1034 echo $range[0]; 1035 $buffer = ''; 1036 fseek($handle, $range[1]); 1037 while (!feof($handle) && $length > 0) { 1038 @set_time_limit(60*60); //reset time limit to 60 min - should be enough for 1 MB chunk 1039 $buffer = fread($handle, ($chunksize < $length ? $chunksize : $length)); 1040 echo $buffer; 1041 flush(); 1042 $length -= strlen($buffer); 1043 } 1044 } 1045 echo "\r\n--".BYTESERVING_BOUNDARY."--\r\n"; 1046 fclose($handle); 1047 die; 1048 } 1049 } 1050 1051 /** 1052 * add includes (js and css) into uploaded files 1053 * before returning them, useful for themes and utf.js includes 1054 * @param string text - text to search and replace 1055 * @return string - text with added head includes 1056 */ 1057 function file_modify_html_header($text) { 1058 // first look for <head> tag 1059 global $CFG; 1060 1061 $stylesheetshtml = ''; 1062 foreach ($CFG->stylesheets as $stylesheet) { 1063 $stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n"; 1064 } 1065 1066 $filters = explode(",", $CFG->textfilters); 1067 if (in_array('filter/mediaplugin', $filters)) { 1068 // this script is needed by most media filter plugins. 1069 $ufo = "\n".'<script type="text/javascript" src="'.$CFG->wwwroot.'/lib/ufo.js"></script>'."\n"; 1070 } else { 1071 $ufo = ''; 1072 } 1073 1074 preg_match('/\<head\>|\<HEAD\>/', $text, $matches); 1075 if ($matches) { 1076 $replacement = '<head>'.$ufo.$stylesheetshtml; 1077 $text = preg_replace('/\<head\>|\<HEAD\>/', $replacement, $text, 1); 1078 return $text; 1079 } 1080 1081 // if not, look for <html> tag, and stick <head> right after 1082 preg_match('/\<html\>|\<HTML\>/', $text, $matches); 1083 if ($matches) { 1084 // replace <html> tag with <html><head>includes</head> 1085 $replacement = '<html>'."\n".'<head>'.$ufo.$stylesheetshtml.'</head>'; 1086 $text = preg_replace('/\<html\>|\<HTML\>/', $replacement, $text, 1); 1087 return $text; 1088 } 1089 1090 // if not, look for <body> tag, and stick <head> before body 1091 preg_match('/\<body\>|\<BODY\>/', $text, $matches); 1092 if ($matches) { 1093 $replacement = '<head>'.$ufo.$stylesheetshtml.'</head>'."\n".'<body>'; 1094 $text = preg_replace('/\<body\>|\<BODY\>/', $replacement, $text, 1); 1095 return $text; 1096 } 1097 1098 // if not, just stick a <head> tag at the beginning 1099 $text = '<head>'.$ufo.$stylesheetshtml.'</head>'."\n".$text; 1100 return $text; 1101 } 1102 1103 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |