X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=boot.php;h=cdb1b35edb8d2bdec0d0f080cd401055cba7d07b;hb=6a3815e751b013d2fba1e1de6df89566f971e39c;hp=786ebdee68a0595215b5189863c632fd98e4ecd2;hpb=511c761fec572a093e833541968635ca011cb71e;p=friendica.git diff --git a/boot.php b/boot.php index 786ebdee68..cdb1b35edb 100644 --- a/boot.php +++ b/boot.php @@ -2,12 +2,20 @@ set_time_limit(0); -define ( 'BUILD_ID', 1008 ); +define ( 'BUILD_ID', 1017 ); define ( 'DFRN_PROTOCOL_VERSION', '2.0' ); define ( 'EOL', "
\r\n" ); define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' ); +// log levels + +define ( 'LOGGER_NORMAL', 0 ); +define ( 'LOGGER_TRACE', 1 ); +define ( 'LOGGER_DEBUG', 2 ); +define ( 'LOGGER_DATA', 3 ); +define ( 'LOGGER_ALL', 4 ); + // registration policy define ( 'REGISTER_CLOSED', 0 ); @@ -52,9 +60,13 @@ define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' ); define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' ); define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' ); define ( 'NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/' ); -define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/'); -define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env'); -define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe'); +define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' ); +define ( 'NAMESPACE_MEDIA', 'http://purl.org/syndication/atommedia' ); +define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env' ); +define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe' ); +define ( 'NAMESPACE_GEORSS', 'http://www.georss.org/georss' ); +define ( 'NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0' ); +define ( 'NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from' ); // activity stream defines @@ -63,8 +75,11 @@ define ( 'ACTIVITY_DISLIKE', NAMESPACE_DFRN . '/dislike' ); define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_DFRN . '/heart' ); define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' ); +define ( 'ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow' ); +define ( 'ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'unfollow' ); define ( 'ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post' ); define ( 'ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update' ); +define ( 'ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag' ); define ( 'ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment' ); define ( 'ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note' ); @@ -115,6 +130,7 @@ class App { private $db; private $curl_code; + private $curl_headers; function __construct() { @@ -122,17 +138,17 @@ class App { $this->page = array(); $this->pager= array(); - $this->scheme = ((isset($_SERVER['HTTPS']) - && ($_SERVER['HTTPS'])) ? 'https' : 'http' ); - $this->hostname = str_replace('www.','', - $_SERVER['SERVER_NAME']); - set_include_path("include/$this->hostname" - . PATH_SEPARATOR . 'include' - . PATH_SEPARATOR . '.' ); + $this->scheme = ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'])) ? 'https' : 'http' ); + + if(x($_SERVER,'SERVER_NAME')) + $this->hostname = $_SERVER['SERVER_NAME']; - if(substr($_SERVER['QUERY_STRING'],0,2) == "q=") + set_include_path("include/$this->hostname" . PATH_SEPARATOR . 'include' . PATH_SEPARATOR . '.' ); + + if((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'],0,2) === "q=") $_SERVER['QUERY_STRING'] = substr($_SERVER['QUERY_STRING'],2); - $this->cmd = trim($_GET['q'],'/'); + if(x($_GET,'q')) + $this->cmd = trim($_GET['q'],'/'); $this->argv = explode('/',$this->cmd); @@ -147,6 +163,7 @@ class App { if($this->cmd === '.well-known/host-meta') require_once('include/hostxrd.php'); + $this->pager['page'] = ((x($_GET,'page')) ? $_GET['page'] : 1); $this->pager['itemspage'] = 50; $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage']; @@ -157,9 +174,7 @@ class App { if(strlen($this->baseurl)) return $this->baseurl; - $this->baseurl = (($ssl) ? 'https' : $this->scheme) . "://" . $this->hostname - . ((isset($this->path) && strlen($this->path)) - ? '/' . $this->path : '' ); + $this->baseurl = (($ssl) ? 'https' : $this->scheme) . "://" . $this->hostname . ((isset($this->path) && strlen($this->path)) ? '/' . $this->path : '' ); return $this->baseurl; } @@ -177,7 +192,7 @@ class App { } function set_path($p) { - $this->path = ltrim(trim($p),'/'); + $this->path = trim(trim($p),'/'); } function get_path() { @@ -209,6 +224,15 @@ class App { return $this->curl_code; } + function set_curl_headers($headers) { + $this->curl_headers = $headers; + } + + function get_curl_headers() { + return $this->curl_headers; + } + + }} // retrieve the App structure @@ -332,10 +356,10 @@ function load_translation_table($lang) { if(! function_exists('t')) { function t($s) { - + $a = get_app(); - if($a->strings[$s]) + if(x($a->strings,$s)) return $a->strings[$s]; return $s; }} @@ -344,15 +368,19 @@ function t($s) { // results. if(! function_exists('fetch_url')) { -function fetch_url($url,$binary = false) { +function fetch_url($url,$binary = false, &$redirects = 0) { $ch = curl_init($url); - if(! $ch) return false; + if(($redirects > 8) || (! $ch)) + return false; - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true); - curl_setopt($ch, CURLOPT_MAXREDIRS,8); + curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); + + $curl_time = intval(get_config('system','curl_timeout')); + if($curl_time) + curl_setopt($ch, CURLOPT_TIMEOUT, $curl_time); + // by default we will allow self-signed certs // but you can override this @@ -371,26 +399,53 @@ function fetch_url($url,$binary = false) { curl_setopt($ch, CURLOPT_BINARYTRANSFER,1); $s = curl_exec($ch); - $info = curl_getinfo($ch); + + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $header = substr($s,0,strpos($s,"\r\n\r\n")); + if(stristr($header,'100') && (strlen($header) < 30)) { + // 100 Continue has two headers, get the real one + $s = substr($s,strlen($header)+4); + $header = substr($s,0,strpos($s,"\r\n\r\n")); + } + if($http_code == 301 || $http_code == 302 || $http_code == 303) { + $matches = array(); + preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches); + $url = trim(array_pop($matches)); + $url_parsed = parse_url($url); + if (isset($url_parsed)) { + $redirects++; + return fetch_url($url,$binary,$redirects); + } + } $a = get_app(); - $a->set_curl_code($info['http_code']); + $a->set_curl_code($http_code); + $body = substr($s,strlen($header)+4); + $a->set_curl_headers($header); + curl_close($ch); - return($s); + return($body); }} // post request to $url. $params is an array of post variables. if(! function_exists('post_url')) { -function post_url($url,$params) { +function post_url($url,$params, $headers = null, &$redirects = 0) { $ch = curl_init($url); - if(! $ch) return false; + if(($redirects > 8) || (! $ch)) + return false; - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true); - curl_setopt($ch, CURLOPT_MAXREDIRS,8); + curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); curl_setopt($ch, CURLOPT_POST,1); curl_setopt($ch, CURLOPT_POSTFIELDS,$params); + + $curl_time = intval(get_config('system','curl_timeout')); + if($curl_time) + curl_setopt($ch, CURLOPT_TIMEOUT, $curl_time); + + if(is_array($headers)) + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + $check_cert = get_config('system','verifyssl'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false)); $prx = get_config('system','proxy'); @@ -403,11 +458,31 @@ function post_url($url,$params) { } $s = curl_exec($ch); - $info = curl_getinfo($ch); + + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $header = substr($s,0,strpos($s,"\r\n\r\n")); + if(stristr($header,'100') && (strlen($header) < 30)) { + // 100 Continue has two headers, get the real one + $s = substr($s,strlen($header)+4); + $header = substr($s,0,strpos($s,"\r\n\r\n")); + } + if($http_code == 301 || $http_code == 302 || $http_code == 303) { + $matches = array(); + preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches); + $url = trim(array_pop($matches)); + $url_parsed = parse_url($url); + if (isset($url_parsed)) { + $redirects++; + return post_url($url,$binary,$headers,$redirects); + } + } $a = get_app(); - $a->set_curl_code($info['http_code']); + $a->set_curl_code($http_code); + $body = substr($s,strlen($header)+4); + $a->set_curl_headers($header); + curl_close($ch); - return($s); + return($body); }} // random hash, 64 chars @@ -553,8 +628,10 @@ function goaway($s) { if(! function_exists('xml_status')) { function xml_status($st, $message = '') { - if(strlen($message)) - $xml_message = "\t" . xmlify($message) . "\r\n"; + $xml_message = ((strlen($message)) ? "\t" . xmlify($message) . "\r\n" : ''); + + if($st) + logger('xml_status returning non_zero: ' . $st . " message=" . $message); header( "Content-type: text/xml" ); echo ''."\r\n"; @@ -630,7 +707,7 @@ function xmlify($str) { $buffer .= '>'; break; case "\n" : - $buffer .= ' '; + $buffer .= "\n"; break; default : $buffer .= $char; @@ -671,7 +748,7 @@ function hex2bin($s) { if(! function_exists('paginate')) { function paginate(&$a) { $o = ''; - $stripped = ereg_replace("(&page=[0-9]*)","",$_SERVER['QUERY_STRING']); + $stripped = preg_replace('/(&page=[0-9]*)/','',$_SERVER['QUERY_STRING']); $stripped = str_replace('q=','',$stripped); $stripped = trim($stripped,'/'); $url = $a->get_baseurl() . '/' . $stripped; @@ -890,6 +967,7 @@ function webfinger_dfrn($s) { return $s; } $links = webfinger($s); + logger('webfinger_dfrn: ' . $s . ':' . print_r($links,true), LOGGER_DATA); if(count($links)) { foreach($links as $link) if($link['@attributes']['rel'] === NAMESPACE_DFRN) @@ -914,12 +992,13 @@ function webfinger($s) { } if(strlen($host)) { $tpl = fetch_lrdd_template($host); + logger('webfinger: lrdd template: ' . $tpl); if(strlen($tpl)) { - $pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl); + $pxrd = str_replace('{uri}', urlencode('acct:'.$s), $tpl); $links = fetch_xrd_links($pxrd); if(! count($links)) { - // try without the double slashes - $pxrd = str_replace('{uri}', urlencode('acct:'.$s), $tpl); + // try with double slashes + $pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl); $links = fetch_xrd_links($pxrd); } return $links; @@ -928,6 +1007,54 @@ function webfinger($s) { return array(); }} +if(! function_exists('lrdd')) { +function lrdd($uri) { + + $a = get_app(); + + if(strstr($uri,'@')) { + return(webfinger($uri)); + } + else { + $html = fetch_url($uri); + $headers = $a->get_curl_headers(); + $lines = explode("\n",$headers); + if(count($lines)) { + foreach($lines as $line) { + // TODO alter the following regex to support multiple relations (space separated) + if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) { + $link = $matches[1]; + break; + } + } + } + if(! isset($link)) { + // parse the page of the supplied URL looking for rel links + + require_once('library/HTML5/Parser.php'); + $dom = HTML5_Parser::parse($html); + + if($dom) { + $items = $dom->getElementsByTagName('link'); + + foreach($items as $item) { + $x = $item->getAttribute('rel'); + if($x == "lrdd") { + $link = $item->getAttribute('href'); + break; + } + } + } + } + + if(isset($link)) + return(fetch_xrd_links($link)); + } + return array(); +}} + + + // Given a host name, locate the LRDD template from that // host. Returns the LRDD template or an empty string on // error/failure. @@ -954,9 +1081,12 @@ function fetch_lrdd_template($host) { if(! function_exists('fetch_xrd_links')) { function fetch_xrd_links($url) { + $xml = fetch_url($url); if (! $xml) return array(); + + logger('fetch_xrd_links: ' . $xml, LOGGER_DATA); $h = simplexml_load_string($xml); $arr = convert_xml_element_to_array($h); @@ -1023,13 +1153,6 @@ function photo_new_resource() { }} -// Returns logged in user ID - -if(! function_exists('get_uid')) { -function get_uid() { - return local_user(); -}} - // Take a URL from the wild, prepend http:// if necessary // and check DNS to see if it's real // return true if it's OK, false if something is wrong with it @@ -1040,13 +1163,25 @@ function validate_url(&$url) { $url = 'http://' . $url; $h = parse_url($url); - if(! $h) { - return false; + if(($h) && (checkdnsrr($h['host'], 'ANY'))) { + return true; } - if(! checkdnsrr($h['host'], 'ANY')) { + return false; +}} + +// checks that email is an actual resolvable internet address + +if(! function_exists('validate_email')) { +function validate_email($addr) { + + if(! strpos($addr,'@')) return false; + $h = substr($addr,strpos($addr,'@') + 1); + + if(($h) && (checkdnsrr($h, 'ANY'))) { + return true; } - return true; + return false; }} // Check $url against our list of allowed sites, @@ -1134,6 +1269,7 @@ function allowed_email($email) { if(! function_exists('format_like')) { function format_like($cnt,$arr,$type,$id) { + $o = ''; if($cnt == 1) $o .= $arr[0] . (($type === 'like') ? t(' likes this.') : t(' doesn\'t like this.')) . EOL ; else { @@ -1148,7 +1284,7 @@ function format_like($cnt,$arr,$type,$id) { if($total >= MAX_LIKERS) $str .= t(', and ') . $total - MAX_LIKERS . t(' other people'); $str .= (($type === 'like') ? t(' like this.') : t(' don\'t like this.')); - $o .= ''; + $o .= "\t" . ''; } return $o; }} @@ -1162,7 +1298,197 @@ function load_view_file($s) { $b = basename($s); $d = dirname($s); $lang = get_config('system','language'); - if($lang && file_exists("$d/$lang/$b")) + if($lang === false) + $lang = 'en'; + if(file_exists("$d/$lang/$b")) return file_get_contents("$d/$lang/$b"); return file_get_contents($s); -}} \ No newline at end of file +}} + +// for html,xml parsing - let's say you've got +// an attribute foobar="class1 class2 class3" +// and you want to find out if it contains 'class3'. +// you can't use a normal sub string search because you +// might match 'notclass3' and a regex to do the job is +// possible but a bit complicated. +// pass the attribute string as $attr and the attribute you +// are looking for as $s - returns true if found, otherwise false + +if(! function_exists('attribute_contains')) { +function attribute_contains($attr,$s) { + $a = explode(' ', $attr); + if(count($a) && in_array($s,$a)) + return true; + return false; +}} + +if(! function_exists('logger')) { +function logger($msg,$level = 0) { + + $debugging = get_config('system','debugging'); + $loglevel = intval(get_config('system','loglevel')); + $logfile = get_config('system','logfile'); + + if((! $debugging) || (! $logfile) || ($level > $loglevel)) + return; + + @file_put_contents($logfile, datetime_convert() . ':' . session_id() . ' ' . $msg . "\n", FILE_APPEND); + return; +}} + + +if(! function_exists('activity_match')) { +function activity_match($haystack,$needle) { + if(($haystack === $needle) || ((basename($needle) === $haystack) && strstr($needle,NAMESPACE_ACTIVITY_SCHEMA))) + return true; + return false; +}} + + +// Pull out all #hashtags and @person tags from $s; +// We also get @person@domain.com - which would make +// the regex quite complicated as tags can also +// end a sentence. So we'll run through our results +// and strip the period from any tags which end with one. +// Returns array of tags found, or empty array. + + +if(! function_exists('get_tags')) { +function get_tags($s) { + $ret = array(); + if(preg_match_all('/([@#][^ ,:?]*)([ ,:?]|$)/',$s,$match)) { + foreach($match[1] as $match) { + if(substr($match,-1,1) === '.') + $ret[] = substr($match,0,-1); + else + $ret[] = $match; + } + } + + return $ret; +}} + + +// quick and dirty quoted_printable encoding + +if(! function_exists('qp')) { +function qp($s) { +return str_replace ("%","=",rawurlencode($s)); +}} + + +if(! function_exists('like_puller')) { +function like_puller($a,$item,&$arr,$mode) { + + $url = ''; + $sparkle = ''; + $verb = (($mode === 'like') ? ACTIVITY_LIKE : ACTIVITY_DISLIKE); + + if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) { + $url = $item['author-link']; + if(($item['network'] === 'dfrn') && (! $item['self']) && ($item['author-link'] == $item['url'])) { + $url = $a->get_baseurl() . '/redir/' . $item['contact-id']; + $sparkle = ' class="sparkle" '; + } + if(! ((isset($arr[$item['parent'] . '-l'])) && (is_array($arr[$item['parent'] . '-l'])))) + $arr[$item['parent'] . '-l'] = array(); + if(! isset($arr[$item['parent']])) + $arr[$item['parent']] = 1; + else + $arr[$item['parent']] ++; + $arr[$item['parent'] . '-l'][] = '' . $item['author-name'] . ''; + } + return; +}} + +if(! function_exists('get_mentions')) { +function get_mentions($item) { + $o = ''; + if(! strlen($item['tag'])) + return $o; + + $arr = explode(',',$item['tag']); + foreach($arr as $x) { + $matches = null; + if(preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) + $o .= "\t\t" . '' . "\r\n"; + } + return $o; +}} + +if(! function_exists('contact_block')) { +function contact_block() { + $o = ''; + $a = get_app(); + if((! is_array($a->profile)) || ($a->profile['hide-friends'])) + return $o; + $r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0", + intval($a->profile['uid']) + ); + if(count($r)) { + $total = intval($r[0]['total']); + } + if(! $total) { + $o .= '

' . t('No contacts') . '

'; + return $o; + } + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 ORDER BY RAND() LIMIT 24", + intval($a->profile['uid']) + ); + if(count($r)) { + $o .= '

' . $total . ' ' . t('Contacts') . '

'; + foreach($r as $rr) { + $redirect_url = $a->get_baseurl() . '/redir/' . $rr['id']; + if(local_user() && ($rr['uid'] == local_user()) + && ($rr['network'] === 'dfrn')) { + $url = $redirect_url; + $sparkle = ' sparkle'; + } + else { + $url = $rr['url']; + $sparkle = ''; + } + + $o .= '
' . $rr['name'] . '
' . "\r\n"; + } + $o .= '
'; + $o .= '
' . t('View Contacts') . '
'; + + } + return $o; + +}} + +if(! function_exists('search')) { +function search($s) { + $a = get_app(); + $o = ''; + return $o; +}} + +if(! function_exists('valid_email')) { +function valid_email($x){ + if(preg_match('/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/',$x)) + return true; + return false; +}} + + +if(! function_exists('gravatar_img')) { +function gravatar_img($email) { + $size = 175; + $opt = 'identicon'; // psuedo-random geometric pattern if not found + $rating = 'pg'; + $hash = md5(trim(strtolower($email))); + + $url = 'http://www.gravatar.com/avatar/' . $hash . '.jpg' + . '?s=' . $size . '&d=' . $opt . '&r=' . $rating; + + logger('gravatar: ' . $email . ' ' . $url); + return $url; +}} +