Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2368 lines
65 KiB

11 years ago
10 years ago
7 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
9 years ago
11 years ago
9 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
9 years ago
9 years ago
9 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
9 years ago
9 years ago
11 years ago
9 years ago
9 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
8 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
11 years ago
  1. <?php
  2. require_once('include/config.php');
  3. require_once('include/network.php');
  4. require_once('include/plugin.php');
  5. require_once('include/text.php');
  6. require_once('include/datetime.php');
  7. require_once('include/pgettext.php');
  8. require_once('include/nav.php');
  9. require_once('include/cache.php');
  10. require_once('library/Mobile_Detect/Mobile_Detect.php');
  11. require_once('include/features.php');
  12. require_once('update.php');
  13. require_once('include/dbstructure.php');
  14. define ( 'FRIENDICA_PLATFORM', 'Friendica');
  15. define ( 'FRIENDICA_VERSION', '3.3rc' );
  16. define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
  17. define ( 'DB_UPDATE_VERSION', 1173 );
  18. define ( 'EOL', "<br />\r\n" );
  19. define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
  20. /**
  21. *
  22. * Image storage quality. Lower numbers save space at cost of image detail.
  23. * For ease of upgrade, please do not change here. Change jpeg quality with
  24. * $a->config['system']['jpeg_quality'] = n;
  25. * in .htconfig.php, where n is netween 1 and 100, and with very poor results
  26. * below about 50
  27. *
  28. */
  29. define ( 'JPEG_QUALITY', 100 );
  30. /**
  31. * $a->config['system']['png_quality'] from 0 (uncompressed) to 9
  32. */
  33. define ( 'PNG_QUALITY', 8 );
  34. /**
  35. *
  36. * An alternate way of limiting picture upload sizes. Specify the maximum pixel
  37. * length that pictures are allowed to be (for non-square pictures, it will apply
  38. * to the longest side). Pictures longer than this length will be resized to be
  39. * this length (on the longest side, the other side will be scaled appropriately).
  40. * Modify this value using
  41. *
  42. * $a->config['system']['max_image_length'] = n;
  43. *
  44. * in .htconfig.php
  45. *
  46. * If you don't want to set a maximum length, set to -1. The default value is
  47. * defined by 'MAX_IMAGE_LENGTH' below.
  48. *
  49. */
  50. define ( 'MAX_IMAGE_LENGTH', -1 );
  51. /**
  52. * Not yet used
  53. */
  54. define ( 'DEFAULT_DB_ENGINE', 'MyISAM' );
  55. /**
  56. * SSL redirection policies
  57. */
  58. define ( 'SSL_POLICY_NONE', 0 );
  59. define ( 'SSL_POLICY_FULL', 1 );
  60. define ( 'SSL_POLICY_SELFSIGN', 2 );
  61. /**
  62. * log levels
  63. */
  64. define ( 'LOGGER_NORMAL', 0 );
  65. define ( 'LOGGER_TRACE', 1 );
  66. define ( 'LOGGER_DEBUG', 2 );
  67. define ( 'LOGGER_DATA', 3 );
  68. define ( 'LOGGER_ALL', 4 );
  69. /**
  70. * registration policies
  71. */
  72. define ( 'REGISTER_CLOSED', 0 );
  73. define ( 'REGISTER_APPROVE', 1 );
  74. define ( 'REGISTER_OPEN', 2 );
  75. /**
  76. * relationship types
  77. */
  78. define ( 'CONTACT_IS_FOLLOWER', 1);
  79. define ( 'CONTACT_IS_SHARING', 2);
  80. define ( 'CONTACT_IS_FRIEND', 3);
  81. /**
  82. * DB update return values
  83. */
  84. define ( 'UPDATE_SUCCESS', 0);
  85. define ( 'UPDATE_FAILED', 1);
  86. /**
  87. *
  88. * page/profile types
  89. *
  90. * PAGE_NORMAL is a typical personal profile account
  91. * PAGE_SOAPBOX automatically approves all friend requests as CONTACT_IS_SHARING, (readonly)
  92. * PAGE_COMMUNITY automatically approves all friend requests as CONTACT_IS_SHARING, but with
  93. * write access to wall and comments (no email and not included in page owner's ACL lists)
  94. * PAGE_FREELOVE automatically approves all friend requests as full friends (CONTACT_IS_FRIEND).
  95. *
  96. */
  97. define ( 'PAGE_NORMAL', 0 );
  98. define ( 'PAGE_SOAPBOX', 1 );
  99. define ( 'PAGE_COMMUNITY', 2 );
  100. define ( 'PAGE_FREELOVE', 3 );
  101. define ( 'PAGE_BLOG', 4 );
  102. define ( 'PAGE_PRVGROUP', 5 );
  103. /**
  104. * Network and protocol family types
  105. */
  106. define ( 'NETWORK_DFRN', 'dfrn'); // Friendica, Mistpark, other DFRN implementations
  107. define ( 'NETWORK_ZOT', 'zot!'); // Zot!
  108. define ( 'NETWORK_OSTATUS', 'stat'); // status.net, identi.ca, GNU-social, other OStatus implementations
  109. define ( 'NETWORK_FEED', 'feed'); // RSS/Atom feeds with no known "post/notify" protocol
  110. define ( 'NETWORK_DIASPORA', 'dspr'); // Diaspora
  111. define ( 'NETWORK_MAIL', 'mail'); // IMAP/POP
  112. define ( 'NETWORK_MAIL2', 'mai2'); // extended IMAP/POP
  113. define ( 'NETWORK_FACEBOOK', 'face'); // Facebook API
  114. define ( 'NETWORK_LINKEDIN', 'lnkd'); // LinkedIn
  115. define ( 'NETWORK_XMPP', 'xmpp'); // XMPP
  116. define ( 'NETWORK_MYSPACE', 'mysp'); // MySpace
  117. define ( 'NETWORK_GPLUS', 'goog'); // Google+
  118. define ( 'NETWORK_PUMPIO', 'pump'); // pump.io
  119. define ( 'NETWORK_TWITTER', 'twit'); // Twitter
  120. define ( 'NETWORK_DIASPORA2', 'dspc'); // Diaspora connector
  121. define ( 'NETWORK_STATUSNET', 'stac'); // Statusnet connector
  122. define ( 'NETWORK_APPNET', 'apdn'); // app.net
  123. define ( 'NETWORK_PHANTOM', 'unkn'); // Place holder
  124. /**
  125. * These numbers are used in stored permissions
  126. * and existing allocations MUST NEVER BE CHANGED
  127. * OR RE-ASSIGNED! You may only add to them.
  128. */
  129. $netgroup_ids = array(
  130. NETWORK_DFRN => (-1),
  131. NETWORK_ZOT => (-2),
  132. NETWORK_OSTATUS => (-3),
  133. NETWORK_FEED => (-4),
  134. NETWORK_DIASPORA => (-5),
  135. NETWORK_MAIL => (-6),
  136. NETWORK_MAIL2 => (-7),
  137. NETWORK_FACEBOOK => (-8),
  138. NETWORK_LINKEDIN => (-9),
  139. NETWORK_XMPP => (-10),
  140. NETWORK_MYSPACE => (-11),
  141. NETWORK_GPLUS => (-12),
  142. NETWORK_PUMPIO => (-13),
  143. NETWORK_TWITTER => (-14),
  144. NETWORK_DIASPORA2 => (-15),
  145. NETWORK_STATUSNET => (-16),
  146. NETWORK_APPNET => (-17),
  147. NETWORK_PHANTOM => (-127),
  148. );
  149. /**
  150. * Maximum number of "people who like (or don't like) this" that we will list by name
  151. */
  152. define ( 'MAX_LIKERS', 75);
  153. /**
  154. * Communication timeout
  155. */
  156. define ( 'ZCURL_TIMEOUT' , (-1));
  157. /**
  158. * email notification options
  159. */
  160. define ( 'NOTIFY_INTRO', 0x0001 );
  161. define ( 'NOTIFY_CONFIRM', 0x0002 );
  162. define ( 'NOTIFY_WALL', 0x0004 );
  163. define ( 'NOTIFY_COMMENT', 0x0008 );
  164. define ( 'NOTIFY_MAIL', 0x0010 );
  165. define ( 'NOTIFY_SUGGEST', 0x0020 );
  166. define ( 'NOTIFY_PROFILE', 0x0040 );
  167. define ( 'NOTIFY_TAGSELF', 0x0080 );
  168. define ( 'NOTIFY_TAGSHARE', 0x0100 );
  169. define ( 'NOTIFY_POKE', 0x0200 );
  170. define ( 'NOTIFY_SHARE', 0x0400 );
  171. define ( 'NOTIFY_SYSTEM', 0x8000 );
  172. /**
  173. * Tag/term types
  174. */
  175. define ( 'TERM_UNKNOWN', 0 );
  176. define ( 'TERM_HASHTAG', 1 );
  177. define ( 'TERM_MENTION', 2 );
  178. define ( 'TERM_CATEGORY', 3 );
  179. define ( 'TERM_PCATEGORY', 4 );
  180. define ( 'TERM_FILE', 5 );
  181. define ( 'TERM_SAVEDSEARCH', 6 );
  182. define ( 'TERM_CONVERSATION', 7 );
  183. define ( 'TERM_OBJ_POST', 1 );
  184. define ( 'TERM_OBJ_PHOTO', 2 );
  185. /**
  186. * various namespaces we may need to parse
  187. */
  188. define ( 'NAMESPACE_ZOT', 'http://purl.org/zot' );
  189. define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' );
  190. define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' );
  191. define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' );
  192. define ( 'NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/' );
  193. define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' );
  194. define ( 'NAMESPACE_MEDIA', 'http://purl.org/syndication/atommedia' );
  195. define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env' );
  196. define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe' );
  197. define ( 'NAMESPACE_GEORSS', 'http://www.georss.org/georss' );
  198. define ( 'NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0' );
  199. define ( 'NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from' );
  200. define ( 'NAMESPACE_OSTATUS', 'http://ostatus.org/schema/1.0' );
  201. define ( 'NAMESPACE_STATUSNET', 'http://status.net/schema/api/1/' );
  202. define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
  203. /**
  204. * activity stream defines
  205. */
  206. define ( 'ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like' );
  207. define ( 'ACTIVITY_DISLIKE', NAMESPACE_DFRN . '/dislike' );
  208. define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_DFRN . '/heart' );
  209. define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
  210. define ( 'ACTIVITY_REQ_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'request-friend' );
  211. define ( 'ACTIVITY_UNFRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'remove-friend' );
  212. define ( 'ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow' );
  213. define ( 'ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'stop-following' );
  214. define ( 'ACTIVITY_JOIN', NAMESPACE_ACTIVITY_SCHEMA . 'join' );
  215. define ( 'ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post' );
  216. define ( 'ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update' );
  217. define ( 'ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag' );
  218. define ( 'ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite' );
  219. define ( 'ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke' );
  220. define ( 'ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood' );
  221. define ( 'ACTIVITY_OBJ_BOOKMARK', NAMESPACE_ACTIVITY_SCHEMA . 'bookmark' );
  222. define ( 'ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment' );
  223. define ( 'ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note' );
  224. define ( 'ACTIVITY_OBJ_PERSON', NAMESPACE_ACTIVITY_SCHEMA . 'person' );
  225. define ( 'ACTIVITY_OBJ_IMAGE', NAMESPACE_ACTIVITY_SCHEMA . 'image' );
  226. define ( 'ACTIVITY_OBJ_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'photo' );
  227. define ( 'ACTIVITY_OBJ_VIDEO', NAMESPACE_ACTIVITY_SCHEMA . 'video' );
  228. define ( 'ACTIVITY_OBJ_P_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'profile-photo' );
  229. define ( 'ACTIVITY_OBJ_ALBUM', NAMESPACE_ACTIVITY_SCHEMA . 'photo-album' );
  230. define ( 'ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event' );
  231. define ( 'ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group' );
  232. define ( 'ACTIVITY_OBJ_TAGTERM', NAMESPACE_DFRN . '/tagterm' );
  233. define ( 'ACTIVITY_OBJ_PROFILE', NAMESPACE_DFRN . '/profile' );
  234. /**
  235. * item weight for query ordering
  236. */
  237. define ( 'GRAVITY_PARENT', 0);
  238. define ( 'GRAVITY_LIKE', 3);
  239. define ( 'GRAVITY_COMMENT', 6);
  240. /**
  241. *
  242. * Reverse the effect of magic_quotes_gpc if it is enabled.
  243. * Please disable magic_quotes_gpc so we don't have to do this.
  244. * See http://php.net/manual/en/security.magicquotes.disabling.php
  245. *
  246. */
  247. function startup() {
  248. error_reporting(E_ERROR | E_WARNING | E_PARSE);
  249. set_time_limit(0);
  250. // This has to be quite large to deal with embedded private photos
  251. ini_set('pcre.backtrack_limit', 500000);
  252. if (get_magic_quotes_gpc()) {
  253. $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
  254. while (list($key, $val) = each($process)) {
  255. foreach ($val as $k => $v) {
  256. unset($process[$key][$k]);
  257. if (is_array($v)) {
  258. $process[$key][stripslashes($k)] = $v;
  259. $process[] = &$process[$key][stripslashes($k)];
  260. } else {
  261. $process[$key][stripslashes($k)] = stripslashes($v);
  262. }
  263. }
  264. }
  265. unset($process);
  266. }
  267. }
  268. /**
  269. *
  270. * class: App
  271. *
  272. * Our main application structure for the life of this page
  273. * Primarily deals with the URL that got us here
  274. * and tries to make some sense of it, and
  275. * stores our page contents and config storage
  276. * and anything else that might need to be passed around
  277. * before we spit the page out.
  278. *
  279. */
  280. if(! class_exists('App')) {
  281. class App {
  282. public $module_loaded = false;
  283. public $query_string;
  284. public $config;
  285. public $page;
  286. public $profile;
  287. public $user;
  288. public $cid;
  289. public $contact;
  290. public $contacts;
  291. public $page_contact;
  292. public $content;
  293. public $data = array();
  294. public $error = false;
  295. public $cmd;
  296. public $argv;
  297. public $argc;
  298. public $module;
  299. public $pager;
  300. public $strings;
  301. public $path;
  302. public $hooks;
  303. public $timezone;
  304. public $interactive = true;
  305. public $plugins;
  306. public $apps = array();
  307. public $identities;
  308. public $is_mobile;
  309. public $is_tablet;
  310. public $performance = array();
  311. public $nav_sel;
  312. public $category;
  313. // Allow themes to control internal parameters
  314. // by changing App values in theme.php
  315. public $sourcename = '';
  316. public $videowidth = 425;
  317. public $videoheight = 350;
  318. public $force_max_items = 0;
  319. public $theme_thread_allow = true;
  320. // An array for all theme-controllable parameters
  321. // Mostly unimplemented yet. Only options 'stylesheet' and
  322. // beyond are used.
  323. public $theme = array(
  324. 'sourcename' => '',
  325. 'videowidth' => 425,
  326. 'videoheight' => 350,
  327. 'force_max_items' => 0,
  328. 'thread_allow' => true,
  329. 'stylesheet' => '',
  330. 'template_engine' => 'smarty3',
  331. );
  332. // array of registered template engines ('name'=>'class name')
  333. public $template_engines = array();
  334. // array of instanced template engines ('name'=>'instance')
  335. public $template_engine_instance = array();
  336. // Used for reducing load to the ostatus completion
  337. public $last_ostatus_conversation_url;
  338. private $ldelim = array(
  339. 'internal' => '',
  340. 'smarty3' => '{{'
  341. );
  342. private $rdelim = array(
  343. 'internal' => '',
  344. 'smarty3' => '}}'
  345. );
  346. private $scheme;
  347. private $hostname;
  348. private $baseurl;
  349. private $db;
  350. private $curl_code;
  351. private $curl_content_type;
  352. private $curl_headers;
  353. private $cached_profile_image;
  354. private $cached_profile_picdate;
  355. function __construct() {
  356. global $default_timezone, $argv, $argc;
  357. $hostname = "";
  358. if (file_exists(".htpreconfig.php"))
  359. @include(".htpreconfig.php");
  360. $this->timezone = ((x($default_timezone)) ? $default_timezone : 'UTC');
  361. date_default_timezone_set($this->timezone);
  362. $this->performance["start"] = microtime(true);
  363. $this->performance["database"] = 0;
  364. $this->performance["network"] = 0;
  365. $this->performance["file"] = 0;
  366. $this->performance["rendering"] = 0;
  367. $this->performance["parser"] = 0;
  368. $this->performance["marktime"] = 0;
  369. $this->performance["markstart"] = microtime(true);
  370. $this->config = array();
  371. $this->page = array();
  372. $this->pager= array();
  373. $this->query_string = '';
  374. startup();
  375. set_include_path(
  376. 'include' . PATH_SEPARATOR
  377. . 'library' . PATH_SEPARATOR
  378. . 'library/phpsec' . PATH_SEPARATOR
  379. . 'library/langdet' . PATH_SEPARATOR
  380. . '.' );
  381. $this->scheme = 'http';
  382. if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
  383. $this->scheme = 'https';
  384. elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
  385. $this->scheme = 'https';
  386. if(x($_SERVER,'SERVER_NAME')) {
  387. $this->hostname = $_SERVER['SERVER_NAME'];
  388. // See bug 437 - this didn't work so disabling it
  389. //if(stristr($this->hostname,'xn--')) {
  390. // PHP or webserver may have converted idn to punycode, so
  391. // convert punycode back to utf-8
  392. // require_once('library/simplepie/idn/idna_convert.class.php');
  393. // $x = new idna_convert();
  394. // $this->hostname = $x->decode($_SERVER['SERVER_NAME']);
  395. //}
  396. if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443)
  397. $this->hostname .= ':' . $_SERVER['SERVER_PORT'];
  398. /**
  399. * Figure out if we are running at the top of a domain
  400. * or in a sub-directory and adjust accordingly
  401. */
  402. $path = trim(dirname($_SERVER['SCRIPT_NAME']),'/\\');
  403. if(isset($path) && strlen($path) && ($path != $this->path))
  404. $this->path = $path;
  405. }
  406. if ($hostname != "")
  407. $this->hostname = $hostname;
  408. if (is_array($argv) && $argc>1 && substr(end($argv), 0, 4)=="http" ) {
  409. $this->set_baseurl(array_pop($argv) );
  410. $argc --;
  411. }
  412. set_include_path("include/$this->hostname" . PATH_SEPARATOR . get_include_path());
  413. if((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'],0,9) === "pagename=") {
  414. $this->query_string = substr($_SERVER['QUERY_STRING'],9);
  415. // removing trailing / - maybe a nginx problem
  416. if (substr($this->query_string, 0, 1) == "/")
  417. $this->query_string = substr($this->query_string, 1);
  418. } elseif((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'],0,2) === "q=") {
  419. $this->query_string = substr($_SERVER['QUERY_STRING'],2);
  420. // removing trailing / - maybe a nginx problem
  421. if (substr($this->query_string, 0, 1) == "/")
  422. $this->query_string = substr($this->query_string, 1);
  423. }
  424. if (x($_GET,'pagename'))
  425. $this->cmd = trim($_GET['pagename'],'/\\');
  426. elseif (x($_GET,'q'))
  427. $this->cmd = trim($_GET['q'],'/\\');
  428. // unix style "homedir"
  429. if(substr($this->cmd,0,1) === '~')
  430. $this->cmd = 'profile/' . substr($this->cmd,1);
  431. // Diaspora style profile url
  432. if(substr($this->cmd,0,2) === 'u/')
  433. $this->cmd = 'profile/' . substr($this->cmd,2);
  434. /**
  435. *
  436. * Break the URL path into C style argc/argv style arguments for our
  437. * modules. Given "http://example.com/module/arg1/arg2", $this->argc
  438. * will be 3 (integer) and $this->argv will contain:
  439. * [0] => 'module'
  440. * [1] => 'arg1'
  441. * [2] => 'arg2'
  442. *
  443. *
  444. * There will always be one argument. If provided a naked domain
  445. * URL, $this->argv[0] is set to "home".
  446. *
  447. */
  448. $this->argv = explode('/',$this->cmd);
  449. $this->argc = count($this->argv);
  450. if((array_key_exists('0',$this->argv)) && strlen($this->argv[0])) {
  451. $this->module = str_replace(".", "_", $this->argv[0]);
  452. $this->module = str_replace("-", "_", $this->module);
  453. }
  454. else {
  455. $this->argc = 1;
  456. $this->argv = array('home');
  457. $this->module = 'home';
  458. }
  459. /**
  460. * See if there is any page number information, and initialise
  461. * pagination
  462. */
  463. $this->pager['page'] = ((x($_GET,'page') && intval($_GET['page']) > 0) ? intval($_GET['page']) : 1);
  464. $this->pager['itemspage'] = 50;
  465. $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
  466. if($this->pager['start'] < 0)
  467. $this->pager['start'] = 0;
  468. $this->pager['total'] = 0;
  469. /**
  470. * Detect mobile devices
  471. */
  472. $mobile_detect = new Mobile_Detect();
  473. $this->is_mobile = $mobile_detect->isMobile();
  474. $this->is_tablet = $mobile_detect->isTablet();
  475. /**
  476. * register template engines
  477. */
  478. $dc = get_declared_classes();
  479. foreach ($dc as $k) {
  480. if (in_array("ITemplateEngine", class_implements($k))){
  481. $this->register_template_engine($k);
  482. }
  483. }
  484. }
  485. function get_basepath() {
  486. $basepath = get_config("system", "basepath");
  487. if ($basepath == "")
  488. $basepath = $_SERVER["DOCUMENT_ROOT"];
  489. if ($basepath == "")
  490. $basepath = $_SERVER["PWD"];
  491. return($basepath);
  492. }
  493. function get_baseurl($ssl = false) {
  494. $scheme = $this->scheme;
  495. if((x($this->config,'system')) && (x($this->config['system'],'ssl_policy'))) {
  496. if(intval($this->config['system']['ssl_policy']) === intval(SSL_POLICY_FULL))
  497. $scheme = 'https';
  498. // Basically, we have $ssl = true on any links which can only be seen by a logged in user
  499. // (and also the login link). Anything seen by an outsider will have it turned off.
  500. if($this->config['system']['ssl_policy'] == SSL_POLICY_SELFSIGN) {
  501. if($ssl)
  502. $scheme = 'https';
  503. else
  504. $scheme = 'http';
  505. }
  506. }
  507. $this->baseurl = $scheme . "://" . $this->hostname . ((isset($this->path) && strlen($this->path)) ? '/' . $this->path : '' );
  508. return $this->baseurl;
  509. }
  510. function set_baseurl($url) {
  511. $parsed = @parse_url($url);
  512. $this->baseurl = $url;
  513. if($parsed) {
  514. $this->scheme = $parsed['scheme'];
  515. $hostname = $parsed['host'];
  516. if(x($parsed,'port'))
  517. $hostname .= ':' . $parsed['port'];
  518. if(x($parsed,'path'))
  519. $this->path = trim($parsed['path'],'\\/');
  520. if (file_exists(".htpreconfig.php"))
  521. @include(".htpreconfig.php");
  522. $this->hostname = $hostname;
  523. }
  524. }
  525. function get_hostname() {
  526. return $this->hostname;
  527. }
  528. function set_hostname($h) {
  529. $this->hostname = $h;
  530. }
  531. function set_path($p) {
  532. $this->path = trim(trim($p),'/');
  533. }
  534. function get_path() {
  535. return $this->path;
  536. }
  537. function set_pager_total($n) {
  538. $this->pager['total'] = intval($n);
  539. }
  540. function set_pager_itemspage($n) {
  541. $this->pager['itemspage'] = ((intval($n) > 0) ? intval($n) : 0);
  542. $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
  543. }
  544. function set_pager_page($n) {
  545. $this->pager['page'] = $n;
  546. $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
  547. }
  548. function init_pagehead() {
  549. $interval = ((local_user()) ? get_pconfig(local_user(),'system','update_interval') : 40000);
  550. if($interval < 10000)
  551. $interval = 40000;
  552. $this->page['title'] = $this->config['sitename'];
  553. /* put the head template at the beginning of page['htmlhead']
  554. * since the code added by the modules frequently depends on it
  555. * being first
  556. */
  557. if(!isset($this->page['htmlhead']))
  558. $this->page['htmlhead'] = '';
  559. // If we're using Smarty, then doing replace_macros() will replace
  560. // any unrecognized variables with a blank string. Since we delay
  561. // replacing $stylesheet until later, we need to replace it now
  562. // with another variable name
  563. if($this->theme['template_engine'] === 'smarty3')
  564. $stylesheet = $this->get_template_ldelim('smarty3') . '$stylesheet' . $this->get_template_rdelim('smarty3');
  565. else
  566. $stylesheet = '$stylesheet';
  567. $shortcut_icon = get_config("system", "shortcut_icon");
  568. if ($shortcut_icon == "")
  569. $shortcut_icon = $this->get_baseurl()."/images/friendica-32.png";
  570. $touch_icon = get_config("system", "touch_icon");
  571. if ($touch_icon == "")
  572. $touch_icon = $this->get_baseurl()."/images/friendica-128.png";
  573. $tpl = get_markup_template('head.tpl');
  574. $this->page['htmlhead'] = replace_macros($tpl,array(
  575. '$baseurl' => $this->get_baseurl(), // FIXME for z_path!!!!
  576. '$local_user' => local_user(),
  577. '$generator' => 'Friendica' . ' ' . FRIENDICA_VERSION,
  578. '$delitem' => t('Delete this item?'),
  579. '$comment' => t('Comment'),
  580. '$showmore' => t('show more'),
  581. '$showfewer' => t('show fewer'),
  582. '$update_interval' => $interval,
  583. '$shortcut_icon' => $shortcut_icon,
  584. '$touch_icon' => $touch_icon,
  585. '$stylesheet' => $stylesheet
  586. )) . $this->page['htmlhead'];
  587. }
  588. function init_page_end() {
  589. if(!isset($this->page['end']))
  590. $this->page['end'] = '';
  591. $tpl = get_markup_template('end.tpl');
  592. $this->page['end'] = replace_macros($tpl,array(
  593. '$baseurl' => $this->get_baseurl() // FIXME for z_path!!!!
  594. )) . $this->page['end'];
  595. }
  596. function set_curl_code($code) {
  597. $this->curl_code = $code;
  598. }
  599. function get_curl_code() {
  600. return $this->curl_code;
  601. }
  602. function set_curl_content_type($content_type) {
  603. $this->curl_content_type = $content_type;
  604. }
  605. function get_curl_content_type() {
  606. return $this->curl_content_type;
  607. }
  608. function set_curl_headers($headers) {
  609. $this->curl_headers = $headers;
  610. }
  611. function get_curl_headers() {
  612. return $this->curl_headers;
  613. }
  614. function get_cached_avatar_image($avatar_image){
  615. if($this->cached_profile_image[$avatar_image])
  616. return $this->cached_profile_image[$avatar_image];
  617. $path_parts = explode("/",$avatar_image);
  618. $common_filename = $path_parts[count($path_parts)-1];
  619. if($this->cached_profile_picdate[$common_filename]){
  620. $this->cached_profile_image[$avatar_image] = $avatar_image . $this->cached_profile_picdate[$common_filename];
  621. } else {
  622. $r = q("SELECT `contact`.`avatar-date` AS picdate FROM `contact` WHERE `contact`.`thumb` like '%%/%s'",
  623. $common_filename);
  624. if(! count($r)){
  625. $this->cached_profile_image[$avatar_image] = $avatar_image;
  626. } else {
  627. $this->cached_profile_picdate[$common_filename] = "?rev=".urlencode($r[0]['picdate']);
  628. $this->cached_profile_image[$avatar_image] = $avatar_image.$this->cached_profile_picdate[$common_filename];
  629. }
  630. }
  631. return $this->cached_profile_image[$avatar_image];
  632. }
  633. /**
  634. * register template engine class
  635. * if $name is "", is used class static property $class::$name
  636. * @param string $class
  637. * @param string $name
  638. */
  639. function register_template_engine($class, $name = '') {
  640. if ($name===""){
  641. $v = get_class_vars( $class );
  642. if(x($v,"name")) $name = $v['name'];
  643. }
  644. if ($name===""){
  645. echo "template engine <tt>$class</tt> cannot be registered without a name.\n";
  646. killme();
  647. }
  648. $this->template_engines[$name] = $class;
  649. }
  650. /**
  651. * return template engine instance. If $name is not defined,
  652. * return engine defined by theme, or default
  653. *
  654. * @param strin $name Template engine name
  655. * @return object Template Engine instance
  656. */
  657. function template_engine($name = ''){
  658. if ($name!=="") {
  659. $template_engine = $name;
  660. } else {
  661. $template_engine = 'smarty3';
  662. if (x($this->theme, 'template_engine')) {
  663. $template_engine = $this->theme['template_engine'];
  664. }
  665. }
  666. if (isset($this->template_engines[$template_engine])){
  667. if(isset($this->template_engine_instance[$template_engine])){
  668. return $this->template_engine_instance[$template_engine];
  669. } else {
  670. $class = $this->template_engines[$template_engine];
  671. $obj = new $class;
  672. $this->template_engine_instance[$template_engine] = $obj;
  673. return $obj;
  674. }
  675. }
  676. echo "template engine <tt>$template_engine</tt> is not registered!\n"; killme();
  677. }
  678. function get_template_engine() {
  679. return $this->theme['template_engine'];
  680. }
  681. function set_template_engine($engine = 'smarty3') {
  682. $this->theme['template_engine'] = $engine;
  683. /*
  684. $this->theme['template_engine'] = 'smarty3';
  685. switch($engine) {
  686. case 'smarty3':
  687. if(is_writable('view/smarty3/'))
  688. $this->theme['template_engine'] = 'smarty3';
  689. break;
  690. default:
  691. break;
  692. }
  693. */
  694. }
  695. function get_template_ldelim($engine = 'smarty3') {
  696. return $this->ldelim[$engine];
  697. }
  698. function get_template_rdelim($engine = 'smarty3') {
  699. return $this->rdelim[$engine];
  700. }
  701. function save_timestamp($stamp, $value) {
  702. $duration = (float)(microtime(true)-$stamp);
  703. $this->performance[$value] += (float)$duration;
  704. $this->performance["marktime"] += (float)$duration;
  705. }
  706. function mark_timestamp($mark) {
  707. //$this->performance["markstart"] -= microtime(true) - $this->performance["marktime"];
  708. $this->performance["markstart"] = microtime(true) - $this->performance["markstart"] - $this->performance["marktime"];
  709. }
  710. function get_useragent() {
  711. return(FRIENDICA_PLATFORM." ".FRIENDICA_VERSION."-".DB_UPDATE_VERSION."; ".$this->get_baseurl());
  712. }
  713. }
  714. }
  715. // retrieve the App structure
  716. // useful in functions which require it but don't get it passed to them
  717. if(! function_exists('get_app')) {
  718. function get_app() {
  719. global $a;
  720. return $a;
  721. }
  722. };
  723. // Multi-purpose function to check variable state.
  724. // Usage: x($var) or $x($array,'key')
  725. // returns false if variable/key is not set
  726. // if variable is set, returns 1 if has 'non-zero' value, otherwise returns 0.
  727. // e.g. x('') or x(0) returns 0;
  728. if(! function_exists('x')) {
  729. function x($s,$k = NULL) {
  730. if($k != NULL) {
  731. if((is_array($s)) && (array_key_exists($k,$s))) {
  732. if($s[$k])
  733. return (int) 1;
  734. return (int) 0;
  735. }
  736. return false;
  737. }
  738. else {
  739. if(isset($s)) {
  740. if($s) {
  741. return (int) 1;
  742. }
  743. return (int) 0;
  744. }
  745. return false;
  746. }
  747. }
  748. }
  749. // called from db initialisation if db is dead.
  750. if(! function_exists('system_unavailable')) {
  751. function system_unavailable() {
  752. include('system_unavailable.php');
  753. system_down();
  754. killme();
  755. }
  756. }
  757. function clean_urls() {
  758. global $a;
  759. // if($a->config['system']['clean_urls'])
  760. return true;
  761. // return false;
  762. }
  763. function z_path() {
  764. global $a;
  765. $base = $a->get_baseurl();
  766. if(! clean_urls())
  767. $base .= '/?q=';
  768. return $base;
  769. }
  770. function z_root() {
  771. global $a;
  772. return $a->get_baseurl();
  773. }
  774. function absurl($path) {
  775. if(strpos($path,'/') === 0)
  776. return z_path() . $path;
  777. return $path;
  778. }
  779. function is_ajax() {
  780. return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
  781. }
  782. function check_db() {
  783. $build = get_config('system','build');
  784. if(! x($build)) {
  785. set_config('system','build',DB_UPDATE_VERSION);
  786. $build = DB_UPDATE_VERSION;
  787. }
  788. if($build != DB_UPDATE_VERSION)
  789. proc_run('php', 'include/dbupdate.php');
  790. }
  791. // Sets the base url for use in cmdline programs which don't have
  792. // $_SERVER variables
  793. if(! function_exists('check_url')) {
  794. function check_url(&$a) {
  795. $url = get_config('system','url');
  796. // if the url isn't set or the stored url is radically different
  797. // than the currently visited url, store the current value accordingly.
  798. // "Radically different" ignores common variations such as http vs https
  799. // and www.example.com vs example.com.
  800. // We will only change the url to an ip address if there is no existing setting
  801. if(! x($url))
  802. $url = set_config('system','url',$a->get_baseurl());
  803. if((! link_compare($url,$a->get_baseurl())) && (! preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$a->get_hostname)))
  804. $url = set_config('system','url',$a->get_baseurl());
  805. return;
  806. }
  807. }
  808. // Automatic database updates
  809. if(! function_exists('update_db')) {
  810. function update_db(&$a) {
  811. $build = get_config('system','build');
  812. if(! x($build))
  813. $build = set_config('system','build',DB_UPDATE_VERSION);
  814. if($build != DB_UPDATE_VERSION) {
  815. $stored = intval($build);
  816. $current = intval(DB_UPDATE_VERSION);
  817. if($stored < $current) {
  818. load_config('database');
  819. // We're reporting a different version than what is currently installed.
  820. // Run any existing update scripts to bring the database up to current.
  821. // make sure that boot.php and update.php are the same release, we might be
  822. // updating right this very second and the correct version of the update.php
  823. // file may not be here yet. This can happen on a very busy site.
  824. if(DB_UPDATE_VERSION == UPDATE_VERSION) {
  825. // Compare the current structure with the defined structure
  826. $t = get_config('database','dbupdate_'.DB_UPDATE_VERSION);
  827. if($t !== false)
  828. return;
  829. set_config('database','dbupdate_'.DB_UPDATE_VERSION, time());
  830. // run old update routine (wich could modify the schema and
  831. // conflits with new routine)
  832. for ($x = $stored; $x < NEW_UPDATE_ROUTINE_VERSION; $x++) {
  833. $r = run_update_function($x);
  834. if (!$r) break;
  835. }
  836. if ($stored < NEW_UPDATE_ROUTINE_VERSION) $stored = NEW_UPDATE_ROUTINE_VERSION;
  837. // run new update routine
  838. // it update the structure in one call
  839. $retval = update_structure(false, true);
  840. if($retval) {
  841. update_fail(
  842. DB_UPDATE_VERSION,
  843. $retval
  844. );
  845. return;
  846. } else {
  847. set_config('database','dbupdate_'.DB_UPDATE_VERSION, 'success');
  848. }
  849. // run any left update_nnnn functions in update.php
  850. for($x = $stored; $x < $current; $x ++) {
  851. $r = run_update_function($x);
  852. if (!$r) break;
  853. }
  854. }
  855. }
  856. }
  857. return;
  858. }
  859. }
  860. if(!function_exists('run_update_function')){
  861. function run_update_function($x) {
  862. if(function_exists('update_' . $x)) {
  863. // There could be a lot of processes running or about to run.
  864. // We want exactly one process to run the update command.
  865. // So store the fact that we're taking responsibility
  866. // after first checking to see if somebody else already has.
  867. // If the update fails or times-out completely you may need to
  868. // delete the config entry to try again.
  869. $t = get_config('database','update_' . $x);
  870. if($t !== false)
  871. return false;
  872. set_config('database','update_' . $x, time());
  873. // call the specific update
  874. $func = 'update_' . $x;
  875. $retval = $func();
  876. if($retval) {
  877. //send the administrator an e-mail
  878. update_fail(
  879. $x,
  880. sprintf(t('Update %s failed. See error logs.'), $x)
  881. );
  882. return false;
  883. } else {
  884. set_config('database','update_' . $x, 'success');
  885. set_config('system','build', $x + 1);
  886. return true;
  887. }
  888. } else {
  889. set_config('database','update_' . $x, 'success');
  890. set_config('system','build', $x + 1);
  891. return true;
  892. }
  893. return true;
  894. }
  895. }
  896. if(! function_exists('check_plugins')) {
  897. function check_plugins(&$a)