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.

2534 lines
65 KiB

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