Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
1149 lines (1080 sloc) 38.3 KB
<?php /*
ocPortal
Copyright (c) ocProducts, 2004-2012
See text/EN/licence.txt for full licencing information.
NOTE TO PROGRAMMERS:
Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
**** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****
*/
/**
* @license http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
* @copyright ocProducts Ltd
* @package core
*/
/**
* Standard code module initialisation function.
*/
function init__files2()
{
global $HTTP_DOWNLOAD_MIME_TYPE,$HTTP_DOWNLOAD_SIZE,$HTTP_DOWNLOAD_URL,$HTTP_MESSAGE,$HTTP_MESSAGE_B,$HTTP_NEW_COOKIES,$HTTP_FILENAME,$HTTP_CHARSET;
$HTTP_DOWNLOAD_MIME_TYPE=NULL;
$HTTP_DOWNLOAD_SIZE=NULL;
$HTTP_DOWNLOAD_URL=NULL;
$HTTP_MESSAGE=NULL;
$HTTP_MESSAGE_B=NULL;
$HTTP_NEW_COOKIES=NULL;
$HTTP_FILENAME=NULL;
$HTTP_CHARSET=NULL;
}
/**
* Provides a hook for file-move synchronisation between mirrored servers. Called after any rename or move action.
*
* @param PATH File/directory name to move from (may be full or relative path)
* @param PATH File/directory name to move to (may be full or relative path)
*/
function _sync_file_move($old,$new)
{
global $FILE_BASE;
if (file_exists($FILE_BASE.'/data_custom/sync_script.php'))
{
require_once($FILE_BASE.'/data_custom/sync_script.php');
if (substr($old,0,strlen($FILE_BASE))==$FILE_BASE)
{
$old=substr($old,strlen($FILE_BASE));
}
if (substr($new,0,strlen($FILE_BASE))==$FILE_BASE)
{
$new=substr($new,strlen($FILE_BASE));
}
if (function_exists('master__sync_file_move')) master__sync_file_move($old,$new);
}
}
/**
* Delete all the contents of a directory, and any subdirectories of that specified directory (recursively).
*
* @param PATH The pathname to the directory to delete
* @param boolean Whether to preserve files there by default
* @param boolean Whether to just delete files
*/
function _deldir_contents($dir,$default_preserve=false,$just_files=false)
{
$current_dir=@opendir($dir);
if ($current_dir!==false)
{
while (false!==($entryname=readdir($current_dir)))
{
if ($default_preserve)
{
if ($entryname=='index.html') continue;
if ($entryname[0]=='.') continue;
if (in_array(str_replace(get_file_base().'/','',$dir).'/'.$entryname,array('uploads/banners/advertise_here.png','uploads/banners/donate.png','themes/map.ini','themes/default')))
continue;
}
if ((is_dir($dir.'/'.$entryname)) && ($entryname!='.') && ($entryname!='..'))
{
deldir_contents($dir.'/'.$entryname,$default_preserve,$just_files);
if (!$just_files)
{
$test=@rmdir($dir.'/'.$entryname);
if (($test===false) && (!$just_files/*tolerate weird locked dirs if we only need to delete files anyways*/)) warn_exit(do_lang_tempcode('WRITE_ERROR',escape_html($dir.'/'.$entryname)));
}
}
elseif (($entryname!='.') && ($entryname!='..') /*&& ($entryname!='index.html') && ($entryname!='.htaccess')*/)
{
$test=@unlink($dir.'/'.$entryname);
if ($test===false) intelligent_write_error($dir.'/'.$entryname);
}
sync_file($dir.'/'.$entryname);
}
closedir($current_dir);
}
}
/**
* Output data to a CSV file.
*
* @param array List of maps, each map representing a row
* @param ID_TEXT Filename to output
* @param boolean Whether to output CSV headers
* @param boolean Whether to output/exit when we're done instead of return
* @return string CSV data (we might not return though, depending on $exit)
*/
function make_csv($data,$filename='data.csv',$headers=true,$output_and_exit=true)
{
if ($headers)
{
header('Content-type: text/csv');
if (strstr(ocp_srv('HTTP_USER_AGENT'),'MSIE')!==false)
header('Content-Disposition: filename="'.str_replace(chr(13),'',str_replace(chr(10),'',addslashes($filename))).'"');
else
header('Content-Disposition: attachment; filename="'.str_replace(chr(13),'',str_replace(chr(10),'',addslashes($filename))).'"');
}
$out='';
foreach ($data as $i=>$line)
{
if ($i==0) // Header
{
foreach (array_keys($line) as $j=>$val)
{
if ($j!=0) $out.=',';
$out.='"'.str_replace('"','""',$val).'"';
}
$out.=chr(10);
}
// Main data
$j=0;
foreach ($line as $val)
{
if (is_null($val)) $val='';
elseif (!is_string($val)) $val=strval($val);
if ($j!=0) $out.=',';
$out.='"'.str_replace('"','""',$val).'"';
$j++;
}
$out.=chr(10);
}
if ($output_and_exit)
{
$GLOBALS['SCREEN_TEMPLATE_CALLED']='';
@ini_set('ocproducts.xss_detect','0');
exit($out);
}
return $out;
}
/**
* Find path to the PHP executable.
*
* @return PATH Path to PHP
*/
function find_php_path()
{
$search_dirs=array(
'/bin',
'/usr/bin',
'/usr/local/bin',
'/usr/php/bin',
'/usr/php/sbin',
'/usr/php5/bin',
'/usr/php5/sbin',
'/usr/php6/bin',
'/usr/php6/sbin',
'c:\\php',
'c:\\php5',
'c:\\php6',
'c:\\progra~1\\php',
'c:\\progra~1\\php5',
'c:\\progra~1\\php6',
);
$filenames=array(
'php.dSYM',
'php-cli',
'php5-cli',
'php6-cli',
'php',
'php5',
'php6',
'php-cgi',
'php5-cgi',
'php6-cgi',
);
foreach ($search_dirs as $dir)
{
foreach ($filenames as $file)
{
if (@file_exists($dir.'/'.$file)) break 2;
}
}
if (!@file_exists($dir.'/'.$file))
{
$php_path='php';
} else
{
$php_path=$dir.'/'.$file;
}
return $php_path;
}
/**
* Get the contents of a directory, recursively. It is assumed that the directory exists.
*
* @param PATH The path to search
* @param PATH The path we prepend to everything we find (intended to be used inside the recursion)
* @param boolean Whether to also get special files
* @param boolean Whether to recurse (if not, will return directories as files)
* @return array The contents of the directory
*/
function get_directory_contents($path,$rel_path='',$special_too=false,$recurse=true)
{
$out=array();
$d=opendir($path);
while (($file=readdir($d))!==false)
{
if (!$special_too)
{
if (should_ignore_file($rel_path.(($rel_path=='')?'':'/').$file,IGNORE_ACCESS_CONTROLLERS)) continue;
} elseif (($file=='.') || ($file=='..')) continue;
if ((is_file($path.'/'.$file)) || (!$recurse))
{
$out[]=$rel_path.(($rel_path=='')?'':'/').$file;
} elseif (is_dir($path.'/'.$file))
{
$out=array_merge($out,get_directory_contents($path.'/'.$file,$rel_path.(($rel_path=='')?'':'/').$file,$special_too,$recurse));
}
}
closedir($d);
return $out;
}
/**
* Get the size in bytes of a directory. It is assumed that the directory exists.
*
* @param PATH The path to search
* @return integer The extra space requested
*/
function get_directory_size($path)
{
$size=0;
$d=opendir($path);
while (($e=readdir($d))!==false)
{
if (($e=='.') || ($e=='..')) continue;
if (is_file($path.'/'.$e))
{
$size+=filesize($path.'/'.$e);
} else
{
$size+=get_directory_size($path.'/'.$e);
}
}
return $size;
}
/**
* Get the URL to the config option group for editing limits
*
* @return ?URLPATH The URL to the config option group for editing limits (NULL: no access)
*/
function get_upload_limit_config_url()
{
$config_url=NULL;
if (has_actual_page_access(get_member(),'admin_config'))
{
$_config_url=build_url(array('page'=>'admin_config','type'=>'category','id'=>'SITE'),get_module_zone('admin_config'));
$config_url=$_config_url->evaluate();
$config_url.='#group_UPLOAD';
}
return $config_url;
}
/**
* Get the maximum allowed upload filesize, as specified in the configuration
*
* @param ?MEMBER Member we consider quota for (NULL: do not consider quota)
* @param ?object Database connection to get quota from (NULL: site DB)
* @return integer The maximum allowed upload filesize, in bytes
*/
function get_max_file_size($source_member=NULL,$connection=NULL)
{
$possibilities=array();
$a=php_return_bytes(ini_get('upload_max_filesize'));
$b=php_return_bytes(ini_get('post_max_size'));
$c=intval(get_option('max_download_size'))*1024;
if (has_specific_permission(get_member(),'exceed_filesize_limit')) $c=0;
$d=0;
if ((!is_null($source_member)) && (!has_specific_permission(get_member(),'exceed_filesize_limit'))) // We'll be considering quota also
{
if (get_forum_type()=='ocf')
{
require_code('ocf_groups');
$daily_quota=ocf_get_member_best_group_property($source_member,'max_daily_upload_mb');
} else
{
$daily_quota=5; // 5 is a hard-coded default for non-OCF forums
}
if (is_null($connection)) $connection=$GLOBALS['SITE_DB'];
$_size_uploaded_today=$connection->query('SELECT SUM(a_file_size) AS the_answer FROM '.$connection->get_table_prefix().'attachments WHERE a_member_id='.strval((integer)$source_member).' AND a_add_time>'.strval(time()-60*60*24));
$size_uploaded_today=intval($_size_uploaded_today[0]['the_answer']);
$d=$daily_quota*1024*1024-$size_uploaded_today;
}
if ($a!=0) $possibilities[]=$a;
if ($b!=0) $possibilities[]=$b;
if ($c!=0) $possibilities[]=$c;
if ($d!=0) $possibilities[]=$d;
return min($possibilities);
}
/**
* Check uploaded file extensions for possible malicious intent, and if some is found, an error is put out, and the hackattack logged.
*
* @param string The filename
* @param boolean Whether to skip the server side security check
* @param ?string Delete this file if we have to exit (NULL: no file to delete)
* @param boolean Whether to allow errors without dying
* @return boolean Success status
*/
function check_extension($name,$skip_server_side_security_check=false,$file_to_delete=NULL,$accept_errors=false)
{
$ext=get_file_extension($name);
$_types=get_option('valid_types');
$types=array_flip(explode(',',$_types));
$_types='';
ksort($types);
if (!$skip_server_side_security_check)
{
if (!has_specific_permission(get_member(),'use_very_dangerous_comcode'))
{
unset($types['js']);
unset($types['swf']);
unset($types['html']);
unset($types['htm']);
unset($types['shtml']);
unset($types['svg']);
unset($types['xml']);
}
}
foreach (array_flip($types) as $val)
$_types.=$val.',';
$_types=substr($_types,0,strlen($_types)-1);
if (!$skip_server_side_security_check)
{
if (($ext=='py') || ($ext=='fcgi') || ($ext=='yaws') || ($ext=='dll') || ($ext=='cgi') || ($ext=='cfm') || ($ext=='vbs') || ($ext=='rhtml') || ($ext=='rb') || ($ext=='pl') || ($ext=='phtml') || ($ext=='php') || ($ext=='php3') || ($ext=='php4') || ($ext=='php5') || ($ext=='php6') || ($ext=='phtml') || ($ext=='aspx') || ($ext=='ashx') || ($ext=='asmx') || ($ext=='asx') || ($ext=='axd') || ($ext=='asp') || ($ext=='aspx') || ($ext=='jsp') || ($ext=='sh') || ($ext=='cgi') || (strtolower($name)=='.htaccess'))
{
if (!is_null($file_to_delete)) unlink($file_to_delete);
if ($accept_errors) return false;
log_hack_attack_and_exit('SCRIPT_UPLOAD_HACK');
}
}
if ($_types!='')
{
$types=explode(',',$_types);
foreach ($types as $val)
if (strtolower(trim($val))==$ext) return true;
if (!is_null($file_to_delete)) unlink($file_to_delete);
$message=do_lang_tempcode('INVALID_FILE_TYPE',escape_html($ext),escape_html(str_replace(',',', ',$_types)));
if (has_actual_page_access(get_member(),'admin_config'))
{
$_link=build_url(array('page'=>'admin_config','type'=>'category','id'=>'SECURITY'),get_module_zone('admin_config'));
$link=$_link->evaluate();
$link.='#group_UPLOAD';
$message=do_lang_tempcode('INVALID_FILE_TYPE_ADMIN',escape_html($ext),escape_html(str_replace(',',', ',$_types)),escape_html($link));
}
if ($accept_errors)
{
require_code('site');
attach_message($message,'warn');
return false;
} else
{
warn_exit($message);
}
}
return true;
}
/**
* Delete an uploaded file from disk, if it's URL has changed (i.e. it's been replaced, leaving a redundant disk file).
*
* @param string The path to the upload directory
* @param ID_TEXT The table name
* @param ID_TEXT The table field name
* @param mixed The table ID field name, or a map array
* @param mixed The table ID
* @param ?string The new URL to use (NULL: deleting without replacing: no change check)
*/
function delete_upload($upload_path,$table,$field,$id_field,$id,$new_url=NULL)
{
// Try and delete the file
if ($GLOBALS['FORUM_DRIVER']->is_staff(get_member())) // This isn't really a permission - more a failsafe in case there is a security hole. Staff can cleanup leftover files from the Cleanup module anyway
{
$where=is_array($id_field)?$id_field:array($id_field=>$id);
$url=$GLOBALS['SITE_DB']->query_value($table,$field,$where);
if ($url=='') return;
if ((is_null($new_url)) || (($url!=$new_url) && ($new_url!=STRING_MAGIC_NULL)))
{
if ((url_is_local($url)) && (substr($url,0,strlen($upload_path)+1)==$upload_path.'/'))
{
$count=$GLOBALS['SITE_DB']->query_value($table,'COUNT(*)',array($field=>$url));
if ($count<=1)
{
@unlink(get_custom_file_base().'/'.rawurldecode($url));
sync_file(rawurldecode($url));
}
}
}
}
}
/**
* Check bandwidth usage against page view ratio for shared hosting.
*
* @param integer The extra bandwidth requested
*/
function check_shared_bandwidth_usage($extra)
{
global $SITE_INFO;
if (array_key_exists('throttle_bandwidth_registered',$SITE_INFO))
{
$views_till_now=intval(get_value('page_views'));
$bandwidth_allowed=$SITE_INFO['throttle_bandwidth_registered'];
$total_bandwidth=intval(get_value('download_bandwidth'));
if ($bandwidth_allowed*1024*1024>=$total_bandwidth+$extra) return;
}
if (array_key_exists('throttle_bandwidth_complementary',$SITE_INFO))
{
// $timestamp_start=$SITE_INFO['custom_user_'].current_share_user();
// $days_till_now=(time()-$timestamp_start)/(24*60*60);
$views_till_now=intval(get_value('page_views'));
$bandwidth_allowed=$SITE_INFO['throttle_bandwidth_complementary']+$SITE_INFO['throttle_bandwidth_views_per_meg']*$views_till_now;
$total_bandwidth=intval(get_value('download_bandwidth'));
if ($bandwidth_allowed*1024*1024<$total_bandwidth+$extra)
critical_error('RELAY','The hosted user has exceeded their shared-hosting "bandwidth-limit to page-view" ratio. More pages must be viewed before this may be downloaded.');
}
}
/**
* Check disk space usage against page view ratio for shared hosting.
*
* @param integer The extra space in bytes requested
*/
function check_shared_space_usage($extra)
{
global $SITE_INFO;
if (array_key_exists('throttle_space_registered',$SITE_INFO))
{
$views_till_now=intval(get_value('page_views'));
$bandwidth_allowed=$SITE_INFO['throttle_space_registered'];
$total_space=get_directory_size(get_custom_file_base().'/uploads');
if ($bandwidth_allowed*1024*1024>=$total_space+$extra) return;
}
if (array_key_exists('throttle_space_complementary',$SITE_INFO))
{
// $timestamp_start=$SITE_INFO['custom_user_'].current_share_user();
// $days_till_now=(time()-$timestamp_start)/(24*60*60);
$views_till_now=intval(get_value('page_views'));
$space_allowed=$SITE_INFO['throttle_space_complementary']+$SITE_INFO['throttle_space_views_per_meg']*$views_till_now;
$total_space=get_directory_size(get_custom_file_base().'/uploads');
if ($space_allowed*1024*1024<$total_space+$extra)
critical_error('RELAY','The hosted user has exceeded their shared-hosting "disk-space to page-view" ratio. More pages must be viewed before this may be uploaded.');
}
}
/**
* Return the file in the URL by downloading it over HTTP. If a byte limit is given, it will only download that many bytes. It outputs warnings, returning NULL, on error.
*
* @param URLPATH The URL to download
* @param ?integer The number of bytes to download. This is not a guarantee, it is a minimum (NULL: all bytes)
* @range 1 max
* @param boolean Whether to throw an ocPortal error, on error
* @param boolean Whether to block redirects (returns NULL when found)
* @param string The user-agent to identify as
* @param ?array An optional array of POST parameters to send; if this is NULL, a GET request is used (NULL: none)
* @param ?array An optional array of cookies to send (NULL: none)
* @param ?string 'accept' header value (NULL: don't pass one)
* @param ?string 'accept-charset' header value (NULL: don't pass one)
* @param ?string 'accept-language' header value (NULL: don't pass one)
* @param ?resource File handle to write to (NULL: do not do that)
* @param ?string The HTTP referer (NULL: none)
* @param ?array A pair: authentication username and password (NULL: none)
* @param float The timeout
* @param boolean Whether to treat the POST parameters as a raw POST (rather than using MIME)
* @param ?array Files to send. Map between field to file path (NULL: none)
* @return ?string The data downloaded (NULL: error)
*/
function _http_download_file($url,$byte_limit=NULL,$trigger_error=true,$no_redirect=false,$ua='ocPortal',$post_params=NULL,$cookies=NULL,$accept=NULL,$accept_charset=NULL,$accept_language=NULL,$write_to_file=NULL,$referer=NULL,$auth=NULL,$timeout=6.0,$is_xml=false,$files=NULL)
{
$url=str_replace(' ','%20',$url);
// Prevent DOS loop attack
if (ocp_srv('HTTP_USER_AGENT')==$ua) $ua='ocP-recurse';
if (ocp_srv('HTTP_USER_AGENT')=='ocP-recurse') return NULL;
require_code('urls');
if (url_is_local($url)) $url=get_custom_base_url().'/'.$url;
if ((strpos($url,'/')!==false) && (strrpos($url,'/')<7)) $url.='/';
global $DOWNLOAD_LEVEL;
$DOWNLOAD_LEVEL++;
global $HTTP_DOWNLOAD_MIME_TYPE;
$HTTP_DOWNLOAD_MIME_TYPE=NULL;
global $HTTP_CHARSET;
$HTTP_CHARSET=NULL;
global $HTTP_DOWNLOAD_SIZE;
$HTTP_DOWNLOAD_SIZE=0;
global $HTTP_DOWNLOAD_URL;
$HTTP_DOWNLOAD_URL=$url;
global $HTTP_MESSAGE;
$HTTP_MESSAGE=NULL;
global $HTTP_MESSAGE_B;
$HTTP_MESSAGE_B=NULL;
global $HTTP_NEW_COOKIES;
if ($DOWNLOAD_LEVEL==0) $HTTP_NEW_COOKIES=array();
global $HTTP_FILENAME;
$HTTP_FILENAME=NULL;
if ($DOWNLOAD_LEVEL==8) return '';//critical_error('FILE_DOS',$url); // Prevent possible DOS attack
$url_parts=@parse_url($url);
if ($url_parts===false)
{
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL',escape_html($url)));
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL',escape_html($url));
$DOWNLOAD_LEVEL--;
$HTTP_MESSAGE='malconstructed-URL';
return NULL;
}
if (!array_key_exists('scheme',$url_parts)) $url_parts['scheme']='http';
$use_curl=(($url_parts['scheme']!='http') && (function_exists('curl_version'))) || ((function_exists('get_value')) && (get_value('prefer_curl')==='1'));
// Prep cookies and post data
if (!is_null($post_params))
{
if ($is_xml)
{
$_postdetails_params=$post_params[0];
} else
{
$_postdetails_params='';//$url_parts['scheme'].'://'.$url_parts['host'].$url2.'?';
$first=true;
if (array_keys($post_params)==array('_'))
{
$_postdetails_params=$post_params['_'];
} else
{
foreach ($post_params as $param_key=>$param_value)
{
if ($use_curl)
{
if (substr($param_value,0,1)=='@') $param_value=' @'.substr($param_value,1);
}
$_postdetails_params.=((array_key_exists('query',$url_parts)) || (!$first))?('&'.$param_key.'='.rawurlencode($param_value)):($param_key.'='.rawurlencode($param_value));
$first=false;
}
}
}
} else $_postdetails_params='';
if ((!is_null($cookies)) && (count($cookies)!=0))
{
$_cookies='';
$done_one_cookie=false;
foreach ($cookies as $key=>$val)
{
if ($done_one_cookie) $_cookies.='; ';
if (is_array($val))
{
foreach ($val as $key2=>$val2)
{
if (!is_string($key2)) $key2=strval($key2);
if ($done_one_cookie) $_cookies.='; ';
$_cookies.=$key.'['.$key2.']='.rawurlencode($val2);
$done_one_cookie=true;
}
} else
{
$_cookies.=$key.'='.rawurlencode($val);
}
$done_one_cookie=true;
}
}
if ($use_curl) // We'll have to try to use CURL
{
if (!is_null($files))
{
if (is_null($post_params)) $post_params=array();
foreach ($files as $upload_field=>$file_path)
{
$post_params[$upload_field]='@'.$file_path;
}
}
// CURL
if (function_exists('curl_version'))
if (function_exists('curl_init'))
if (function_exists('curl_setopt'))
if (function_exists('curl_exec'))
if (function_exists('curl_error'))
if (function_exists('curl_close'))
if (function_exists('curl_getinfo'))
if (($url_parts['scheme']=='https') || ($url_parts['scheme']=='http'))
{
$curl_version=curl_version();
if (((is_string($curl_version)) && (strpos($curl_version,'OpenSSL')!==false)) || ((is_array($curl_version)) && (array_key_exists('ssl_version',$curl_version))))
{
$ch=curl_init($url);
if (!is_null($post_params))
{
curl_setopt($ch,CURLOPT_POST,true);
if (is_null($files))
{
curl_setopt($ch,CURLOPT_POSTFIELDS,$_postdetails_params);
} else
{
curl_setopt($ch,CURLOPT_POSTFIELDS,$post_params);
}
}
if ((!is_null($cookies)) && (count($cookies)!=0)) curl_setopt($ch,CURLOPT_COOKIE,$_cookies);
$crt_path=get_file_base().'/data/curl-ca-bundle.crt';
curl_setopt($ch,CURLOPT_CAINFO,$crt_path);
curl_setopt($ch,CURLOPT_CAPATH,$crt_path);
//if (!$no_redirect) @curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); // May fail with safe mode, meaning we can't follow Location headers. But we can do better ourselves anyway and protect against file:// exploits.
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,intval($timeout));
curl_setopt($ch,CURLOPT_TIMEOUT,intval($timeout));
curl_setopt($ch,CURLOPT_USERAGENT,$ua);
$headers=array();
if ($is_xml) $headers[]='Content-Type: application/xml';
if (!is_null($accept)) $headers[]='Accept: '.rawurlencode($accept);
if (!is_null($accept_charset)) $headers[]='Accept-Charset: '.rawurlencode($accept_charset);
if (!is_null($accept_language)) $headers[]='Accept-Language: '.rawurlencode($accept_language);
if (is_null($files)) // Breaks file uploads for some reason
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_HEADER,true);
if (!is_null($auth)) curl_setopt($ch,CURLOPT_USERPWD,implode(':',$auth));
if (!is_null($referer))
curl_setopt($ch,CURLOPT_REFERER,$referer);
$proxy=get_value('proxy',NULL,true);
if ($proxy=='') $proxy=NULL;
if ((!is_null($proxy)) && ($url_parts['host']!='localhost') && ($url_parts['host']!='127.0.0.1'))
{
$port=get_value('proxy_port',NULL,true);
if (is_null($port)) $port='8080';
curl_setopt($ch, CURLOPT_PROXY,$proxy.':'.$port);
$proxy_user=get_value('proxy_user',NULL,true);
if (!is_null($proxy_user))
{
$proxy_password=get_value('proxy_password',NULL,true);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_user.':'.$proxy_password);
}
}
if (!is_null($byte_limit)) curl_setopt($ch,CURLOPT_RANGE,'0-'.strval(($byte_limit==0)?0:($byte_limit-1)));
$line=curl_exec($ch);
if ($line===false)
{
$error=curl_error($ch);
curl_close($ch);
if ($trigger_error)
warn_exit($error);
return NULL;
}
if (substr($line,0,25)=="HTTP/1.1 100 Continue\r\n\r\n") $line=substr($line,25);
if (substr($line,0,25)=="HTTP/1.0 100 Continue\r\n\r\n") $line=substr($line,25);
$HTTP_DOWNLOAD_MIME_TYPE=curl_getinfo($ch,CURLINFO_CONTENT_TYPE);
$HTTP_DOWNLOAD_SIZE=curl_getinfo($ch,CURLINFO_CONTENT_LENGTH_DOWNLOAD);
$HTTP_DOWNLOAD_URL=curl_getinfo($ch,CURLINFO_EFFECTIVE_URL);
$HTTP_MESSAGE=strval(curl_getinfo($ch,CURLINFO_HTTP_CODE));
if ($HTTP_MESSAGE=='206') $HTTP_MESSAGE='200'; // We don't care about partial-content return code, as ocP implementation gets ranges differently and we check '200' as a return result
if (strpos($HTTP_DOWNLOAD_MIME_TYPE,';')!==false)
{
$HTTP_CHARSET=substr($HTTP_DOWNLOAD_MIME_TYPE,8+strpos($HTTP_DOWNLOAD_MIME_TYPE,'charset='));
$HTTP_DOWNLOAD_MIME_TYPE=substr($HTTP_DOWNLOAD_MIME_TYPE,0,strpos($HTTP_DOWNLOAD_MIME_TYPE,';'));
}
curl_close($ch);
if (substr($line,0,strlen('HTTP/1.0 200 Connection Established'))=='HTTP/1.0 200 Connection Established') $line=substr($line,strpos($line,"\r\n\r\n")+4);
$pos=strpos($line,"\r\n\r\n");
if (substr($line,0,strlen('HTTP/1.1 100 '))=='HTTP/1.1 100 ' || substr($line,0,strlen('HTTP/1.0 100 '))=='HTTP/1.0 100 ') $pos=strpos($line,"\r\n\r\n",$pos+4);
if ($pos===false) $pos=strlen($line); else $pos+=4;
$lines=explode("\r\n",substr($line,0,$pos));
foreach ($lines as $lno=>$_line)
{
$_line.="\r\n";
$matches=array();
if (preg_match('#^Content-Disposition: [^;]*;\s*filename="([^"]*)"#i',$_line,$matches)!=0)
{
$HTTP_FILENAME=$matches[1];
}
if (preg_match("#^Set-Cookie: ([^\r\n=]*)=([^\r\n]*)\r\n#i",$_line,$matches)!=0)
{
$HTTP_NEW_COOKIES[trim(rawurldecode($matches[1]))]=trim($matches[2]);
}
if (preg_match("#^Location: (.*)\r\n#i",$_line,$matches)!=0)
{
if (is_null($HTTP_FILENAME)) $HTTP_FILENAME=basename($matches[1]);
if (strpos($matches[1],'://')===false) $matches[1]=qualify_url($matches[1],$url);
if ($matches[1]!=$url)
{
$bak=$HTTP_FILENAME;
$text=$no_redirect?NULL:_http_download_file($matches[1],$byte_limit,$trigger_error,false,$ua,NULL,$cookies,$accept,$accept_charset,$accept_language,$write_to_file);
if (is_null($HTTP_FILENAME)) $HTTP_FILENAME=$bak;
$DOWNLOAD_LEVEL--;
return $text;
}
}
}
$DOWNLOAD_LEVEL--;
return substr($line,$pos);
}
}
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL',escape_html($url)));
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL',escape_html($url));
$DOWNLOAD_LEVEL--;
$HTTP_MESSAGE='non-HTTP';
return NULL;
}
$errno=0;
$errstr='';
if ($url_parts['scheme']=='http')
{
if (!array_key_exists('host',$url_parts)) $url_parts['host']='127.0.0.1';
$connect_to=$url_parts['host'];
$base_url_parsed=parse_url(get_base_url());
if (!array_key_exists('host',$base_url_parsed)) $base_url_parsed['host']='127.0.0.1';
if (($base_url_parsed['host']==$connect_to) && (function_exists('get_option')) && (get_option('ip_forwarding')=='1')) // For cases where we have IP-forwarding, and a strong firewall (i.e. blocked to our own domain's IP by default)
{
$connect_to='127.0.0.1'; // Localhost can fail due to IP6
} elseif (preg_match('#(\s|,|^)gethostbyname(\s|$|,)#i',@ini_get('disable_functions'))==0) $connect_to=gethostbyname($connect_to); // for DNS cacheing
$proxy=function_exists('get_value')?get_value('proxy',NULL,true):NULL;
if ($proxy=='') $proxy=NULL;
if ((!is_null($proxy)) && ($connect_to!='localhost') && ($connect_to!='127.0.0.1'))
{
$proxy_port=get_value('proxy_port',NULL,true);
if (is_null($proxy_port)) $proxy_port='8080';
$mysock=@fsockopen($proxy,intval($proxy_port),$errno,$errstr,$timeout);
} else
{
$mysock=@fsockopen($connect_to,array_key_exists('port',$url_parts)?$url_parts['port']:80,$errno,$errstr,$timeout);
}
if (is_null($mysock)) $mysock=false; // For Quercus #4549
} else $mysock=false;
if ($mysock!==false)
{
if (function_exists('stream_set_timeout'))
{
if (@stream_set_timeout($mysock,intval($timeout))===false) $mysock=false;
} elseif (function_exists('socket_set_timeout'))
{
if (@socket_set_timeout($mysock,intval($timeout))===false) $mysock=false;
}
}
if ($mysock!==false)
{
$url2=array_key_exists('path',$url_parts)?$url_parts['path']:'/';
if (array_key_exists('query',$url_parts)) $url2.='?'.$url_parts['query'];
if ((!is_null($proxy)) && ($connect_to!='localhost') && ($connect_to!='127.0.0.1'))
{
$out='';
$out.=((is_null($post_params))?(($byte_limit===0)?'HEAD ':'GET '):'POST ').str_replace("\r",'',str_replace(chr(10),'',$url))." HTTP/1.1\r\n";
$proxy_user=get_value('proxy_user',NULL,true);
if (!is_null($proxy_user))
{
$proxy_password=get_value('proxy_password',NULL,true);
$out.='Proxy-Authorization: Basic '.base64_encode($proxy_user.':'.$proxy_password)."\r\n";
}
} else
{
$out=((is_null($post_params))?(($byte_limit===0)?'HEAD ':'GET '):'POST ').str_replace("\r",'',str_replace(chr(10),'',$url2))." HTTP/1.1\r\n";
}
$out.="Host: ".$url_parts['host']."\r\n";
if ((!is_null($cookies)) && (count($cookies)!=0)) $out.='Cookie: '.$_cookies."\r\n";
$out.="User-Agent: ".rawurlencode($ua)."\r\n";
if (!is_null($auth))
{
$out.="Authorization: Basic ".base64_encode(implode(':',$auth))."==\r\n";
}
if (!is_null($accept))
{
$out.="Accept: ".rawurlencode($accept)."\r\n";
} else
{
$out.="Accept: */*(\r\n"; // There's a mod_security rule that checks for this
}
if (!is_null($accept_charset))
{
$out.="Accept-Charset: ".rawurlencode($accept_charset)."\r\n";
}
if (!is_null($accept_language))
{
$out.="Accept-Language: ".rawurlencode($accept_language)."\r\n";
}
if (!is_null($referer))
$out.="Referer: ".rawurlencode($referer)."\r\n";
if ($_postdetails_params!='')
{
if ($is_xml)
{
$out.="Content-Type: application/xml\r\n";
$out.='Content-length: '.strval(strlen($_postdetails_params))."\r\n";
$out.="\r\n".$_postdetails_params."\r\n\r\n";
} else
{
if (is_null($files))
{
$out.='Content-type: application/x-www-form-urlencoded; charset='.get_charset()."\r\n";
$out.='Content-length: '.strval(strlen($_postdetails_params))."\r\n";
$out.="\r\n".$_postdetails_params."\r\n\r\n";
} else
{
$divider=uniqid('');
$out2='';
$out.='Content-type: multipart/form-data; boundary="--ocp'.$divider.'"; charset='.get_charset()."\r\n";
foreach ($post_params as $key=>$val)
{
$out2.='----ocp'.$divider."\r\n";
$out2.='Content-Disposition: form-data; name="'.urlencode($key).'"'."\r\n\r\n";
$out2.=$val."\r\n";
}
if (!is_null($files))
{
foreach ($files as $upload_field=>$file_path)
{
$out2.='----ocp'.$divider."\r\n";
$out2.='Content-Disposition: form-data; name="'.urlencode($upload_field).'"; filename="'.urlencode(basename($file_path)).'"'."\r\n";
$out2.='Content-Type: application/octet-stream'."\r\n\r\n";
$out2.=file_get_contents($file_path)."\r\n";
}
}
$out2.='----ocp'.$divider."--\r\n";
$out.='Content-length: '.strval(strlen($out2))."\r\n";
$out.="\r\n".$out2;
}
}
}
$out.="Connection: Close\r\n\r\n";
@fwrite($mysock,$out);
$data_started=false;
$input='';
$input_len=0;
$first_fail_time=mixed();
$chunked=false;
$buffer_unprocessed='';
while (($chunked) || (!@feof($mysock))) // @'d because socket might have died. If so fread will will return false and hence we'll break
{
$line=@fread($mysock,(($chunked) && (strlen($buffer_unprocessed)>10))?10:1024);
if ($line===false)
{
if ((!$chunked) || ($buffer_unprocessed=='')) break;
$line='';
}
if ($line=='')
{
if (!is_null($first_fail_time))
{
if ($first_fail_time<time()-5) break;
} else $first_fail_time=time();
} else $first_fail_time=NULL;
if ($data_started)
{
$line=$buffer_unprocessed.$line;
$buffer_unprocessed='';
if ($chunked)
{
$matches=array();
if (preg_match('#^(\r\n)?([a-f\d]+) *(;[^\r\n]*)?\r\n(.*)$#is',$line,$matches)!=0)
{
$amount_wanted=hexdec($matches[2]);
if (strlen($matches[4])<$amount_wanted) // Chunk was more than what we grabbed, so we need to iterate more to parse
{
$buffer_unprocessed=$line;
continue;
}
$buffer_unprocessed=substr($matches[4],$amount_wanted); // May be some more extra read
$line=substr($matches[4],0,$amount_wanted);
if ($line=='')
{
break;
}
} else
{
// Should not happen :S
}
}
if (is_null($write_to_file)) $input.=$line; else fwrite($write_to_file,$line);
$input_len+=strlen($line);
if ((!is_null($byte_limit)) && ($input_len>=$byte_limit))
{
$input=substr($input,0,$byte_limit);
break;
}
}
elseif ($line!='')
{
$old_line=$line;
$lines=explode("\r\n",$line);
$tally=0;
foreach ($lines as $lno=>$line)
{
$line.="\r\n";
$tally+=strlen($line);
$matches=array();
if (preg_match("#Transfer-Encoding: chunked\r\n#i",$line,$matches)!=0)
{
$chunked=true;
}
if (preg_match("#Content-Disposition: [^\r\n]*filename=\"([^;\r\n]*)\"\r\n#i",$line,$matches)!=0)
{
$HTTP_FILENAME=$matches[1];
}
if (preg_match("#^Set-Cookie: ([^\r\n=]*)=([^\r\n]*)\r\n#i",$line,$matches)!=0)
{
$HTTP_NEW_COOKIES[trim(rawurldecode($matches[1]))]=trim($matches[2]);
}
if (preg_match("#^Content-Length: ([^;\r\n]*)\r\n#i",$line,$matches)!=0)
{
$HTTP_DOWNLOAD_SIZE=intval($matches[1]);
}
if (preg_match("#^Content-Type: ([^;\r\n]*)(;[^\r\n]*)?\r\n#i",$line,$matches)!=0)
{
$HTTP_DOWNLOAD_MIME_TYPE=$matches[1];
if (array_key_exists(2,$matches))
{
$_ct_more=explode(';',str_replace(' ','',trim($matches[2])));
foreach ($_ct_more as $ct_more)
{
$ct_bits=explode('=',$ct_more,2);
if ((count($ct_bits)==2) && (strtolower($ct_bits[0])=='charset'))
{
$HTTP_CHARSET=trim($ct_bits[1]);
}
}
}
}
if (preg_match("#^Refresh: (\d*);(.*)\r\n#i",$line,$matches)!=0)
{
if (is_null($HTTP_FILENAME)) $HTTP_FILENAME=basename($matches[1]);
@fclose($mysock);
if (strpos($matches[1],'://')===false) $matches[1]=qualify_url($matches[1],$url);
$bak=$HTTP_FILENAME;
$text=$no_redirect?NULL:_http_download_file($matches[2],$byte_limit,$trigger_error,false,$ua,NULL,$cookies,$accept,$accept_charset,$accept_language,$write_to_file);
if (is_null($HTTP_FILENAME)) $HTTP_FILENAME=$bak;
$DOWNLOAD_LEVEL--;
return $text;
}
if (preg_match("#^Location: (.*)\r\n#i",$line,$matches)!=0)
{
if (is_null($HTTP_FILENAME)) $HTTP_FILENAME=basename($matches[1]);
@fclose($mysock);
if (strpos($matches[1],'://')===false) $matches[1]=qualify_url($matches[1],$url);
if ($matches[1]!=$url)
{
$bak=$HTTP_FILENAME;
$text=$no_redirect?NULL:_http_download_file($matches[1],$byte_limit,$trigger_error,false,$ua,NULL,$cookies,$accept,$accept_charset,$accept_language,$write_to_file);
if (is_null($HTTP_FILENAME)) $HTTP_FILENAME=$bak;
$DOWNLOAD_LEVEL--;
return $text;
}
}
if (preg_match("#HTTP/(\d*\.\d*) (\d*) #",$line,$matches)!=0)
{
// 200 = Ok
// 301/302 = Redirected: Not good, we should not be here
// 401 = Unauthorized
// 403 = Forbidden
// 404 = Not found
// 500 = Internal server error
$HTTP_MESSAGE=$matches[2];
switch ($matches[2])
{
case '302':
case '301':
// We'll expect a location header
break;
case '200':
// Good
break;
case '401':
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED',escape_html($url)));
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED',escape_html($url));
@fclose($mysock);
$HTTP_DOWNLOAD_MIME_TYPE='security';
$DOWNLOAD_LEVEL--;
return NULL;
case '403':
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED',escape_html($url)));
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED',escape_html($url));
@fclose($mysock);
$HTTP_DOWNLOAD_MIME_TYPE='security';
$DOWNLOAD_LEVEL--;
return NULL;
case '404':
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_NOT_FOUND',escape_html($url)));
@fclose($mysock);
$DOWNLOAD_LEVEL--;
return NULL;
case '500':
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_SERVER_ERROR',escape_html($url)));
@fclose($mysock);
$DOWNLOAD_LEVEL--;
return NULL;
default:
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNKNOWN',escape_html($url)));
}
}
if ($line=="\r\n")
{
$data_started=true;
$input_len+=max(0,strlen($old_line)-$tally);
$buffer_unprocessed=substr($old_line,$tally);
if ($buffer_unprocessed===false) $buffer_unprocessed='';
break;
}
}
}
}
// Process any non-chunked extra buffer (chunked would have been handled in main loop)
if (!$chunked)
{
if ($buffer_unprocessed!='')
{
if (is_null($write_to_file)) $input.=$buffer_unprocessed; else fwrite($write_to_file,$buffer_unprocessed);
$input_len+=strlen($line);
if ((!is_null($byte_limit)) && ($input_len>=$byte_limit))
{
$input=substr($input,0,$byte_limit);
}
}
}
@fclose($mysock);
if (!$data_started)
{
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER',escape_html($url)));
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER',escape_html($url));
$DOWNLOAD_LEVEL--;
$HTTP_MESSAGE='no-data';
return NULL;
}
$size_expected=$HTTP_DOWNLOAD_SIZE;
if (!is_null($byte_limit))
{
if ($byte_limit<$HTTP_DOWNLOAD_SIZE)
$size_expected=$byte_limit;
}
if ($input_len<$size_expected)
{
if ($trigger_error)
warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_CUT_SHORT',escape_html($url),escape_html(integer_format($size_expected)),escape_html(integer_format($input_len))));
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_CUT_SHORT',escape_html($url),escape_html(integer_format($size_expected)),escape_html(integer_format($input_len)));
$DOWNLOAD_LEVEL--;
$HTTP_MESSAGE='short-data';
return $input;
}
$DOWNLOAD_LEVEL--;
return $input;
} else
{
if (($errno!=110) && (($errno!=10060) || (@ini_get('default_socket_timeout')=='1')) && (is_null($post_params)))
{
// Perhaps fsockopen is restricted... try fread/file_get_contents
@ini_set('allow_url_fopen','1');
$timeout_before=@ini_get('default_socket_timeout');
@ini_set('default_socket_timeout',strval(intval($timeout)));
if (is_null($byte_limit))
{
$read_file=@file_get_contents($url);
} else
{
$_read_file=@fopen($url,'rb');
if ($_read_file!==false)
{
$read_file='';
while ((!feof($_read_file)) && (strlen($read_file)<$byte_limit)) $read_file.=fread($_read_file,1024);
fclose($_read_file);
} else $read_file=false;
}
@ini_set('allow_url_fopen','0');
@ini_set('default_socket_timeout',$timeout_before);
if ($read_file!==false)
{
$DOWNLOAD_LEVEL--;
return $read_file;
}
}
if ($trigger_error)
{
$error=do_lang_tempcode('_HTTP_DOWNLOAD_NO_SERVER',escape_html($url),escape_html($errstr));
warn_exit($error);
}
else $HTTP_MESSAGE_B=do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER',escape_html($url));
$DOWNLOAD_LEVEL--;
$HTTP_MESSAGE='could not connect to host ('.$errstr.')';
return NULL;
}
}
Something went wrong with that request. Please try again.