1<?php 2/** 3 * Smarty plugin 4 * 5 * @package Smarty 6 * @subpackage PluginsFunction 7 */ 8/** 9 * Smarty {fetch} plugin 10 * Type: function 11 * Name: fetch 12 * Purpose: fetch file, web or ftp data and display results 13 * 14 * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch} 15 * (Smarty online manual) 16 * @author Monte Ohrt <monte at ohrt dot com> 17 * 18 * @param array $params parameters 19 * @param Smarty_Internal_Template $template template object 20 * 21 * @throws SmartyException 22 * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable 23 */ 24function smarty_function_fetch($params, $template) 25{ 26 if (empty($params[ 'file' ])) { 27 trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE); 28 return; 29 } 30 // strip file protocol 31 if (stripos($params[ 'file' ], 'file://') === 0) { 32 $params[ 'file' ] = substr($params[ 'file' ], 7); 33 } 34 $protocol = strpos($params[ 'file' ], '://'); 35 if ($protocol !== false) { 36 $protocol = strtolower(substr($params[ 'file' ], 0, $protocol)); 37 } 38 if (isset($template->smarty->security_policy)) { 39 if ($protocol) { 40 // remote resource (or php stream, …) 41 if (!$template->smarty->security_policy->isTrustedUri($params[ 'file' ])) { 42 return; 43 } 44 } else { 45 // local file 46 if (!$template->smarty->security_policy->isTrustedResourceDir($params[ 'file' ])) { 47 return; 48 } 49 } 50 } 51 $content = ''; 52 if ($protocol === 'http') { 53 // http fetch 54 if ($uri_parts = parse_url($params[ 'file' ])) { 55 // set defaults 56 $host = $server_name = $uri_parts[ 'host' ]; 57 $timeout = 30; 58 $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*'; 59 $agent = 'Smarty Template Engine ' . Smarty::SMARTY_VERSION; 60 $referer = ''; 61 $uri = !empty($uri_parts[ 'path' ]) ? $uri_parts[ 'path' ] : '/'; 62 $uri .= !empty($uri_parts[ 'query' ]) ? '?' . $uri_parts[ 'query' ] : ''; 63 $_is_proxy = false; 64 if (empty($uri_parts[ 'port' ])) { 65 $port = 80; 66 } else { 67 $port = $uri_parts[ 'port' ]; 68 } 69 if (!empty($uri_parts[ 'user' ])) { 70 $user = $uri_parts[ 'user' ]; 71 } 72 if (!empty($uri_parts[ 'pass' ])) { 73 $pass = $uri_parts[ 'pass' ]; 74 } 75 // loop through parameters, setup headers 76 foreach ($params as $param_key => $param_value) { 77 switch ($param_key) { 78 case 'file': 79 case 'assign': 80 case 'assign_headers': 81 break; 82 case 'user': 83 if (!empty($param_value)) { 84 $user = $param_value; 85 } 86 break; 87 case 'pass': 88 if (!empty($param_value)) { 89 $pass = $param_value; 90 } 91 break; 92 case 'accept': 93 if (!empty($param_value)) { 94 $accept = $param_value; 95 } 96 break; 97 case 'header': 98 if (!empty($param_value)) { 99 if (!preg_match('![\w\d-]+: .+!', $param_value)) { 100 trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE); 101 return; 102 } else { 103 $extra_headers[] = $param_value; 104 } 105 } 106 break; 107 case 'proxy_host': 108 if (!empty($param_value)) { 109 $proxy_host = $param_value; 110 } 111 break; 112 case 'proxy_port': 113 if (!preg_match('!\D!', $param_value)) { 114 $proxy_port = (int)$param_value; 115 } else { 116 trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE); 117 return; 118 } 119 break; 120 case 'agent': 121 if (!empty($param_value)) { 122 $agent = $param_value; 123 } 124 break; 125 case 'referer': 126 if (!empty($param_value)) { 127 $referer = $param_value; 128 } 129 break; 130 case 'timeout': 131 if (!preg_match('!\D!', $param_value)) { 132 $timeout = (int)$param_value; 133 } else { 134 trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE); 135 return; 136 } 137 break; 138 default: 139 trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE); 140 return; 141 } 142 } 143 if (!empty($proxy_host) && !empty($proxy_port)) { 144 $_is_proxy = true; 145 $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout); 146 } else { 147 $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout); 148 } 149 if (!$fp) { 150 trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE); 151 return; 152 } else { 153 if ($_is_proxy) { 154 fputs($fp, 'GET ' . $params[ 'file' ] . " HTTP/1.0\r\n"); 155 } else { 156 fputs($fp, "GET $uri HTTP/1.0\r\n"); 157 } 158 if (!empty($host)) { 159 fputs($fp, "Host: $host\r\n"); 160 } 161 if (!empty($accept)) { 162 fputs($fp, "Accept: $accept\r\n"); 163 } 164 if (!empty($agent)) { 165 fputs($fp, "User-Agent: $agent\r\n"); 166 } 167 if (!empty($referer)) { 168 fputs($fp, "Referer: $referer\r\n"); 169 } 170 if (isset($extra_headers) && is_array($extra_headers)) { 171 foreach ($extra_headers as $curr_header) { 172 fputs($fp, $curr_header . "\r\n"); 173 } 174 } 175 if (!empty($user) && !empty($pass)) { 176 fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n"); 177 } 178 fputs($fp, "\r\n"); 179 while (!feof($fp)) { 180 $content .= fgets($fp, 4096); 181 } 182 fclose($fp); 183 $csplit = preg_split("!\r\n\r\n!", $content, 2); 184 $content = $csplit[ 1 ]; 185 if (!empty($params[ 'assign_headers' ])) { 186 $template->assign($params[ 'assign_headers' ], preg_split("!\r\n!", $csplit[ 0 ])); 187 } 188 } 189 } else { 190 trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE); 191 return; 192 } 193 } else { 194 $content = @file_get_contents($params[ 'file' ]); 195 if ($content === false) { 196 throw new SmartyException("{fetch} cannot read resource '" . $params[ 'file' ] . "'"); 197 } 198 } 199 if (!empty($params[ 'assign' ])) { 200 $template->assign($params[ 'assign' ], $content); 201 } else { 202 return $content; 203 } 204} 205