]> git.mxchange.org Git - friendica.git/blob - boot.php
i18n strings update
[friendica.git] / boot.php
1 <?php
2
3 set_time_limit(0);
4
5 define ( 'BUILD_ID' , 1007 );
6
7 define ( 'EOL', "<br />\r\n");
8 define ( 'ATOM_TIME',  'Y-m-d\TH:i:s\Z' );
9
10 define ( 'REGISTER_CLOSED',  0);
11 define ( 'REGISTER_APPROVE', 1);
12 define ( 'REGISTER_OPEN',    2);
13
14 // relationship types
15
16 define ( 'REL_VIP',        1);
17 define ( 'REL_FAN',        2);
18 define ( 'REL_BUD',        3);
19
20 define ( 'NOTIFY_INTRO',   0x0001 );
21 define ( 'NOTIFY_CONFIRM', 0x0002 );
22 define ( 'NOTIFY_WALL',    0x0004 );
23 define ( 'NOTIFY_COMMENT', 0x0008 );
24 define ( 'NOTIFY_MAIL',    0x0010 );
25
26 define ( 'NAMESPACE_DFRN' ,           'http://purl.org/macgirvin/dfrn/1.0' ); 
27 define ( 'NAMESPACE_THREAD' ,         'http://purl.org/syndication/thread/1.0' );
28 define ( 'NAMESPACE_TOMB' ,           'http://purl.org/atompub/tombstones/1.0' );
29 define ( 'NAMESPACE_ACTIVITY',        'http://activitystrea.ms/spec/1.0/' );
30 define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/');
31 define ( 'NAMESPACE_SALMON_ME',       'http://salmon-protocol.org/ns/magic-env');
32
33 define ( 'ACTIVITY_LIKE',        NAMESPACE_ACTIVITY_SCHEMA . 'like' );
34 define ( 'ACTIVITY_DISLIKE',     NAMESPACE_DFRN            . '/dislike' );
35 define ( 'ACTIVITY_OBJ_HEART',   NAMESPACE_DFRN            . '/heart' );
36
37 define ( 'ACTIVITY_FRIEND',      NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
38 define ( 'ACTIVITY_POST',        NAMESPACE_ACTIVITY_SCHEMA . 'post' );
39 define ( 'ACTIVITY_UPDATE',      NAMESPACE_ACTIVITY_SCHEMA . 'update' );
40
41 define ( 'ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment' );
42 define ( 'ACTIVITY_OBJ_NOTE',    NAMESPACE_ACTIVITY_SCHEMA . 'note' );
43 define ( 'ACTIVITY_OBJ_PERSON',  NAMESPACE_ACTIVITY_SCHEMA . 'person' );
44 define ( 'ACTIVITY_OBJ_PHOTO',   NAMESPACE_ACTIVITY_SCHEMA . 'photo' );
45 define ( 'ACTIVITY_OBJ_P_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'profile-photo' );
46 define ( 'ACTIVITY_OBJ_ALBUM',   NAMESPACE_ACTIVITY_SCHEMA . 'photo-album' );
47
48 define ( 'GRAVITY_PARENT',       0);
49 define ( 'GRAVITY_LIKE',         3);
50 define ( 'GRAVITY_COMMENT',      6);
51
52
53 // Our main application structure for the life of this page
54 // Primarily deals with the URL that got us here
55 // and tries to make some sense of it, and 
56 // stores our page contents and config storage
57 // and anything else that might need to be passed around 
58 // before we spit the page out. 
59
60 if(! class_exists('App')) {
61 class App {
62
63         public  $module_loaded = false;
64         public  $config;
65         public  $page;
66         public  $profile;
67         public  $user;
68         public  $cid;
69         public  $contact;
70         public  $content;
71         public  $data;
72         public  $error = false;
73         public  $cmd;
74         public  $argv;
75         public  $argc;
76         public  $module;
77         public  $pager;
78         public  $strings;   
79         public  $path;
80
81         private $scheme;
82         private $hostname;
83         private $baseurl;
84         private $db;
85
86         function __construct() {
87
88                 $this->config = array();
89                 $this->page = array();
90                 $this->pager= array();
91
92                 $this->scheme = ((isset($_SERVER['HTTPS']) 
93                                 && ($_SERVER['HTTPS'])) ?  'https' : 'http' );
94                 $this->hostname = str_replace('www.','',
95                                 $_SERVER['SERVER_NAME']);
96                 set_include_path("include/$this->hostname" 
97                                 . PATH_SEPARATOR . 'include' 
98                                 . PATH_SEPARATOR . '.' );
99
100                 if(substr($_SERVER['QUERY_STRING'],0,2) == "q=")
101                         $_SERVER['QUERY_STRING'] = substr($_SERVER['QUERY_STRING'],2);
102                 $this->cmd = trim($_GET['q'],'/');
103
104
105                 $this->argv = explode('/',$this->cmd);
106                 $this->argc = count($this->argv);
107                 if((array_key_exists('0',$this->argv)) && strlen($this->argv[0])) {
108                         $this->module = $this->argv[0];
109                 }
110                 else {
111                         $this->module = 'home';
112                 }
113
114                 if($this->cmd === '.well-known/host-meta')
115                         require_once('include/hostxrd.php');
116
117                 $this->pager['page'] = ((x($_GET,'page')) ? $_GET['page'] : 1);
118                 $this->pager['itemspage'] = 50;
119                 $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
120                 $this->pager['total'] = 0;
121         }
122
123         function get_baseurl($ssl = false) {
124                 if(strlen($this->baseurl))
125                         return $this->baseurl;
126
127                 $this->baseurl = (($ssl) ? 'https' : $this->scheme) . "://" . $this->hostname
128                         . ((isset($this->path) && strlen($this->path)) 
129                         ? '/' . $this->path : '' );
130                 return $this->baseurl;
131         }
132
133         function set_baseurl($url) {
134                 $this->baseurl = $url;
135                 $this->hostname = basename($url);
136         }
137
138         function get_hostname() {
139                 return $this->hostname;
140         }
141
142         function set_hostname($h) {
143                 $this->hostname = $h;
144         }
145
146         function set_path($p) {
147                 $this->path = ltrim(trim($p),'/');
148         } 
149
150         function get_path() {
151                 return $this->path;
152         }
153
154         function set_pager_total($n) {
155                 $this->pager['total'] = intval($n);
156         }
157
158         function set_pager_itemspage($n) {
159                 $this->pager['itemspage'] = intval($n);
160                 $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
161
162         } 
163
164         function init_pagehead() {
165                 $tpl = load_view_file("view/head.tpl");
166                 $this->page['htmlhead'] = replace_macros($tpl,array(
167                         '$baseurl' => $this->get_baseurl()
168                 ));
169         }
170
171 }}
172
173 // retrieve the App structure
174 // useful in functions which require it but don't get it passed to them
175
176 if(! function_exists('get_app')) {
177 function get_app() {
178         global $a;
179         return $a;
180 }};
181
182
183 // Multi-purpose function to check variable state.
184 // Usage: x($var) or $x($array,'key')
185 // returns false if variable/key is not set
186 // if variable is set, returns 1 if has 'non-zero' value, otherwise returns 0.
187 // e.g. x('') or x(0) returns 0;
188
189 if(! function_exists('x')) {
190 function x($s,$k = NULL) {
191         if($k != NULL) {
192                 if((is_array($s)) && (array_key_exists($k,$s))) {
193                         if($s[$k])
194                                 return (int) 1;
195                         return (int) 0;
196                 }
197                 return false;
198         }
199         else {          
200                 if(isset($s)) {
201                         if($s) {
202                                 return (int) 1;
203                         }
204                         return (int) 0;
205                 }
206                 return false;
207         }
208 }}
209
210 // called from db initialisation if db is dead.
211
212 if(! function_exists('system_unavailable')) {
213 function system_unavailable() {
214         include('system_unavailable.php');
215         killme();
216 }}
217
218 // Primarily involved with database upgrade, but also sets the 
219 // base url for use in cmdline programs which don't have
220 // $_SERVER variables.
221
222 if(! function_exists('check_config')) {
223 function check_config(&$a) {
224
225         load_config('system');
226
227         $build = get_config('system','build');
228         if(! x($build))
229                 $build = set_config('system','build',BUILD_ID);
230
231         $url = get_config('system','url');
232         if(! x($url))
233                 $url = set_config('system','url',$a->get_baseurl());
234
235         if($build != BUILD_ID) {
236                 $stored = intval($build);
237                 $current = intval(BUILD_ID);
238                 if(($stored < $current) && file_exists('update.php')) {
239                         // We're reporting a different version than what is currently installed.
240                         // Run any existing update scripts to bring the database up to current.
241
242                         require_once('update.php');
243                         for($x = $stored; $x < $current; $x ++) {
244                                 if(function_exists('update_' . $x)) {
245                                         $func = 'update_' . $x;
246                                         $func($a);
247                                 }
248                         }
249                         set_config('system','build', BUILD_ID);
250                 }
251         }
252         return;
253 }}
254
255
256 // This is our template processor.
257 // $s is the string requiring macro substitution.
258 // $r is an array of key value pairs (search => replace)
259 // returns substituted string.
260 // WARNING: this is pretty basic, and doesn't properly handle search strings that are substrings of each other.
261 // For instance if 'test' => "foo" and 'testing' => "bar", testing could become either bar or fooing, 
262 // depending on the order in which they were declared in the array.   
263
264 if(! function_exists('replace_macros')) {  
265 function replace_macros($s,$r) {
266
267         $search = array();
268         $replace = array();
269
270         if(is_array($r) && count($r)) {
271                 foreach ($r as $k => $v ) {
272                         $search[] =  $k;
273                         $replace[] = $v;
274                 }
275         }
276         return str_replace($search,$replace,$s);
277 }}
278
279
280 // load string tranlsation table for alternate language
281
282 if(! function_exists('load_translation_table')) {
283 function load_translation_table($lang) {
284         global $a;
285
286         if(file_exists("view/$lang/strings.php"))
287                 include("view/$lang/strings.php");
288 }}
289
290 // translate string if translation exists
291
292 if(! function_exists('t')) {
293 function t($s) {
294         
295         $a = get_app();
296
297         if($a->strings[$s])
298                 return $a->strings[$s];
299         return $s;
300 }}
301
302 // curl wrapper. If binary flag is true, return binary
303 // results. 
304
305 if(! function_exists('fetch_url')) {
306 function fetch_url($url,$binary = false) {
307         $ch = curl_init($url);
308         if(! $ch) return false;
309
310         curl_setopt($ch, CURLOPT_HEADER, 0);
311         curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
312         curl_setopt($ch, CURLOPT_MAXREDIRS,8);
313         curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
314
315         // by default we will allow self-signed certs
316         // but you can override this
317
318         $check_cert = get_config('system','verifyssl');
319         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
320
321         $prx = get_config('system','proxy');
322         if(strlen($prx)) {
323                 curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
324                 curl_setopt($ch, CURLOPT_PROXY, $prx);
325                 $prxusr = get_config('system','proxyuser');
326                 if(strlen($prxusr))
327                         curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
328         }
329         if($binary)
330                 curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
331
332         $s = curl_exec($ch);
333         curl_close($ch);
334         return($s);
335 }}
336
337 // post request to $url. $params is an array of post variables.
338
339 if(! function_exists('post_url')) {
340 function post_url($url,$params) {
341         $ch = curl_init($url);
342         if(! $ch) return false;
343
344         curl_setopt($ch, CURLOPT_HEADER, 0);
345         curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
346         curl_setopt($ch, CURLOPT_MAXREDIRS,8);
347         curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
348         curl_setopt($ch, CURLOPT_POST,1);
349         curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
350         $check_cert = get_config('system','verifyssl');
351         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
352         $prx = get_config('system','proxy');
353         if(strlen($prx)) {
354                 curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
355                 curl_setopt($ch, CURLOPT_PROXY, $prx);
356                 $prxusr = get_config('system','proxyuser');
357                 if(strlen($prxusr))
358                         curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
359         }
360
361         $s = curl_exec($ch);
362         curl_close($ch);
363         return($s);
364 }}
365
366 // random hash, 64 chars
367
368 if(! function_exists('random_string')) {
369 function random_string() {
370         return(hash('sha256',uniqid(rand(),true)));
371 }}
372
373 // This is our primary input filter. The high bit hack only involved some old
374 // IE browser, forget which. 
375 // Use this on any text input where angle chars are not valid or permitted
376 // They will be replaced with safer brackets. This may be filtered further
377 // if these are not allowed either.   
378
379 if(! function_exists('notags')) {
380 function notags($string) {
381         // protect against :<> with high-bit set
382         return(str_replace(array("<",">","\xBA","\xBC","\xBE"), array('[',']','','',''), $string));
383 }}
384
385 // use this on "body" or "content" input where angle chars shouldn't be removed,
386 // and allow them to be safely displayed.
387
388 if(! function_exists('escape_tags')) {
389 function escape_tags($string) {
390
391         return(htmlspecialchars($string));
392 }}
393
394 // wrapper for adding a login box. If $register == true provide a registration
395 // link. This will most always depend on the value of $a->config['register_policy'].
396
397 if(! function_exists('login')) {
398 function login($register = false) {
399         $o = "";
400         $register_html = (($register) ? load_view_file("view/register-link.tpl") : "");
401
402
403         if(x($_SESSION,'authenticated')) {
404                 $o = load_view_file("view/logout.tpl");
405         }
406         else {
407                 $o = load_view_file("view/login.tpl");
408
409                 $o = replace_macros($o,array('$register_html' => $register_html ));
410         }
411         return $o;
412 }}
413
414 // generate a string that's random, but usually pronounceable. 
415 // used to generate initial passwords
416
417 if(! function_exists('autoname')) {
418 function autoname($len) {
419
420         $vowels = array('a','a','ai','au','e','e','e','ee','ea','i','ie','o','ou','u'); 
421         if(mt_rand(0,5) == 4)
422                 $vowels[] = 'y';
423
424         $cons = array(
425                         'b','bl','br',
426                         'c','ch','cl','cr',
427                         'd','dr',
428                         'f','fl','fr',
429                         'g','gh','gl','gr',
430                         'h',
431                         'j',
432                         'k','kh','kl','kr',
433                         'l',
434                         'm',
435                         'n',
436                         'p','ph','pl','pr',
437                         'qu',
438                         'r','rh',
439                         's','sc','sh','sm','sp','st',
440                         't','th','tr',
441                         'v',
442                         'w','wh',
443                         'x',
444                         'z','zh'
445                         );
446
447         $midcons = array('ck','ct','gn','ld','lf','lm','lt','mb','mm', 'mn','mp',
448                                 'nd','ng','nk','nt','rn','rp','rt');
449
450         $noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr',
451                                 'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh');
452
453         $start = mt_rand(0,2);
454         if($start == 0)
455                 $table = $vowels;
456         else
457                 $table = $cons;
458
459         $word = '';
460
461         for ($x = 0; $x < $len; $x ++) {
462                 $r = mt_rand(0,count($table) - 1);
463                 $word .= $table[$r];
464   
465                 if($table == $vowels)
466                         $table = array_merge($cons,$midcons);
467                 else
468                         $table = $vowels;
469
470         }
471
472         $word = substr($word,0,$len);
473
474         foreach($noend as $noe) {
475                 if((strlen($word) > 2) && (substr($word,-2) == $noe)) {
476                         $word = substr($word,0,-1);
477                         break;
478                 }
479         }
480         if(substr($word,-1) == 'q')
481                 $word = substr($word,0,-1);    
482         return $word;
483 }}
484
485 // Used to end the current process, after saving session state. 
486
487 if(! function_exists('killme')) {
488 function killme() {
489         session_write_close();
490         exit;
491 }}
492
493 // redirect to another URL and terminate this process.
494
495 if(! function_exists('goaway')) {
496 function goaway($s) {
497         header("Location: $s");
498         killme();
499 }}
500
501 // Generic XML return
502 // Outputs a basic dfrn XML status structure to STDOUT, with a <status> variable 
503 // of $st and an optional text <message> of $message and terminates the current process. 
504
505 if(! function_exists('xml_status')) {
506 function xml_status($st, $message = '') {
507
508         if(strlen($message))
509                 $xml_message = "\t<message>" . xmlify($message) . "</message>\r\n";
510
511         header( "Content-type: text/xml" );
512         echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";
513         echo "<result>\r\n\t<status>$st</status>\r\n$xml_message</result>\r\n";
514         killme();
515 }}
516
517 // Returns the uid of locally logged on user or false.
518
519 if(! function_exists('local_user')) {
520 function local_user() {
521         if((x($_SESSION,'authenticated')) && (x($_SESSION,'uid')))
522                 return $_SESSION['uid'];
523         return false;
524 }}
525
526 // Returns contact id of authenticated site visitor or false
527
528 if(! function_exists('remote_user')) {
529 function remote_user() {
530         if((x($_SESSION,'authenticated')) && (x($_SESSION,'visitor_id')))
531                 return $_SESSION['visitor_id'];
532         return false;
533 }}
534
535 // contents of $s are displayed prominently on the page the next time
536 // a page is loaded. Usually used for errors or alerts.
537
538 if(! function_exists('notice')) {
539 function notice($s) {
540
541         $_SESSION['sysmsg'] .= $s;
542
543 }}
544
545 // wrapper around config to limit the text length of an incoming message
546
547 if(! function_exists('get_max_import_size')) {
548 function get_max_import_size() {
549         global $a;
550         return ((x($a->config,'max_import_size')) ? $a->config['max_import_size'] : 0 );
551 }}
552
553
554 // escape text ($str) for XML transport
555 // returns escaped text.
556
557 if(! function_exists('xmlify')) {
558 function xmlify($str) {
559         $buffer = '';
560         
561         for($x = 0; $x < strlen($str); $x ++) {
562                 $char = $str[$x];
563         
564                 switch( $char ) {
565
566                         case "\r" :
567                                 break;
568                         case "&" :
569                                 $buffer .= '&amp;';
570                                 break;
571                         case "'" :
572                                 $buffer .= '&apos;';
573                                 break;
574
575                         case "\"" :
576                                 $buffer .= '&quot;';
577                                 break;
578                         case '<' :
579                                 $buffer .= '&lt;';
580                                 break;
581                         case '>' :
582                                 $buffer .= '&gt;';
583                                 break;
584                         case "\n" :
585                                 $buffer .= ' ';
586                                 break;
587                         default :
588                                 $buffer .= $char;
589                                 break;
590                 }       
591         }
592         $buffer = trim($buffer);
593         return($buffer);
594 }}
595
596 // undo an xmlify
597 // pass xml escaped text ($s), returns unescaped text
598
599 if(! function_exists('unxmlify')) {
600 function unxmlify($s) {
601         $ret = str_replace('&amp;','&', $s);
602         $ret = str_replace(array('&lt;','&gt;','&quot;','&apos;'),array('<','>','"',"'"),$ret);
603         return $ret;    
604 }}
605
606 // convenience wrapper, reverse the operation "bin2hex"
607
608 if(! function_exists('hex2bin')) {
609 function hex2bin($s) {
610         return(pack("H*",$s));
611 }}
612
613 // Automatic pagination.
614 // To use, get the count of total items.
615 // Then call $a->set_pager_total($number_items);
616 // Optionally call $a->set_pager_itemspage($n) to the number of items to display on each page
617 // Then call paginate($a) after the end of the display loop to insert the pager block on the page
618 // (assuming there are enough items to paginate).
619 // When using with SQL, the setting LIMIT %d, %d => $a->pager['start'],$a->pager['itemspage']
620 // will limit the results to the correct items for the current page. 
621 // The actual page handling is then accomplished at the application layer. 
622
623 if(! function_exists('paginate')) {
624 function paginate(&$a) {
625         $o = '';
626         $stripped = ereg_replace("(&page=[0-9]*)","",$_SERVER['QUERY_STRING']);
627         $stripped = str_replace('q=','',$stripped);
628         $stripped = trim($stripped,'/');
629         $url = $a->get_baseurl() . '/' . $stripped;
630
631
632           if($a->pager['total'] > $a->pager['itemspage']) {
633                 $o .= '<div class="pager">';
634                 if($a->pager['page'] != 1)
635                         $o .= '<span class="pager_prev">'."<a href=\"$url".'&page='.($a->pager['page'] - 1).'">' . t('prev') . '</a></span> ';
636
637                 $o .=  "<span class=\"pager_first\"><a href=\"$url"."&page=1\">" . t('first') . "</a></span> ";
638
639                 $numpages = $a->pager['total'] / $a->pager['itemspage'];
640
641                 $numstart = 1;
642                 $numstop = $numpages;
643
644                 if($numpages > 14) {
645                         $numstart = (($pagenum > 7) ? ($pagenum - 7) : 1);
646                         $numstop = (($pagenum > ($numpages - 7)) ? $numpages : ($numstart + 14));
647                 }
648    
649                 for($i = $numstart; $i <= $numstop; $i++){
650                         if($i == $a->pager['page'])
651                                 $o .= '<span class="pager_current">'.(($i < 10) ? '&nbsp;'.$i : $i);
652                         else
653                                 $o .= "<span class=\"pager_n\"><a href=\"$url"."&page=$i\">".(($i < 10) ? '&nbsp;'.$i : $i)."</a>";
654                         $o .= '</span> ';
655                 }
656
657                 if(($a->pager['total'] % $a->pager['itemspage']) != 0) {
658                         if($i == $a->pager['page'])
659                                 $o .= '<span class="pager_current">'.(($i < 10) ? '&nbsp;'.$i : $i);
660                         else
661                                 $o .= "<span class=\"pager_n\"><a href=\"$url"."&page=$i\">".(($i < 10) ? '&nbsp;'.$i : $i)."</a>";
662                         $o .= '</span> ';
663                 }
664
665                 $lastpage = (($numpages > intval($numpages)) ? intval($numpages)+1 : $numpages);
666                 $o .= "<span class=\"pager_last\"><a href=\"$url"."&page=$lastpage\">" . t('last') . "</a></span> ";
667
668                 if(($a->pager['total'] - ($a->pager['itemspage'] * $a->pager['page'])) > 0)
669                         $o .= '<span class="pager_next">'."<a href=\"$url"."&page=".($a->pager['page'] + 1).'">' . t('next') . '</a></span>';
670                 $o .= '</div>'."\r\n";
671         }
672         return $o;
673 }}
674
675 // Turn user/group ACLs stored as angle bracketed text into arrays
676
677 if(! function_exists('expand_acl')) {
678 function expand_acl($s) {
679         // turn string array of angle-bracketed elements into numeric array
680         // e.g. "<1><2><3>" => array(1,2,3);
681         $ret = array();
682
683         if(strlen($s)) {
684                 $t = str_replace('<','',$s);
685                 $a = explode('>',$t);
686                 foreach($a as $aa) {
687                         if(intval($aa))
688                                 $ret[] = intval($aa);
689                 }
690         }
691         return $ret;
692 }}              
693
694 // Used to wrap ACL elements in angle brackets for storage 
695
696 if(! function_exists('sanitise_acl')) {
697 function sanitise_acl(&$item) {
698         if(intval($item))
699                 $item = '<' . intval(notags(trim($item))) . '>';
700         else
701                 unset($item);
702 }}
703
704 // retrieve a "family" of config variables from database to cached storage
705
706 if(! function_exists('load_config')) {
707 function load_config($family) {
708         global $a;
709         $r = q("SELECT * FROM `config` WHERE `cat` = '%s'",
710                 dbesc($family)
711         );
712         if(count($r)) {
713                 foreach($r as $rr) {
714                         $k = $rr['k'];
715                         $a->config[$family][$k] = $rr['v'];
716                 }
717         }
718 }}
719
720 // get a particular config variable given the family name
721 // and key. Returns false if not set.
722 // $instore is only used by the set_config function
723 // to determine if the key already exists in the DB
724 // If a key is found in the DB but doesn't exist in
725 // local config cache, pull it into the cache so we don't have
726 // to hit the DB again for this item.
727
728 if(! function_exists('get_config')) {
729 function get_config($family, $key, $instore = false) {
730
731         global $a;
732
733         if(! $instore) {
734                 if(isset($a->config[$family][$key])) {
735                         if($a->config[$family][$key] === '!<unset>!') {
736                                 return false;
737                         }
738                         return $a->config[$family][$key];
739                 }
740         }
741         $ret = q("SELECT `v` FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
742                 dbesc($family),
743                 dbesc($key)
744         );
745         if(count($ret)) {
746                 $a->config[$family][$key] = $ret[0]['v'];
747                 return $ret[0]['v'];
748         }
749         else {
750                 $a->config[$family][$key] = '!<unset>!';
751         }
752         return false;
753 }}
754
755 // Store a config value ($value) in the category ($family)
756 // under the key ($key)
757 // Return the value, or false if the database update failed
758
759 if(! function_exists('set_config')) {
760 function set_config($family,$key,$value) {
761
762         global $a;
763         $a->config[$family][$key] = $value;
764
765         if(get_config($family,$key,true) === false) {
766                 $ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ",
767                         dbesc($family),
768                         dbesc($key),
769                         dbesc($value)
770                 );
771                 if($ret) 
772                         return $value;
773                 return $ret;
774         }
775         $ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
776                 dbesc($value),
777                 dbesc($family),
778                 dbesc($key)
779         );
780         if($ret)
781                 return $value;
782         return $ret;
783 }}
784
785 // convert an XML document to a normalised, case-corrected array
786 // used by webfinger
787
788 if(! function_exists('convert_xml_element_to_array')) {
789 function convert_xml_element_to_array($xml_element, &$recursion_depth=0) {
790
791         // If we're getting too deep, bail out
792         if ($recursion_depth > 512) {
793                 return(null);
794         }
795
796         if (!is_string($xml_element) &&
797         !is_array($xml_element) &&
798         (get_class($xml_element) == 'SimpleXMLElement')) {
799                 $xml_element_copy = $xml_element;
800                 $xml_element = get_object_vars($xml_element);
801         }
802
803         if (is_array($xml_element)) {
804                 $result_array = array();
805                 if (count($xml_element) <= 0) {
806                         return (trim(strval($xml_element_copy)));
807                 }
808
809                 foreach($xml_element as $key=>$value) {
810
811                         $recursion_depth++;
812                         $result_array[strtolower($key)] =
813                 convert_xml_element_to_array($value, $recursion_depth);
814                         $recursion_depth--;
815                 }
816                 if ($recursion_depth == 0) {
817                         $temp_array = $result_array;
818                         $result_array = array(
819                                 strtolower($xml_element_copy->getName()) => $temp_array,
820                         );
821                 }
822
823                 return ($result_array);
824
825         } else {
826                 return (trim(strval($xml_element)));
827         }
828 }}
829
830 // Given an email style address, perform webfinger lookup and 
831 // return the resulting DFRN profile URL.
832 // If this isn't an email style address just return $s.
833 // Return an empty string if email-style addresses but webfinger fails,
834 // or if the resultant personal XRD doesn't contain a DFRN profile.
835
836 if(! function_exists('webfinger')) {
837 function webfinger($s) {
838         if(! strstr($s,'@')) {
839                 return $s;
840         }
841         $host = substr($s,strpos($s,'@') + 1);
842         $url = 'http://' . $host . '/.well-known/host-meta' ;
843         $xml = fetch_url($url);
844         if (! $xml)
845                 return '';
846         $h = simplexml_load_string($xml);
847         $arr = convert_xml_element_to_array($h);
848
849         if(! isset($arr['xrd']['link']))
850                 return '';
851
852         $link = $arr['xrd']['link'];
853         if(! isset($link[0]))
854                 $links = array($link);
855         else
856                 $links = $link;
857
858         foreach($links as $link)
859                 if($link['@attributes']['rel'] && $link['@attributes']['rel'] === 'lrdd')
860                         $tpl = $link['@attributes']['template'];
861         if((empty($tpl)) || (! strpos($tpl, '{uri}')))
862                 return '';
863
864         $pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl);
865
866         $xml = fetch_url($pxrd);
867         if (! $xml)
868                 return '';
869         $h = simplexml_load_string($xml);
870         $arr = convert_xml_element_to_array($h);
871
872         if(! isset($arr['xrd']['link']))
873                 return '';
874
875         $link = $arr['xrd']['link'];
876         if(! isset($link[0]))
877                 $links = array($link);
878         else
879                 $links = $link;
880
881         foreach($links as $link)
882                 if($link['@attributes']['rel'] == NAMESPACE_DFRN)
883                         return $link['@attributes']['href'];
884         return '';
885 }}
886
887
888 // Convert an ACL array to a storable string
889
890 if(! function_exists('perms2str')) {
891 function perms2str($p) {
892         $ret = '';
893         $tmp = $p;
894         if(is_array($tmp)) {
895                 array_walk($tmp,'sanitise_acl');
896                 $ret = implode('',$tmp);
897         }
898         return $ret;
899 }}
900
901 // generate a guaranteed unique (for this domain) item ID for ATOM
902 // safe from birthday paradox
903
904 if(! function_exists('item_new_uri')) {
905 function item_new_uri($hostname,$uid) {
906
907         do {
908                 $dups = false;
909                 $hash = random_string();
910
911                 $uri = "urn:X-dfrn:" . $hostname . ':' . $uid . ':' . $hash;
912
913                 $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1",
914                         dbesc($uri));
915                 if(count($r))
916                         $dups = true;
917         } while($dups == true);
918         return $uri;
919 }}
920
921 // Generate a guaranteed unique photo ID.
922 // safe from birthday paradox
923
924 if(! function_exists('photo_new_resource')) {
925 function photo_new_resource() {
926
927         do {
928                 $found = false;
929                 $resource = hash('md5',uniqid(mt_rand(),true));
930                 $r = q("SELECT `id` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1",
931                         dbesc($resource)
932                 );
933                 if(count($r))
934                         $found = true;
935         } while($found == true);
936         return $resource;
937 }}
938
939
940 // Returns logged in user ID
941
942 if(! function_exists('get_uid')) {
943 function get_uid() {
944         return ((x($_SESSION,'uid')) ? intval($_SESSION['uid']) : 0) ;
945 }}
946
947 // Take a URL from the wild, prepend http:// if necessary
948 // and check DNS to see if it's real
949 // return true if it's OK, false if something is wrong with it
950
951 if(! function_exists('validate_url')) {
952 function validate_url(&$url) {
953         if(substr($url,0,4) != 'http')
954                 $url = 'http://' . $url;
955         $h = parse_url($url);
956
957         if(! $h) {
958                 return false;
959         }
960         if(! checkdnsrr($h['host'], 'ANY')) {
961                 return false;
962         }
963         return true;
964 }}
965
966 // Check $url against our list of allowed sites,
967 // wildcards allowed. If allowed_sites is unset return true;
968 // If url is allowed, return true.
969 // otherwise, return false
970
971 if(! function_exists('allowed_url')) {
972 function allowed_url($url) {
973
974         $h = parse_url($url);
975
976         if(! $h) {
977                 return false;
978         }
979
980         $str_allowed = get_config('system','allowed_sites');
981         if(! $str_allowed)
982                 return true;
983
984         $found = false;
985
986         $host = strtolower($h['host']);
987
988         // always allow our own site
989
990         if($host == strtolower($_SERVER['SERVER_NAME']))
991                 return true;
992
993         $fnmatch = function_exists('fnmatch');
994         $allowed = explode(',',$str_allowed);
995
996         if(count($allowed)) {
997                 foreach($allowed as $a) {
998                         $pat = strtolower(trim($a));
999                         if(($fnmatch && fnmatch($pat,$host)) || ($pat == $host)) {
1000                                 $found = true; 
1001                                 break;
1002                         }
1003                 }
1004         }
1005         return $found;
1006 }}
1007
1008 // check if email address is allowed to register here.
1009 // Compare against our list (wildcards allowed).
1010 // Returns false if not allowed, true if allowed or if
1011 // allowed list is not configured.
1012
1013 if(! function_exists('allowed_email')) {
1014 function allowed_email($email) {
1015
1016
1017         $domain = strtolower(substr($email,strpos($email,'@') + 1));
1018         if(! $domain)
1019                 return false;
1020
1021         $str_allowed = get_config('system','allowed_email');
1022         if(! $str_allowed)
1023                 return true;
1024
1025         $found = false;
1026
1027         $fnmatch = function_exists('fnmatch');
1028         $allowed = explode(',',$str_allowed);
1029
1030         if(count($allowed)) {
1031                 foreach($allowed as $a) {
1032                         $pat = strtolower(trim($a));
1033                         if(($fnmatch && fnmatch($pat,$host)) || ($pat == $host)) {
1034                                 $found = true; 
1035                                 break;
1036                         }
1037                 }
1038         }
1039         return $found;
1040 }}
1041
1042 // Format the like/dislike text for a profile item
1043 // $cnt = number of people who like/dislike the item
1044 // $arr = array of pre-linked names of likers/dislikers
1045 // $type = one of 'like, 'dislike'
1046 // $id  = item id
1047 // returns formatted text
1048
1049 if(! function_exists('format_like')) {
1050 function format_like($cnt,$arr,$type,$id) {
1051         if($cnt == 1)
1052                 $o .= $arr[0] . (($type === 'like') ? t(' likes this.') : t(' doesn\'t like this.')) . EOL ;
1053         else {
1054                 $o .= '<span class="fakelink" onclick="openClose(\'' . $type . 'list-' . $id . '\');" >' 
1055                         . $cnt . ' ' . t('people') . '</span> ' . (($type === 'like') ? t('like this.') : t('don\'t like this.')) . EOL ;
1056                 $total = count($arr);
1057                 if($total >= 75)
1058                         $arr = array_slice($arr,0,74);
1059                 if($total < 75)
1060                         $arr[count($arr)-1] = t('and') . ' ' . $arr[count($arr)-1];
1061                 $str = implode(', ', $arr);
1062                 if($total >= 75)
1063                         $str .= t(', and ') . $total - 75 . t(' other people');
1064                 $str .= (($type === 'like') ? t(' like this.') : t(' don\'t like this.'));
1065                 $o .= '<div id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>';
1066         }
1067         return $o;
1068 }}
1069
1070
1071 // wrapper to load a view template, checking for alternate
1072 // languages before falling back to the default
1073
1074 if(! function_exists('load_view_file')) {
1075 function load_view_file($s) {
1076         $b = basename($s);
1077         $d = dirname($s);
1078         $lang = get_config('system','language');
1079         if($lang && file_exists("$d/$lang/$b"))
1080                 return file_get_contents("$d/$lang/$b");
1081         return file_get_contents($s);
1082 }}