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.

2334 lines
60 KiB

11 years ago
11 years ago
10 years ago
6 years ago
11 years ago
10 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
10 years ago
10 years ago
9 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
9 years ago
9 years ago
9 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
10 years ago
11 years ago
11 years ago
11 years ago
6 years ago
6 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
11 years ago
11 years ago
6 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
10 years ago
10 years ago
10 years ago
10 years ago
6 years ago
6 years ago
11 years ago
  1. <?php
  2. /** @file boot.php
  3. *
  4. * This file defines some global constants and includes the central App class.
  5. */
  6. /**
  7. * Friendica
  8. *
  9. * Friendica is a communications platform for integrated social communications
  10. * utilising decentralised communications and linkage to several indie social
  11. * projects - as well as popular mainstream providers.
  12. *
  13. * Our mission is to free our friends and families from the clutches of
  14. * data-harvesting corporations, and pave the way to a future where social
  15. * communications are free and open and flow between alternate providers as
  16. * easily as email does today.
  17. */
  18. require_once('include/autoloader.php');
  19. require_once('include/config.php');
  20. require_once('include/network.php');
  21. require_once('include/plugin.php');
  22. require_once('include/text.php');
  23. require_once('include/datetime.php');
  24. require_once('include/pgettext.php');
  25. require_once('include/nav.php');
  26. require_once('include/cache.php');
  27. require_once('library/Mobile_Detect/Mobile_Detect.php');
  28. require_once('include/features.php');
  29. require_once('include/identity.php');
  30. require_once('include/pidfile.php');
  31. require_once('update.php');
  32. require_once('include/dbstructure.php');
  33. define ( 'FRIENDICA_PLATFORM', 'Friendica');
  34. define ( 'FRIENDICA_CODENAME', 'Asparagus');
  35. define ( 'FRIENDICA_VERSION', '3.5-dev' );
  36. define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
  37. define ( 'DB_UPDATE_VERSION', 1199 );
  38. /**
  39. * @brief Constant with a HTML line break.
  40. *
  41. * Contains a HTML line break (br) element and a real carriage return with line
  42. * feed for the source.
  43. * This can be used in HTML and JavaScript where needed a line break.
  44. */
  45. define ( 'EOL', "<br />\r\n" );
  46. define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
  47. /**
  48. * @brief Image storage quality.
  49. *
  50. * Lower numbers save space at cost of image detail.
  51. * For ease of upgrade, please do not change here. Change jpeg quality with
  52. * $a->config['system']['jpeg_quality'] = n;
  53. * in .htconfig.php, where n is netween 1 and 100, and with very poor results
  54. * below about 50
  55. *
  56. */
  57. define ( 'JPEG_QUALITY', 100 );
  58. /**
  59. * $a->config['system']['png_quality'] from 0 (uncompressed) to 9
  60. */
  61. define ( 'PNG_QUALITY', 8 );
  62. /**
  63. *
  64. * An alternate way of limiting picture upload sizes. Specify the maximum pixel
  65. * length that pictures are allowed to be (for non-square pictures, it will apply
  66. * to the longest side). Pictures longer than this length will be resized to be
  67. * this length (on the longest side, the other side will be scaled appropriately).
  68. * Modify this value using
  69. *
  70. * $a->config['system']['max_image_length'] = n;
  71. *
  72. * in .htconfig.php
  73. *
  74. * If you don't want to set a maximum length, set to -1. The default value is
  75. * defined by 'MAX_IMAGE_LENGTH' below.
  76. *
  77. */
  78. define ( 'MAX_IMAGE_LENGTH', -1 );
  79. /**
  80. * Not yet used
  81. */
  82. define ( 'DEFAULT_DB_ENGINE', 'MyISAM' );
  83. /**
  84. * @name SSL Policy
  85. *
  86. * SSL redirection policies
  87. * @{
  88. */
  89. define ( 'SSL_POLICY_NONE', 0 );
  90. define ( 'SSL_POLICY_FULL', 1 );
  91. define ( 'SSL_POLICY_SELFSIGN', 2 );
  92. /* @}*/
  93. /**
  94. * @name Logger
  95. *
  96. * log levels
  97. * @{
  98. */
  99. define ( 'LOGGER_NORMAL', 0 );
  100. define ( 'LOGGER_TRACE', 1 );
  101. define ( 'LOGGER_DEBUG', 2 );
  102. define ( 'LOGGER_DATA', 3 );
  103. define ( 'LOGGER_ALL', 4 );
  104. /* @}*/
  105. /**
  106. * @name Cache
  107. *
  108. * Cache levels
  109. * @{
  110. */
  111. define ( 'CACHE_MONTH', 0 );
  112. define ( 'CACHE_WEEK', 1 );
  113. define ( 'CACHE_DAY', 2 );
  114. define ( 'CACHE_HOUR', 3 );
  115. /* @}*/
  116. /**
  117. * @name Register
  118. *
  119. * Registration policies
  120. * @{
  121. */
  122. define ( 'REGISTER_CLOSED', 0 );
  123. define ( 'REGISTER_APPROVE', 1 );
  124. define ( 'REGISTER_OPEN', 2 );
  125. /** @}*/
  126. /**
  127. * @name Contact_is
  128. *
  129. * Relationship types
  130. * @{
  131. */
  132. define ( 'CONTACT_IS_FOLLOWER', 1);
  133. define ( 'CONTACT_IS_SHARING', 2);
  134. define ( 'CONTACT_IS_FRIEND', 3);
  135. /** @}*/
  136. /**
  137. * @name Update
  138. *
  139. * DB update return values
  140. * @{
  141. */
  142. define ( 'UPDATE_SUCCESS', 0);
  143. define ( 'UPDATE_FAILED', 1);
  144. /** @}*/
  145. /**
  146. * @name page/profile types
  147. *
  148. * PAGE_NORMAL is a typical personal profile account
  149. * PAGE_SOAPBOX automatically approves all friend requests as CONTACT_IS_SHARING, (readonly)
  150. * PAGE_COMMUNITY automatically approves all friend requests as CONTACT_IS_SHARING, but with
  151. * write access to wall and comments (no email and not included in page owner's ACL lists)
  152. * PAGE_FREELOVE automatically approves all friend requests as full friends (CONTACT_IS_FRIEND).
  153. *
  154. * @{
  155. */
  156. define ( 'PAGE_NORMAL', 0 );
  157. define ( 'PAGE_SOAPBOX', 1 );
  158. define ( 'PAGE_COMMUNITY', 2 );
  159. define ( 'PAGE_FREELOVE', 3 );
  160. define ( 'PAGE_BLOG', 4 );
  161. define ( 'PAGE_PRVGROUP', 5 );
  162. /** @}*/
  163. /**
  164. * @name CP
  165. *
  166. * Type of the community page
  167. * @{
  168. */
  169. define ( 'CP_NO_COMMUNITY_PAGE', -1 );
  170. define ( 'CP_USERS_ON_SERVER', 0 );
  171. define ( 'CP_GLOBAL_COMMUNITY', 1 );
  172. /** @}*/
  173. /**
  174. * @name Network
  175. *
  176. * Network and protocol family types
  177. * @{
  178. */
  179. define ( 'NETWORK_DFRN', 'dfrn'); // Friendica, Mistpark, other DFRN implementations
  180. define ( 'NETWORK_ZOT', 'zot!'); // Zot!
  181. define ( 'NETWORK_OSTATUS', 'stat'); // status.net, identi.ca, GNU-social, other OStatus implementations
  182. define ( 'NETWORK_FEED', 'feed'); // RSS/Atom feeds with no known "post/notify" protocol
  183. define ( 'NETWORK_DIASPORA', 'dspr'); // Diaspora
  184. define ( 'NETWORK_MAIL', 'mail'); // IMAP/POP
  185. define ( 'NETWORK_MAIL2', 'mai2'); // extended IMAP/POP
  186. define ( 'NETWORK_FACEBOOK', 'face'); // Facebook API
  187. define ( 'NETWORK_LINKEDIN', 'lnkd'); // LinkedIn
  188. define ( 'NETWORK_XMPP', 'xmpp'); // XMPP
  189. define ( 'NETWORK_MYSPACE', 'mysp'); // MySpace
  190. define ( 'NETWORK_GPLUS', 'goog'); // Google+
  191. define ( 'NETWORK_PUMPIO', 'pump'); // pump.io
  192. define ( 'NETWORK_TWITTER', 'twit'); // Twitter
  193. define ( 'NETWORK_DIASPORA2', 'dspc'); // Diaspora connector
  194. define ( 'NETWORK_STATUSNET', 'stac'); // Statusnet connector
  195. define ( 'NETWORK_APPNET', 'apdn'); // app.net
  196. define ( 'NETWORK_NEWS', 'nntp'); // Network News Transfer Protocol
  197. define ( 'NETWORK_ICALENDAR', 'ical'); // iCalendar
  198. define ( 'NETWORK_PHANTOM', 'unkn'); // Place holder
  199. /** @}*/
  200. /**
  201. * These numbers are used in stored permissions
  202. * and existing allocations MUST NEVER BE CHANGED
  203. * OR RE-ASSIGNED! You may only add to them.
  204. */
  205. $netgroup_ids = array(
  206. NETWORK_DFRN => (-1),
  207. NETWORK_ZOT => (-2),
  208. NETWORK_OSTATUS => (-3),
  209. NETWORK_FEED => (-4),
  210. NETWORK_DIASPORA => (-5),
  211. NETWORK_MAIL => (-6),
  212. NETWORK_MAIL2 => (-7),
  213. NETWORK_FACEBOOK => (-8),
  214. NETWORK_LINKEDIN => (-9),
  215. NETWORK_XMPP => (-10),
  216. NETWORK_MYSPACE => (-11),
  217. NETWORK_GPLUS => (-12),
  218. NETWORK_PUMPIO => (-13),
  219. NETWORK_TWITTER => (-14),
  220. NETWORK_DIASPORA2 => (-15),
  221. NETWORK_STATUSNET => (-16),
  222. NETWORK_APPNET => (-17),
  223. NETWORK_NEWS => (-18),
  224. NETWORK_ICALENDAR => (-19),
  225. NETWORK_PHANTOM => (-127),
  226. );
  227. /**
  228. * Maximum number of "people who like (or don't like) this" that we will list by name
  229. */
  230. define ( 'MAX_LIKERS', 75);
  231. /**
  232. * Communication timeout
  233. */
  234. define ( 'ZCURL_TIMEOUT' , (-1));
  235. /**
  236. * @name Notify
  237. *
  238. * Email notification options
  239. * @{
  240. */
  241. define ( 'NOTIFY_INTRO', 0x0001 );
  242. define ( 'NOTIFY_CONFIRM', 0x0002 );
  243. define ( 'NOTIFY_WALL', 0x0004 );
  244. define ( 'NOTIFY_COMMENT', 0x0008 );
  245. define ( 'NOTIFY_MAIL', 0x0010 );
  246. define ( 'NOTIFY_SUGGEST', 0x0020 );
  247. define ( 'NOTIFY_PROFILE', 0x0040 );
  248. define ( 'NOTIFY_TAGSELF', 0x0080 );
  249. define ( 'NOTIFY_TAGSHARE', 0x0100 );
  250. define ( 'NOTIFY_POKE', 0x0200 );
  251. define ( 'NOTIFY_SHARE', 0x0400 );
  252. define ( 'NOTIFY_SYSTEM', 0x8000 );
  253. /* @}*/
  254. /**
  255. * @name Term
  256. *
  257. * Tag/term types
  258. * @{
  259. */
  260. define ( 'TERM_UNKNOWN', 0 );
  261. define ( 'TERM_HASHTAG', 1 );
  262. define ( 'TERM_MENTION', 2 );
  263. define ( 'TERM_CATEGORY', 3 );
  264. define ( 'TERM_PCATEGORY', 4 );
  265. define ( 'TERM_FILE', 5 );
  266. define ( 'TERM_SAVEDSEARCH', 6 );
  267. define ( 'TERM_CONVERSATION', 7 );
  268. define ( 'TERM_OBJ_POST', 1 );
  269. define ( 'TERM_OBJ_PHOTO', 2 );
  270. /**
  271. * @name Namespaces
  272. *
  273. * Various namespaces we may need to parse
  274. * @{
  275. */
  276. define ( 'NAMESPACE_ZOT', 'http://purl.org/zot' );
  277. define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' );
  278. define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' );
  279. define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' );
  280. define ( 'NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/' );
  281. define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' );
  282. define ( 'NAMESPACE_MEDIA', 'http://purl.org/syndication/atommedia' );
  283. define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env' );
  284. define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe' );
  285. define ( 'NAMESPACE_GEORSS', 'http://www.georss.org/georss' );
  286. define ( 'NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0' );
  287. define ( 'NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from' );
  288. define ( 'NAMESPACE_OSTATUS', 'http://ostatus.org/schema/1.0' );
  289. define ( 'NAMESPACE_STATUSNET', 'http://status.net/schema/api/1/' );
  290. define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
  291. /* @}*/
  292. /**
  293. * @name Activity
  294. *
  295. * Activity stream defines
  296. * @{
  297. */
  298. define ( 'ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like' );
  299. define ( 'ACTIVITY_DISLIKE', NAMESPACE_DFRN . '/dislike' );
  300. define ( 'ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes' );
  301. define ( 'ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno' );
  302. define ( 'ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe' );
  303. define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_DFRN . '/heart' );
  304. define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
  305. define ( 'ACTIVITY_REQ_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'request-friend' );
  306. define ( 'ACTIVITY_UNFRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'remove-friend' );
  307. define ( 'ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow' );
  308. define ( 'ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'stop-following' );
  309. define ( 'ACTIVITY_JOIN', NAMESPACE_ACTIVITY_SCHEMA . 'join' );
  310. define ( 'ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post' );
  311. define ( 'ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update' );
  312. define ( 'ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag' );
  313. define ( 'ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite' );
  314. define ( 'ACTIVITY_SHARE', NAMESPACE_ACTIVITY_SCHEMA . 'share' );
  315. define ( 'ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke' );
  316. define ( 'ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood' );
  317. define ( 'ACTIVITY_OBJ_BOOKMARK', NAMESPACE_ACTIVITY_SCHEMA . 'bookmark' );
  318. define ( 'ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment' );
  319. define ( 'ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note' );
  320. define ( 'ACTIVITY_OBJ_PERSON', NAMESPACE_ACTIVITY_SCHEMA . 'person' );
  321. define ( 'ACTIVITY_OBJ_IMAGE', NAMESPACE_ACTIVITY_SCHEMA . 'image' );
  322. define ( 'ACTIVITY_OBJ_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'photo' );
  323. define ( 'ACTIVITY_OBJ_VIDEO', NAMESPACE_ACTIVITY_SCHEMA . 'video' );
  324. define ( 'ACTIVITY_OBJ_P_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'profile-photo' );
  325. define ( 'ACTIVITY_OBJ_ALBUM', NAMESPACE_ACTIVITY_SCHEMA . 'photo-album' );
  326. define ( 'ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event' );
  327. define ( 'ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group' );
  328. define ( 'ACTIVITY_OBJ_TAGTERM', NAMESPACE_DFRN . '/tagterm' );
  329. define ( 'ACTIVITY_OBJ_PROFILE', NAMESPACE_DFRN . '/profile' );
  330. define ( 'ACTIVITY_OBJ_QUESTION', 'http://activityschema.org/object/question' );
  331. /* @}*/
  332. /**
  333. * @name Gravity
  334. *
  335. * Item weight for query ordering
  336. * @{
  337. */
  338. define ( 'GRAVITY_PARENT', 0);
  339. define ( 'GRAVITY_LIKE', 3);
  340. define ( 'GRAVITY_COMMENT', 6);
  341. /* @}*/
  342. // Normally this constant is defined - but not if "pcntl" isn't installed
  343. if (!defined("SIGTERM"))
  344. define("SIGTERM", 15);
  345. /**
  346. *
  347. * Reverse the effect of magic_quotes_gpc if it is enabled.
  348. * Please disable magic_quotes_gpc so we don't have to do this.
  349. * See http://php.net/manual/en/security.magicquotes.disabling.php
  350. *
  351. */
  352. function startup() {
  353. error_reporting(E_ERROR | E_WARNING | E_PARSE);
  354. set_time_limit(0);
  355. // This has to be quite large to deal with embedded private photos
  356. ini_set('pcre.backtrack_limit', 500000);
  357. if (get_magic_quotes_gpc()) {
  358. $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
  359. while (list($key, $val) = each($process)) {
  360. foreach ($val as $k => $v) {
  361. unset($process[$key][$k]);
  362. if (is_array($v)) {
  363. $process[$key][stripslashes($k)] = $v;
  364. $process[] = &$process[$key][stripslashes($k)];
  365. } else {
  366. $process[$key][stripslashes($k)] = stripslashes($v);
  367. }
  368. }
  369. }
  370. unset($process);
  371. }
  372. }
  373. /**
  374. *
  375. * class: App
  376. *
  377. * @brief Our main application structure for the life of this page.
  378. *
  379. * Primarily deals with the URL that got us here
  380. * and tries to make some sense of it, and
  381. * stores our page contents and config storage
  382. * and anything else that might need to be passed around
  383. * before we spit the page out.
  384. *
  385. */
  386. class App {
  387. public $module_loaded = false;
  388. public $query_string;
  389. public $config;
  390. public $page;
  391. public $profile;
  392. public $profile_uid;
  393. public $user;
  394. public $cid;
  395. public $contact;
  396. public $contacts;
  397. public $page_contact;
  398. public $content;
  399. public $data = array();
  400. public $error = false;
  401. public $cmd;
  402. public $argv;
  403. public $argc;
  404. public $module;
  405. public $pager;
  406. public $strings;
  407. public $path;
  408. public $hooks;
  409. public $timezone;
  410. public $interactive = true;
  411. public $plugins;
  412. public $apps = array();
  413. public $identities;
  414. public $is_mobile = false;
  415. public $is_tablet = false;
  416. public $is_friendica_app;
  417. public $performance = array();
  418. public $callstack = array();
  419. public $theme_info = array();
  420. public $backend = true;
  421. public $nav_sel;
  422. public $category;
  423. // Allow themes to control internal parameters
  424. // by changing App values in theme.php
  425. public $sourcename = '';
  426. public $videowidth = 425;
  427. public $videoheight = 350;
  428. public $force_max_items = 0;
  429. public $theme_thread_allow = true;
  430. public $theme_events_in_profile = true;
  431. /**
  432. * @brief An array for all theme-controllable parameters
  433. *
  434. * Mostly unimplemented yet. Only options 'template_engine' and
  435. * beyond are used.
  436. */
  437. public $theme = array(
  438. 'sourcename' => '',
  439. 'videowidth' => 425,
  440. 'videoheight' => 350,
  441. 'force_max_items' => 0,
  442. 'thread_allow' => true,
  443. 'stylesheet' => '',
  444. 'template_engine' => 'smarty3',
  445. );
  446. /**
  447. * @brief An array of registered template engines ('name'=>'class name')
  448. */
  449. public $template_engines = array();
  450. /**
  451. * @brief An array of instanced template engines ('name'=>'instance')
  452. */
  453. public $template_engine_instance = array();
  454. public $process_id;
  455. private $ldelim = array(
  456. 'internal' => '',
  457. 'smarty3' => '{{'
  458. );
  459. private $rdelim = array(
  460. 'internal' => '',
  461. 'smarty3' => '}}'
  462. );
  463. private $scheme;
  464. private $hostname;
  465. private $baseurl;
  466. private $db;
  467. private $curl_code;
  468. private $curl_content_type;
  469. private $curl_headers;
  470. private $cached_profile_image;
  471. private $cached_profile_picdate;
  472. private static $a;
  473. /**
  474. * @brief App constructor.
  475. */
  476. function __construct() {
  477. global $default_timezone;
  478. $hostname = "";
  479. if (file_exists(".htpreconfig.php"))
  480. @include(".htpreconfig.php");
  481. $this->timezone = ((x($default_timezone)) ? $default_timezone : 'UTC');
  482. date_default_timezone_set($this->timezone);
  483. $this->performance["start"] = microtime(true);
  484. $this->performance["database"] = 0;
  485. $this->performance["network"] = 0;
  486. $this->performance["file"] = 0;
  487. $this->performance["rendering"] = 0;
  488. $this->performance["parser"] = 0;
  489. $this->performance["marktime"] = 0;
  490. $this->performance["markstart"] = microtime(true);
  491. $this->callstack["database"] = array();
  492. $this->callstack["network"] = array();
  493. $this->callstack["file"] = array();
  494. $this->callstack["rendering"] = array();
  495. $this->callstack["parser"] = array();
  496. $this->config = array();
  497. $this->page = array();
  498. $this->pager= array();
  499. $this->query_string = '';
  500. $this->process_id = uniqid("log", true);
  501. startup();
  502. set_include_path(
  503. 'include' . PATH_SEPARATOR
  504. . 'library' . PATH_SEPARATOR
  505. . 'library/phpsec' . PATH_SEPARATOR
  506. . 'library/langdet' . PATH_SEPARATOR
  507. . '.' );
  508. $this->scheme = 'http';
  509. if((x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) ||
  510. (x($_SERVER['HTTP_FORWARDED']) && preg_match("/proto=https/", $_SERVER['HTTP_FORWARDED'])) ||
  511. (x($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
  512. (x($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') ||
  513. (x($_SERVER['FRONT_END_HTTPS']) && $_SERVER['FRONT_END_HTTPS'] == 'on') ||
  514. (x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) // XXX: reasonable assumption, but isn't this hardcoding too much?
  515. ) {
  516. $this->scheme = 'https';
  517. }
  518. if(x($_SERVER,'SERVER_NAME')) {
  519. $this->hostname = $_SERVER['SERVER_NAME'];
  520. if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443)
  521. $this->hostname .= ':' . $_SERVER['SERVER_PORT'];
  522. /*
  523. * Figure out if we are running at the top of a domain
  524. * or in a sub-directory and adjust accordingly
  525. */
  526. $path = trim(dirname($_SERVER['SCRIPT_NAME']),'/\\');
  527. if(isset($path) && strlen($path) && ($path != $this->path))
  528. $this->path = $path;
  529. }
  530. if ($hostname != "")
  531. $this->hostname = $hostname;
  532. if (is_array($_SERVER["argv"]) && $_SERVER["argc"]>1 && substr(end($_SERVER["argv"]), 0, 4)=="http" ) {
  533. $this->set_baseurl(array_pop($_SERVER["argv"]) );
  534. $_SERVER["argc"] --;
  535. }
  536. #set_include_path("include/$this->hostname" . PATH_SEPARATOR . get_include_path());
  537. if((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'],0,9) === "pagename=") {
  538. $this->query_string = substr($_SERVER['QUERY_STRING'],9);
  539. // removing trailing / - maybe a nginx problem
  540. if (substr($this->query_string, 0, 1) == "/")
  541. $this->query_string = substr($this->query_string, 1);
  542. } elseif((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'],0,2) === "q=") {
  543. $this->query_string = substr($_SERVER['QUERY_STRING'],2);
  544. // removing trailing / - maybe a nginx problem
  545. if (substr($this->query_string, 0, 1) == "/")
  546. $this->query_string = substr($this->query_string, 1);
  547. }
  548. if (x($_GET,'pagename'))
  549. $this->cmd = trim($_GET['pagename'],'/\\');
  550. elseif (x($_GET,'q'))
  551. $this->cmd = trim($_GET['q'],'/\\');
  552. // fix query_string
  553. $this->query_string = str_replace($this->cmd."&",$this->cmd."?", $this->query_string);
  554. // unix style "homedir"
  555. if(substr($this->cmd,0,1) === '~')
  556. $this->cmd = 'profile/' . substr($this->cmd,1);
  557. // Diaspora style profile url
  558. if(substr($this->cmd,0,2) === 'u/')
  559. $this->cmd = 'profile/' . substr($this->cmd,2);
  560. /*
  561. *
  562. * Break the URL path into C style argc/argv style arguments for our
  563. * modules. Given "http://example.com/module/arg1/arg2", $this->argc
  564. * will be 3 (integer) and $this->argv will contain:
  565. * [0] => 'module'
  566. * [1] => 'arg1'
  567. * [2] => 'arg2'
  568. *
  569. *
  570. * There will always be one argument. If provided a naked domain
  571. * URL, $this->argv[0] is set to "home".
  572. *
  573. */
  574. $this->argv = explode('/',$this->cmd);
  575. $this->argc = count($this->argv);
  576. if((array_key_exists('0',$this->argv)) && strlen($this->argv[0])) {
  577. $this->module = str_replace(".", "_", $this->argv[0]);
  578. $this->module = str_replace("-", "_", $this->module);
  579. }
  580. else {
  581. $this->argc = 1;
  582. $this->argv = array('home');
  583. $this->module = 'home';
  584. }
  585. /*
  586. * See if there is any page number information, and initialise
  587. * pagination
  588. */
  589. $this->pager['page'] = ((x($_GET,'page') && intval($_GET['page']) > 0) ? intval($_GET['page']) : 1);
  590. $this->pager['itemspage'] = 50;
  591. $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
  592. if($this->pager['start'] < 0)
  593. $this->pager['start'] = 0;
  594. $this->pager['total'] = 0;
  595. /*
  596. * Detect mobile devices
  597. */
  598. $mobile_detect = new Mobile_Detect();
  599. $this->is_mobile = $mobile_detect->isMobile();
  600. $this->is_tablet = $mobile_detect->isTablet();
  601. // Friendica-Client
  602. $this->is_friendica_app = ($_SERVER['HTTP_USER_AGENT'] == "Apache-HttpClient/UNAVAILABLE (java 1.4)");
  603. /*
  604. * register template engines
  605. */
  606. $dc = get_declared_classes();
  607. foreach ($dc as $k) {
  608. if (in_array("ITemplateEngine", class_implements($k))){
  609. $this->register_template_engine($k);
  610. }
  611. }
  612. self::$a = $this;
  613. }
  614. function get_basepath() {
  615. $basepath = get_config("system", "basepath");
  616. if ($basepath == "")
  617. $basepath = dirname(__FILE__);
  618. if ($basepath == "")
  619. $basepath = $_SERVER["DOCUMENT_ROOT"];
  620. if ($basepath == "")
  621. $basepath = $_SERVER["PWD"];
  622. return($basepath);
  623. }
  624. function get_scheme() {
  625. return($this->scheme);
  626. }
  627. function get_baseurl($ssl = false) {
  628. // Is the function called statically?
  629. if (!is_object($this))
  630. return(self::$a->get_baseurl($ssl));
  631. $scheme = $this->scheme;
  632. if((x($this->config,'system')) && (x($this->config['system'],'ssl_policy'))) {
  633. if(intval($this->config['system']['ssl_policy']) === intval(SSL_POLICY_FULL))
  634. $scheme = 'https';
  635. // Basically, we have $ssl = true on any links which can only be seen by a logged in user
  636. // (and also the login link). Anything seen by an outsider will have it turned off.
  637. if($this->config['system']['ssl_policy'] == SSL_POLICY_SELFSIGN) {
  638. if($ssl)
  639. $scheme = 'https';
  640. else
  641. $scheme = 'http';
  642. }
  643. }
  644. if (get_config('config','hostname') != "")
  645. $this->hostname = get_config('config','hostname');
  646. $this->baseurl = $scheme . "://" . $this->hostname . ((isset($this->path) && strlen($this->path)) ? '/' . $this->path : '' );
  647. return $this->baseurl;
  648. }
  649. function set_baseurl($url) {
  650. $parsed = @parse_url($url);
  651. $this->baseurl = $url;
  652. if($parsed) {
  653. $this->scheme = $parsed['scheme'];
  654. $hostname = $parsed['host'];
  655. if(x($parsed,'port'))
  656. $hostname .= ':' . $parsed['port'];
  657. if(x($parsed,'path'))
  658. $this->path = trim($parsed['path'],'\\/');
  659. if (file_exists(".htpreconfig.php"))
  660. @include(".htpreconfig.php");
  661. if (get_config('config','hostname') != "")
  662. $this->hostname = get_config('config','hostname');
  663. if (!isset($this->hostname) OR ($this->hostname == ""))
  664. $this->hostname = $hostname;
  665. }
  666. }
  667. function get_hostname() {
  668. if (get_config('config','hostname') != "")
  669. $this->hostname = get_config('config','hostname');
  670. return $this->hostname;
  671. }
  672. function set_hostname($h) {
  673. $this->hostname = $h;
  674. }
  675. function set_path($p) {
  676. $this->path = trim(trim($p),'/');
  677. }
  678. function get_path() {
  679. return $this->path;
  680. }
  681. function set_pager_total($n) {
  682. $this->pager['total'] = intval($n);
  683. }
  684. function set_pager_itemspage($n) {
  685. $this->pager['itemspage'] = ((intval($n) > 0) ? intval($n) : 0);
  686. $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
  687. }
  688. function set_pager_page($n) {
  689. $this->pager['page'] = $n;
  690. $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
  691. }
  692. function init_pagehead() {
  693. $interval = ((local_user()) ? get_pconfig(local_user(),'system','update_interval') : 40000);
  694. // If the update is "deactivated" set it to the highest integer number (~24 days)
  695. if ($interval < 0)
  696. $interval = 2147483647;
  697. if($interval < 10000)
  698. $interval = 40000;
  699. // compose the page title from the sitename and the
  700. // current module called
  701. if (!$this->module=='')
  702. {
  703. $this->page['title'] = $this->config['sitename'].' ('.$this->module.')';
  704. } else {
  705. $this->page['title'] = $this->config['sitename'];
  706. }
  707. /* put the head template at the beginning of page['htmlhead']
  708. * since the code added by the modules frequently depends on it
  709. * being first
  710. */
  711. if(!isset($this->page['htmlhead']))
  712. $this->page['htmlhead'] = '';
  713. // If we're using Smarty, then doing replace_macros() will replace
  714. // any unrecognized variables with a blank string. Since we delay
  715. // replacing $stylesheet until later, we need to replace it now
  716. // with another variable name
  717. if($this->theme['template_engine'] === 'smarty3')
  718. $stylesheet = $this->get_template_ldelim('smarty3') . '$stylesheet' . $this->get_template_rdelim('smarty3');
  719. else
  720. $stylesheet = '$stylesheet';
  721. $shortcut_icon = get_config("system", "shortcut_icon");
  722. if ($shortcut_icon == "")
  723. $shortcut_icon = "images/friendica-32.png";
  724. $touch_icon = get_config("system", "touch_icon");
  725. if ($touch_icon == "")
  726. $touch_icon = "images/friendica-128.png";
  727. // get data wich is needed for infinite scroll on the network page
  728. $invinite_scroll = infinite_scroll_data($this->module);
  729. $tpl = get_markup_template('head.tpl');
  730. $this->page['htmlhead'] = replace_macros($tpl,array(
  731. '$baseurl' => $this->get_baseurl(), // FIXME for z_path!!!!
  732. '$local_user' => local_user(),
  733. '$generator' => 'Friendica' . ' ' . FRIENDICA_VERSION,
  734. '$delitem' => t('Delete this item?'),
  735. '$comment' => t('Comment'),
  736. '$showmore' => t('show more'),
  737. '$showfewer' => t('show fewer'),
  738. '$update_interval' => $interval,
  739. '$shortcut_icon' => $shortcut_icon,
  740. '$touch_icon' => $touch_icon,
  741. '$stylesheet' => $stylesheet,
  742. '$infinite_scroll' => $invinite_scroll,
  743. )) . $this->page['htmlhead'];
  744. }
  745. function init_page_end() {
  746. if(!isset($this->page['end']))
  747. $this->page['end'] = '';
  748. $tpl = get_markup_template('end.tpl');
  749. $this->page['end'] = replace_macros($tpl,array(
  750. '$baseurl' => $this->get_baseurl() // FIXME for z_path!!!!
  751. )) . $this->page['end'];
  752. }
  753. function set_curl_code($code) {
  754. $this->curl_code = $code;
  755. }
  756. function get_curl_code() {
  757. return $this->curl_code;
  758. }
  759. function set_curl_content_type($content_type) {
  760. $this->curl_content_type = $content_type;
  761. }
  762. function get_curl_content_type() {
  763. return $this->curl_content_type;
  764. }
  765. function set_curl_headers($headers) {
  766. $this->curl_headers = $headers;
  767. }
  768. function get_curl_headers() {
  769. return $this->curl_headers;
  770. }
  771. function get_cached_avatar_image($avatar_image){
  772. return $avatar_image;
  773. // The following code is deactivated. It doesn't seem to make any sense and it slows down the system.
  774. /*
  775. if($this->cached_profile_image[$avatar_image])
  776. return $this->cached_profile_image[$avatar_image];
  777. $path_parts = explode("/",$avatar_image);
  778. $common_filename = $path_parts[count($path_parts)-1];
  779. if($this->cached_profile_picdate[$common_filename]){
  780. $this->cached_profile_image[$avatar_image] = $avatar_image . $this->cached_profile_picdate[$common_filename];
  781. } else {
  782. $r = q("SELECT `contact`.`avatar-date` AS picdate FROM `contact` WHERE `contact`.`thumb` like '%%/%s'",
  783. $common_filename);
  784. if(! dbm::is_result($r)){
  785. $this->cached_profile_image[$avatar_image] = $avatar_image;
  786. } else {
  787. $this->cached_profile_picdate[$common_filename] = "?rev=".urlencode($r[0]['picdate']);
  788. $this->cached_profile_image[$avatar_image] = $avatar_image.$this->cached_profile_picdate[$common_filename];
  789. }
  790. }
  791. return $this->cached_profile_image[$avatar_image];
  792. */
  793. }
  794. /**
  795. * @brief Removes the baseurl from an url. This avoids some mixed content problems.
  796. *
  797. * @param string $url
  798. *
  799. * @return string The cleaned url
  800. */
  801. function remove_baseurl($url){
  802. // Is the function called statically?
  803. if (!is_object($this))
  804. return(self::$a->remove_baseurl($url));
  805. $url = normalise_link($url);
  806. $base = normalise_link($this->get_baseurl());
  807. $url = str_replace($base."/", "", $url);
  808. return $url;
  809. }
  810. /**
  811. * @brief Register template engine class
  812. *
  813. * If $name is "", is used class static property $class::$name
  814. *
  815. * @param string $class
  816. * @param string $name
  817. */
  818. function register_template_engine($class, $name = '') {
  819. if ($name===""){
  820. $v = get_class_vars( $class );
  821. if(x($v,"name")) $name = $v['name'];
  822. }
  823. if ($name===""){
  824. echo "template engine <tt>$class</tt> cannot be registered without a name.\n";
  825. killme();
  826. }
  827. $this->template_engines[$name] = $class;
  828. }
  829. /**
  830. * @brief Return template engine instance.
  831. *
  832. * If $name is not defined, return engine defined by theme,
  833. * or default
  834. *
  835. * @param strin $name Template engine name
  836. * @return object Template Engine instance
  837. */
  838. function template_engine($name = ''){
  839. if ($name!=="") {
  840. $template_engine = $name;
  841. } else {
  842. $template_engine = 'smarty3';
  843. if (x($this->theme, 'template_engine')) {
  844. $template_engine = $this->theme['template_engine'];
  845. }
  846. }
  847. if (isset($this->template_engines[$template_engine])){
  848. if(isset($this->template_engine_instance[$template_engine])){
  849. return $this->template_engine_instance[$template_engine];
  850. } else {
  851. $class = $this->template_engines[$template_engine];
  852. $obj = new $class;
  853. $this->template_engine_instance[$template_engine] = $obj;
  854. return $obj;
  855. }
  856. }
  857. echo "template engine <tt>$template_engine</tt> is not registered!\n"; killme();
  858. }
  859. /**
  860. * @brief Returns the active template engine.
  861. *
  862. * @return string
  863. */
  864. function get_template_engine() {
  865. return $this->theme['template_engine'];
  866. }
  867. function set_template_engine($engine = 'smarty3') {
  868. $this->theme['template_engine'] = $engine;
  869. /*
  870. $this->theme['template_engine'] = 'smarty3';
  871. switch($engine) {
  872. case 'smarty3':
  873. if(is_writable('view/smarty3/'))
  874. $this->theme['template_engine'] = 'smarty3';
  875. break;
  876. default:
  877. break;
  878. }
  879. */
  880. }
  881. function get_template_ldelim($engine = 'smarty3') {
  882. return $this->ldelim[$engine];
  883. }
  884. function get_template_rdelim($engine = 'smarty3') {
  885. return $this->rdelim[$engine];
  886. }
  887. function save_timestamp($stamp, $value) {
  888. $duration = (float)(microtime(true)-$stamp);
  889. if (!isset($this->performance[$value])) {
  890. // Prevent ugly E_NOTICE
  891. $this->performance[$value] = 0;
  892. }
  893. $this->performance[$value] += (float)$duration;
  894. $this->performance["marktime"] += (float)$duration;
  895. $callstack = $this->callstack();
  896. if (!isset($this->callstack[$value][$callstack])) {
  897. // Prevent ugly E_NOTICE
  898. $this->callstack[$value][$callstack] = 0;
  899. }
  900. $this->callstack[$value][$callstack] += (float)$duration;
  901. }
  902. /**
  903. * @brief Returns a string with a callstack. Can be used for logging.
  904. *
  905. * @return string
  906. */
  907. function callstack() {
  908. $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 6);
  909. // We remove the first two items from the list since they contain data that we don't need.
  910. array_shift($trace);
  911. array_shift($trace);
  912. $callstack = array();
  913. foreach ($trace AS $func)
  914. $callstack[] = $func["function"];
  915. return implode(", ", $callstack);
  916. }
  917. function mark_timestamp($mark) {
  918. //$this->performance["markstart"] -= microtime(true) - $this->performance["marktime"];
  919. $this->performance["markstart"] = microtime(true) - $this->performance["markstart"] - $this->performance["marktime"];
  920. }
  921. function get_useragent() {
  922. return(FRIENDICA_PLATFORM." '".FRIENDICA_CODENAME."' ".FRIENDICA_VERSION."-".DB_UPDATE_VERSION."; ".$this->get_baseurl());
  923. }
  924. function is_friendica_app() {
  925. return($this->is_friendica_app);
  926. }
  927. /**
  928. * @brief Checks if the site is called via a backend process
  929. *
  930. * This isn't a perfect solution. But we need this check very early.
  931. * So we cannot wait until the modules are loaded.
  932. *
  933. * @return bool Is it a known backend?
  934. */
  935. function is_backend() {
  936. $backend = array();
  937. $backend[] = "_well_known";
  938. $backend[] = "api";
  939. $backend[] = "dfrn_notify";
  940. $backend[] = "fetch";
  941. $backend[] = "hcard";
  942. $backend[] = "hostxrd";
  943. $backend[] = "nodeinfo";
  944. $backend[] = "noscrape";
  945. $backend[] = "p";
  946. $backend[] = "poco";
  947. $backend[] = "post";
  948. $backend[] = "proxy";
  949. $backend[] = "pubsub";
  950. $backend[] = "pubsubhubbub";
  951. $backend[] = "receive";
  952. $backend[] = "rsd_xml";
  953. $backend[] = "salmon";
  954. $backend[] = "statistics_json";
  955. $backend[] = "xrd";
  956. if (in_array($this->module, $backend))
  957. return(true);
  958. else
  959. return($this->backend);
  960. }
  961. /**
  962. * @brief Checks if the maximum number of database processes is reached
  963. *
  964. * @return bool Is the limit reached?
  965. */
  966. function max_processes_reached() {
  967. // Is the function called statically?
  968. if (!is_object($this))
  969. return(self::$a->max_processes_reached());
  970. if ($this->is_backend()) {
  971. $process = "backend";
  972. $max_processes = get_config('system', 'max_processes_backend');
  973. if (intval($max_processes) == 0)
  974. $max_processes = 5;
  975. } else {
  976. $process = "frontend";
  977. $max_processes = get_config('system', 'max_processes_frontend');
  978. if (intval($max_processes) == 0)
  979. $max_processes = 20;
  980. }
  981. $processlist = dbm::processlist();
  982. if ($processlist["list"] != "") {
  983. logger("Processcheck: Processes: ".$processlist["amount"]." - Processlist: ".$processlist["list"], LOGGER_DEBUG);
  984. if ($processlist["amount"] > $max_processes) {
  985. logger("Processcheck: Maximum number of processes for ".$process." tasks (".$max_processes.") reached.", LOGGER_DEBUG);
  986. return true;
  987. }
  988. }
  989. return false;
  990. }
  991. /**
  992. * @brief Checks if the maximum load is reached
  993. *
  994. * @return bool Is the load reached?
  995. */
  996. function maxload_reached() {
  997. // Is the function called statically?
  998. if (!is_object($this))
  999. return(self::$a->maxload_reached());
  1000. if ($this->is_backend()) {
  1001. $process = "backend";
  1002. $maxsysload = intval(get_config('system', 'maxloadavg'));
  1003. if ($maxsysload < 1)
  1004. $maxsysload = 50;
  1005. } else {
  1006. $process = "frontend";
  1007. $maxsysload = intval(get_config('system','maxloadavg_frontend'));
  1008. if ($maxsysload < 1)
  1009. $maxsysload = 50;
  1010. }
  1011. $load = current_load();
  1012. if ($load) {
  1013. if (intval($load) > $maxsysload) {
  1014. logger('system: load '.$load.' for '.$process.' tasks ('.$maxsysload.') too high.');
  1015. return true;
  1016. }
  1017. }
  1018. return false;
  1019. }
  1020. /**
  1021. * @brief Checks if the process is already running
  1022. *
  1023. * @param string $taskname The name of the task that will be used for the name of the lockfile
  1024. * @param string $task The path and name of the php script
  1025. * @param int $timeout The timeout after which a task should be killed
  1026. *
  1027. * @return bool Is the process running?
  1028. */
  1029. function is_already_running($taskname, $task = "", $timeout = 540) {
  1030. $lockpath = get_lockpath();
  1031. if ($lockpath != '') {
  1032. $pidfile = new pidfile($lockpath, $taskname);
  1033. if ($pidfile->is_already_running()) {
  1034. logger("Already running");
  1035. if ($pidfile->running_time() > $timeout) {
  1036. $pidfile->kill();
  1037. logger("killed stale process");
  1038. // Calling a new instance
  1039. if ($task != "")
  1040. proc_run('php', $task);
  1041. }
  1042. return true;
  1043. }
  1044. }
  1045. return false;
  1046. }
  1047. }
  1048. /**
  1049. * @brief Retrieve the App structure
  1050. *
  1051. * Useful in functions which require it but don't get it passed to them
  1052. */
  1053. function get_app() {
  1054. global $a;
  1055. return $a;
  1056. }
  1057. /**
  1058. * @brief Multi-purpose function to check variable state.
  1059. *
  1060. * Usage: x($var) or $x($array, 'key')
  1061. *
  1062. * returns false if variable/key is not set
  1063. * if variable is set, returns 1 if has 'non-zero' value, otherwise returns 0.
  1064. * e.g. x('') or x(0) returns 0;
  1065. *
  1066. * @param string|array $s variable to check
  1067. * @param string $k key inside the array to check
  1068. *
  1069. * @return bool|int
  1070. */
  1071. function x($s,$k = NULL) {
  1072. if($k != NULL) {
  1073. if((is_array($s)) && (array_key_exists($k,$s))) {
  1074. if($s[$k])
  1075. return (int) 1;
  1076. return (int) 0;
  1077. }
  1078. return false;
  1079. }
  1080. else {
  1081. if(isset($s)) {
  1082. if($s) {
  1083. return (int) 1;
  1084. }
  1085. return (int) 0;
  1086. }
  1087. return false;
  1088. }
  1089. }
  1090. /**
  1091. * @brief Called from db initialisation if db is dead.
  1092. */
  1093. function system_unavailable() {
  1094. include('system_unavailable.php');
  1095. system_down();
  1096. killme();
  1097. }
  1098. function clean_urls() {
  1099. global $a;
  1100. // if($a->config['system']['clean_urls'])
  1101. return true;
  1102. // return false;
  1103. }
  1104. function z_path() {
  1105. global $a;
  1106. $base = $a->get_baseurl();
  1107. if(! clean_urls())
  1108. $base .= '/?q=';
  1109. return $base;
  1110. }
  1111. /**
  1112. * @brief Returns the baseurl.
  1113. *
  1114. * @see App::get_baseurl()
  1115. *
  1116. * @return string
  1117. */
  1118. function z_root() {
  1119. global $a;
  1120. return $a->get_baseurl();
  1121. }
  1122. /**
  1123. * @brief Return absolut URL for given $path.
  1124. *
  1125. * @param string $path
  1126. *
  1127. * @return string
  1128. */
  1129. function absurl($path) {
  1130. if(strpos($path,'/') === 0)
  1131. return z_path() . $path;
  1132. return $path;
  1133. }
  1134. /**
  1135. * @brief Function to check if request was an AJAX (xmlhttprequest) request.
  1136. *
  1137. * @return boolean
  1138. */
  1139. function is_ajax() {
  1140. return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
  1141. }
  1142. function check_db() {
  1143. $build = get_config('system','build');
  1144. if(! x($build)) {
  1145. set_config('system','build',DB_UPDATE_VERSION);
  1146. $build = DB_UPDATE_VERSION;
  1147. }
  1148. if($build != DB_UPDATE_VERSION)
  1149. proc_run('php', 'include/dbupdate.php');
  1150. }
  1151. /**
  1152. * Sets the base url for use in cmdline programs which don't have
  1153. * $_SERVER variables
  1154. */
  1155. function check_url(&$a) {
  1156. $url = get_config('system','url');
  1157. // if the url isn't set or the stored url is radically different
  1158. // than the currently visited url, store the current value accordingly.
  1159. // "Radically different" ignores common variations such as http vs https
  1160. // and www.example.com vs example.com.
  1161. // We will only change the url to an ip address if there is no existing setting
  1162. if(! x($url))
  1163. $url = set_config('system','url',$a->get_baseurl());
  1164. if((! link_compare($url,$a->get_baseurl())) && (! preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$a->get_hostname)))
  1165. $url = set_config('system','url',$a->get_baseurl());
  1166. return;
  1167. }
  1168. /**
  1169. * @brief Automatic database updates
  1170. */
  1171. function update_db(&$a) {
  1172. $build = get_config('system','build');
  1173. if(! x($build))
  1174. $build = set_config('system','build',DB_UPDATE_VERSION);
  1175. if($build != DB_UPDATE_VERSION) {
  1176. $stored = intval($build);
  1177. $current = intval(DB_UPDATE_VERSION);
  1178. if($stored < $current) {
  1179. load_config('database');
  1180. // We're reporting a different version than what is currently installed.
  1181. // Run any existing update scripts to bring the database up to current.
  1182. // make sure that boot.php and update.php are the same release, we might be
  1183. // updating right this very second and the correct version of the update.php
  1184. // file may not be here yet. This can happen on a very busy site.
  1185. if(DB_UPDATE_VERSION == UPDATE_VERSION) {
  1186. // Compare the current structure with the defined structure
  1187. $t = get_config('database','dbupdate_'.DB_UPDATE_VERSION);
  1188. if($t !== false)
  1189. return;
  1190. set_config('database','dbupdate_'.DB_UPDATE_VERSION, time());
  1191. // run old update routine (wich could modify the schema and
  1192. // conflits with new routine)
  1193. for ($x = $stored; $x < NEW_UPDATE_ROUTINE_VERSION; $x++) {
  1194. $r = run_update_function($x);
  1195. if (!$r) break;
  1196. }
  1197. if ($stored < NEW_UPDATE_ROUTINE_VERSION) $stored = NEW_UPDATE_ROUTINE_VERSION;
  1198. // run new update routine
  1199. // it update the structure in one call
  1200. $retval = update_structure(false, true);
  1201. if($retval) {
  1202. update_fail(
  1203. DB_UPDATE_VERSION,
  1204. $retval
  1205. );
  1206. return;
  1207. } else {
  1208. set_config('database','dbupdate_'.DB_UPDATE_VERSION, 'success');
  1209. }
  1210. // run any left update_nnnn functions in update.php
  1211. for($x = $stored; $x < $current; $x ++) {
  1212. $r = run_update_function($x);
  1213. if (!$r) break;
  1214. }
  1215. }
  1216. }
  1217. }
  1218. return;
  1219. }
  1220. function run_update_function($x) {
  1221. if(function_exists('update_' . $x)) {
  1222. // There could be a lot of processes running or about to run.
  1223. // We want exactly one process to run the update command.
  1224. // So store the fact that we're taking responsibility
  1225. // after first checking to see if somebody else already has.
  1226. // If the update fails or times-out completely you may need to
  1227. // delete the config entry to try again.
  1228. $t = get_config('database','update_' . $x);
  1229. if($t !== false)
  1230. return false;
  1231. set_config('database','update_' . $x, time());
  1232. // call the specific update
  1233. $func = 'update_' . $x;
  1234. $retval = $func();
  1235. if($retval) {
  1236. //send the administrator an e-mail
  1237. update_fail(
  1238. $x,
  1239. sprintf(t('Update %s failed. See error logs.'), $x)
  1240. );
  1241. return false;
  1242. } else {
  1243. set_config('database','update_' . $x, 'success');
  1244. set_config('system','build', $x + 1);
  1245. return true;
  1246. }