streams/boot.php

2660 lines
75 KiB
PHP
Raw Normal View History

2010-07-01 23:48:07 +00:00
<?php
2018-06-01 02:42:13 +00:00
use Zotlabs\Lib\Libzot;
2019-04-12 03:26:38 +00:00
use Zotlabs\Web\Session;
use Zotlabs\Web\HttpMeta;
use Zotlabs\Render\SmartyTemplate;
use Zotlabs\Render\Comanche;
use Zotlabs\Render\Theme;
use Zotlabs\Lib\DB_Upgrade;
use Zotlabs\Lib\System;
2021-05-27 11:04:16 +00:00
use Zotlabs\Lib\PConfig;
use Zotlabs\Lib\Config;
use Zotlabs\Daemon\Run;
2022-01-25 01:26:12 +00:00
use Zotlabs\Lib\Channel;
/**
* @file boot.php
*
* @brief This file defines some global constants and includes the central App class.
*/
2013-09-12 23:52:58 +00:00
require_once('version.php');
define ( 'PLATFORM_NAME', 'streams' );
2020-03-04 02:27:01 +00:00
define ( 'DB_UPDATE_VERSION', 1254 );
define ( 'ZOT_REVISION', '11.0' );
2020-03-04 02:27:01 +00:00
define ( 'PLATFORM_ARCHITECTURE', 'zap' );
define ( 'PROJECT_BASE', __DIR__ );
// This configures the default state of activitypub at the project level.
if (! defined('ACTIVITYPUB_ENABLED')) {
define ( 'ACTIVITYPUB_ENABLED', true );
}
2020-03-04 02:27:01 +00:00
// composer autoloader for all namespaced Classes
require_once('vendor/autoload.php');
2019-05-24 05:51:39 +00:00
if (file_exists('addon/vendor/autoload.php')) {
2019-04-26 22:15:15 +00:00
require_once('addon/vendor/autoload.php');
}
2019-08-16 06:53:02 +00:00
if (file_exists('addon/version.php')) {
require_once('addon/version.php');
}
2019-04-26 22:15:15 +00:00
require_once('include/config.php');
require_once('include/network.php');
2020-08-24 06:05:57 +00:00
require_once('include/addon.php');
require_once('include/text.php');
require_once('include/datetime.php');
require_once('include/language.php');
require_once('include/nav.php');
require_once('include/permissions.php');
require_once('include/features.php');
require_once('include/taxonomy.php');
require_once('include/connections.php');
require_once('include/zid.php');
require_once('include/xchan.php');
2017-01-30 23:01:22 +00:00
require_once('include/hubloc.php');
require_once('include/attach.php');
require_once('include/bbcode.php');
2018-06-01 04:05:09 +00:00
require_once('include/items.php');
/**
* @brief Constant with a HTML line break.
*
* Contains a HTML line break (br) element and a real carriage return with line
* feed for the source.
2019-06-06 06:08:17 +00:00
* This can be used in HTML and JavaScript wherever a line break is required.
*/
define ( 'EOL', '<br>' . "\r\n" );
define ( 'EMPTY_STR', '' );
define ( 'ATOM_TIME', 'Y-m-d\\TH:i:s\\Z' ); // aka ISO 8601 "Zulu"
2020-03-04 02:24:26 +00:00
define ( 'TEMPLATE_BUILD_PATH', 'cache/smarty3' );
2019-10-01 02:25:48 +00:00
//define ( 'USE_BEARCAPS', true);
2021-02-05 20:21:04 +00:00
// Many of these directory settings are no longer used, but may still be referenced in code.
// The only ones of consequence in 2021 are DIRECTORY_MODE_NORMAL and DIRECTORY_MODE_STANDALONE.
define ( 'DIRECTORY_MODE_NORMAL', 0x0000); // A directory client
define ( 'DIRECTORY_MODE_PRIMARY', 0x0001); // There can only be *one* primary directory server in a directory_realm.
define ( 'DIRECTORY_MODE_SECONDARY', 0x0002); // All other mirror directory servers
define ( 'DIRECTORY_MODE_STANDALONE', 0x0100); // A detached (off the grid) hub with itself as directory server.
2019-09-18 04:25:26 +00:00
// We will look for upstream directories whenever we make contact
// with other sites, but if this is a new installation and isn't
// a standalone hub, we need to seed the service with a starting
// point to go out and find the rest of the world.
2018-07-17 03:04:47 +00:00
define ( 'DIRECTORY_REALM', 'ZAP');
2021-08-27 05:15:24 +00:00
// Types of xchan records. These are a superset of ActivityStreams Actor types
define ('XCHAN_TYPE_PERSON', 0);
define ('XCHAN_TYPE_GROUP', 1);
define ('XCHAN_TYPE_COLLECTION', 2);
define ('XCHAN_TYPE_SERVICE', 3);
define ('XCHAN_TYPE_ORGANIZATION', 4);
define ('XCHAN_TYPE_APPLICATION', 5);
define ('XCHAN_TYPE_UNKNOWN', 127);
/**
*
* Image storage quality. Lower numbers save space at cost of image detail.
* For ease of upgrade, please do not change here. Change jpeg quality with
2016-03-31 23:06:03 +00:00
* App::$config['system']['jpeg_quality'] = n;
* in .htconfig.php, where n is netween 1 and 100, and with very poor results
* below about 50
*/
define ( 'JPEG_QUALITY', 100 );
2012-06-07 15:42:13 +00:00
/**
2016-03-31 23:06:03 +00:00
* App::$config['system']['png_quality'] from 0 (uncompressed) to 9
2012-06-07 15:42:13 +00:00
*/
define ( 'PNG_QUALITY', 8 );
/**
* Language detection parameters
*/
define ( 'LANGUAGE_DETECT_MIN_LENGTH', 64 );
define ( 'LANGUAGE_DETECT_MIN_CONFIDENCE', 0.01 );
define ('MAX_EVENT_REPEAT_COUNT', 512);
/**
* Default permissions for file-based storage (webDAV, etc.)
* These files will be owned by the webserver who will need write
* access to the "storage" folder.
* Ideally you should make this 700, however some hosted platforms
* may not let you change ownership of this directory so we're
* defaulting to both owner-write and group-write privilege.
* This should work for most cases without modification.
* Over-ride this in your .htconfig.php if you need something
* either more or less restrictive.
*/
2014-04-10 03:11:52 +00:00
2019-06-02 03:08:09 +00:00
if (! defined('STORAGE_DEFAULT_PERMISSIONS')) {
2017-03-14 07:22:57 +00:00
define ( 'STORAGE_DEFAULT_PERMISSIONS', 0770 );
}
2021-09-13 03:49:53 +00:00
// imported followers for friend suggestions.
if (! defined('MAX_IMPORTED_FOLLOW')) {
define ( 'MAX_IMPORTED_FOLLOW', 10);
}
/**
*
* An alternate way of limiting picture upload sizes. Specify the maximum pixel
* length that pictures are allowed to be (for non-square pictures, it will apply
* to the longest side). Pictures longer than this length will be resized to be
* this length (on the longest side, the other side will be scaled appropriately).
* Modify this value using
*
2016-03-31 23:06:03 +00:00
* App::$config['system']['max_image_length'] = n;
*
* in .htconfig.php
*
* If you don't want to set a maximum length, set to -1. The default value is
* defined by 'MAX_IMAGE_LENGTH' below.
*
*/
define ( 'MAX_IMAGE_LENGTH', -1 );
define ( 'PUBLIC_STREAM_NONE', 0 );
define ( 'PUBLIC_STREAM_SITE', 1 );
define ( 'PUBLIC_STREAM_FULL', 2 );
2010-12-10 12:04:35 +00:00
/**
* log levels
*/
2010-11-02 00:56:36 +00:00
define ( 'LOGGER_NORMAL', 0 );
define ( 'LOGGER_TRACE', 1 );
define ( 'LOGGER_DEBUG', 2 );
define ( 'LOGGER_DATA', 3 );
define ( 'LOGGER_ALL', 4 );
2016-08-22 23:21:07 +00:00
2010-12-10 12:04:35 +00:00
/**
* registration policies
*/
2010-10-13 09:47:32 +00:00
define ( 'REGISTER_CLOSED', 0 );
define ( 'REGISTER_APPROVE', 1 );
define ( 'REGISTER_OPEN', 2 );
2010-07-01 23:48:07 +00:00
/**
* site access policy
*/
define ( 'ACCESS_PRIVATE', 0 );
define ( 'ACCESS_PAID', 1 );
define ( 'ACCESS_FREE', 2 );
define ( 'ACCESS_TIERED', 3 );
/**
* DB update return values
*/
define ( 'UPDATE_SUCCESS', 0);
define ( 'UPDATE_FAILED', 1);
define ( 'CLIENT_MODE_NORMAL', 0x0000);
define ( 'CLIENT_MODE_LOAD', 0x0001);
define ( 'CLIENT_MODE_UPDATE', 0x0002);
2010-12-10 12:04:35 +00:00
/**
*
2013-09-23 03:38:24 +00:00
* Channel pageflags
2010-12-10 12:04:35 +00:00
*
*/
define ( 'PAGE_NORMAL', 0x0000 );
define ( 'PAGE_HIDDEN', 0x0001 );
define ( 'PAGE_AUTOCONNECT', 0x0002 );
define ( 'PAGE_APPLICATION', 0x0004 );
define ( 'PAGE_ALLOWCODE', 0x0008 );
define ( 'PAGE_PREMIUM', 0x0010 );
2013-09-23 03:38:24 +00:00
define ( 'PAGE_ADULT', 0x0020 );
2014-03-27 00:05:45 +00:00
define ( 'PAGE_CENSORED', 0x0040 ); // Site admin has blocked this channel from appearing in casual search results and site feeds
define ( 'PAGE_SYSTEM', 0x1000 );
define ( 'PAGE_HUBADMIN', 0x2000 ); // set this to indicate a preferred admin channel rather than the
// default channel of any accounts with the admin role.
define ( 'PAGE_REMOVED', 0x8000 );
/**
* Photo usage types
*/
define ( 'PHOTO_NORMAL', 0x0000 );
define ( 'PHOTO_PROFILE', 0x0001 );
define ( 'PHOTO_XCHAN', 0x0002 );
define ( 'PHOTO_THING', 0x0004 );
define ( 'PHOTO_COVER', 0x0010 );
define ( 'PHOTO_ADULT', 0x0008 );
define ( 'PHOTO_FLAG_OS', 0x4000 );
2016-01-15 01:25:27 +00:00
define ( 'PHOTO_RES_ORIG', 0 );
define ( 'PHOTO_RES_1024', 1 ); // rectangular 1024 max width or height, floating height if not (4:3)
define ( 'PHOTO_RES_640', 2 ); // to accomodate SMBC vertical comic strips without scrunching the width
define ( 'PHOTO_RES_320', 3 ); // accordingly
define ( 'PHOTO_RES_PROFILE_300', 4 ); // square 300 px
define ( 'PHOTO_RES_PROFILE_80', 5 ); // square 80 px
define ( 'PHOTO_RES_PROFILE_48', 6 ); // square 48 px
define ( 'PHOTO_RES_COVER_1200', 7 ); // 1200w x 435h (2.75:1)
define ( 'PHOTO_RES_COVER_850', 8 ); // 850w x 310h
define ( 'PHOTO_RES_COVER_425', 9 ); // 425w x 160h
2014-01-15 20:57:12 +00:00
/**
* Menu types
2014-04-10 03:11:52 +00:00
*/
2014-01-15 20:57:12 +00:00
define ( 'MENU_SYSTEM', 0x0001 );
define ( 'MENU_BOOKMARK', 0x0002 );
2011-04-11 10:22:09 +00:00
/**
* Network and protocol family types
2011-04-11 10:22:09 +00:00
*/
define ( 'NETWORK_FRND', 'friendica-over-diaspora'); // Friendica, Mistpark, other DFRN implementations
define ( 'NETWORK_DFRN', 'dfrn'); // Friendica, Mistpark, other DFRN implementations
define ( 'NETWORK_ZOT', 'zot'); // Zot!
2018-05-18 10:09:38 +00:00
define ( 'NETWORK_ZOT6', 'zot6');
2021-10-30 04:40:26 +00:00
define ( 'NETWORK_NOMAD', 'nomad');
2011-04-11 10:22:09 +00:00
define ( 'NETWORK_OSTATUS', 'stat'); // status.net, identi.ca, GNU-social, other OStatus implementations
define ( 'NETWORK_GNUSOCIAL', 'gnusoc'); // status.net, identi.ca, GNU-social, other OStatus implementations
define ( 'NETWORK_FEED', 'rss'); // RSS/Atom feeds with no known "post/notify" protocol
define ( 'NETWORK_DIASPORA', 'diaspora'); // Diaspora
define ( 'NETWORK_ACTIVITYPUB', 'activitypub');
2011-04-11 10:22:09 +00:00
define ( 'NETWORK_MAIL', 'mail'); // IMAP/POP
2012-02-01 04:03:46 +00:00
define ( 'NETWORK_MAIL2', 'mai2'); // extended IMAP/POP
define ( 'NETWORK_FACEBOOK', 'face'); // Facebook API
define ( 'NETWORK_LINKEDIN', 'lnkd'); // LinkedIn
define ( 'NETWORK_XMPP', 'xmpp'); // XMPP
define ( 'NETWORK_MYSPACE', 'mysp'); // MySpace
2012-02-01 04:03:46 +00:00
define ( 'NETWORK_GPLUS', 'goog'); // Google+
2012-05-11 10:41:29 +00:00
define ( 'NETWORK_PHANTOM', 'unkn'); // Place holder
/**
2014-04-10 03:11:52 +00:00
* Permissions
2012-03-29 02:56:14 +00:00
*/
2014-04-10 03:11:52 +00:00
define ( 'PERMS_R_STREAM', 0x00001);
define ( 'PERMS_R_PROFILE', 0x00002);
2014-04-10 03:11:52 +00:00
define ( 'PERMS_R_PHOTOS', 0x00004);
define ( 'PERMS_R_ABOOK', 0x00008);
2012-09-10 04:17:06 +00:00
2014-04-10 03:11:52 +00:00
define ( 'PERMS_W_STREAM', 0x00010);
define ( 'PERMS_W_WALL', 0x00020);
2014-04-10 03:11:52 +00:00
define ( 'PERMS_W_TAGWALL', 0x00040);
define ( 'PERMS_W_COMMENT', 0x00080);
define ( 'PERMS_W_MAIL', 0x00100);
define ( 'PERMS_W_PHOTOS', 0x00200);
2014-04-10 03:11:52 +00:00
define ( 'PERMS_W_CHAT', 0x00400);
define ( 'PERMS_A_DELEGATE', 0x00800);
define ( 'PERMS_R_STORAGE', 0x01000);
define ( 'PERMS_W_STORAGE', 0x02000);
define ( 'PERMS_R_PAGES', 0x04000);
define ( 'PERMS_W_PAGES', 0x08000);
define ( 'PERMS_A_REPUBLISH', 0x10000);
define ( 'PERMS_W_LIKE', 0x20000);
2012-03-29 02:56:14 +00:00
// General channel permissions
// 0 = Only you
define ( 'PERMS_PUBLIC' , 0x0001 ); // anybody
define ( 'PERMS_NETWORK' , 0x0002 ); // anybody in this network
define ( 'PERMS_SITE' , 0x0004 ); // anybody on this site
define ( 'PERMS_CONTACTS' , 0x0008 ); // any of my connections
define ( 'PERMS_SPECIFIC' , 0x0080 ); // only specific connections
define ( 'PERMS_AUTHED' , 0x0100 ); // anybody authenticated (could include visitors from other networks)
define ( 'PERMS_PENDING' , 0x0200 ); // any connections including those who haven't yet been approved
// Address book flags
define ( 'ABOOK_FLAG_BLOCKED' , 0x0001);
define ( 'ABOOK_FLAG_IGNORED' , 0x0002);
define ( 'ABOOK_FLAG_HIDDEN' , 0x0004);
define ( 'ABOOK_FLAG_ARCHIVED' , 0x0008);
define ( 'ABOOK_FLAG_PENDING' , 0x0010);
define ( 'ABOOK_FLAG_UNCONNECTED', 0x0020);
2012-10-30 02:31:38 +00:00
define ( 'ABOOK_FLAG_SELF' , 0x0080);
2014-09-01 05:15:00 +00:00
define ( 'ABOOK_FLAG_FEED' , 0x0100);
2019-07-31 00:56:35 +00:00
define ( 'ABOOK_FLAG_CENSORED' , 0x0200);
define ( 'MAIL_DELETED', 0x0001);
define ( 'MAIL_REPLIED', 0x0002);
define ( 'MAIL_ISREPLY', 0x0004);
define ( 'MAIL_SEEN', 0x0008);
define ( 'MAIL_RECALLED', 0x0010);
define ( 'MAIL_OBSCURED', 0x0020);
define ( 'ATTACH_FLAG_DIR', 0x0001);
define ( 'ATTACH_FLAG_OS', 0x0002);
define ( 'MENU_ITEM_ZID', 0x0001);
define ( 'MENU_ITEM_NEWWIN', 0x0002);
define ( 'MENU_ITEM_CHATROOM', 0x0004);
define ( 'SITE_TYPE_ZOT', 0);
define ( 'SITE_TYPE_NOTZOT', 1);
define ( 'SITE_TYPE_UNKNOWN', 2);
/**
* Poll/Survey types
*/
define ( 'POLL_SIMPLE_RATING', 0x0001); // 1-5
define ( 'POLL_TENSCALE', 0x0002); // 1-10
define ( 'POLL_MULTIPLE_CHOICE', 0x0004);
2013-08-26 10:54:27 +00:00
define ( 'POLL_OVERWRITE', 0x8000); // If you vote twice remove the prior entry
define ( 'UPDATE_FLAGS_UPDATED', 0x0001);
2014-03-04 05:00:42 +00:00
define ( 'UPDATE_FLAGS_FORCED', 0x0002);
define ( 'UPDATE_FLAGS_CENSORED', 0x0004);
define ( 'UPDATE_FLAGS_DELETED', 0x1000);
2014-03-28 03:28:48 +00:00
define ( 'DROPITEM_NORMAL', 0);
define ( 'DROPITEM_PHASE1', 1);
define ( 'DROPITEM_PHASE2', 2);
2010-12-10 12:04:35 +00:00
/**
* Maximum number of "people who like (or don't like) this" that we will list by name
*/
2010-10-13 00:11:06 +00:00
define ( 'MAX_LIKERS', 10);
2010-10-13 00:11:06 +00:00
2011-07-15 10:08:43 +00:00
/**
* Communication timeout
*/
define ( 'ZCURL_TIMEOUT' , (-1));
2010-12-10 12:04:35 +00:00
/**
* email notification options
*/
2010-10-13 00:11:06 +00:00
2012-02-09 22:06:17 +00:00
define ( 'NOTIFY_INTRO', 0x0001 );
define ( 'NOTIFY_CONFIRM', 0x0002 );
define ( 'NOTIFY_WALL', 0x0004 );
define ( 'NOTIFY_COMMENT', 0x0008 );
define ( 'NOTIFY_MAIL', 0x0010 );
define ( 'NOTIFY_SUGGEST', 0x0020 );
define ( 'NOTIFY_PROFILE', 0x0040 );
define ( 'NOTIFY_TAGSELF', 0x0080 );
define ( 'NOTIFY_TAGSHARE', 0x0100 );
2012-07-20 04:09:40 +00:00
define ( 'NOTIFY_POKE', 0x0200 );
define ( 'NOTIFY_LIKE', 0x0400 );
define ( 'NOTIFY_RESHARE', 0x0800 );
2012-03-25 11:37:09 +00:00
define ( 'NOTIFY_SYSTEM', 0x8000 );
/**
* visual notification options
*/
define ( 'VNOTIFY_NETWORK', 0x0001 );
define ( 'VNOTIFY_CHANNEL', 0x0002 );
define ( 'VNOTIFY_MAIL', 0x0004 );
define ( 'VNOTIFY_EVENT', 0x0008 );
define ( 'VNOTIFY_EVENTTODAY', 0x0010 );
define ( 'VNOTIFY_BIRTHDAY', 0x0020 );
define ( 'VNOTIFY_SYSTEM', 0x0040 );
define ( 'VNOTIFY_INFO', 0x0080 );
define ( 'VNOTIFY_ALERT', 0x0100 );
define ( 'VNOTIFY_INTRO', 0x0200 );
define ( 'VNOTIFY_REGISTER', 0x0400 );
define ( 'VNOTIFY_FILES', 0x0800 );
define ( 'VNOTIFY_PUBS', 0x1000 );
define ( 'VNOTIFY_LIKE', 0x2000 );
define ( 'VNOTIFY_FORUMS', 0x4000 );
2019-04-16 00:34:29 +00:00
define ( 'VNOTIFY_REPORTS', 0x8000 );
2012-03-25 11:37:09 +00:00
/**
* Tag/term types
*/
2013-06-20 01:06:14 +00:00
define ( 'TERM_UNKNOWN', 0 );
define ( 'TERM_HASHTAG', 1 );
2014-04-10 03:11:52 +00:00
define ( 'TERM_MENTION', 2 );
2013-06-20 01:06:14 +00:00
define ( 'TERM_CATEGORY', 3 );
define ( 'TERM_PCATEGORY', 4 );
define ( 'TERM_FILE', 5 );
define ( 'TERM_SAVEDSEARCH', 6 );
2013-06-28 02:35:59 +00:00
define ( 'TERM_THING', 7 );
2014-02-03 22:03:43 +00:00
define ( 'TERM_BOOKMARK', 8 );
2015-07-03 21:56:48 +00:00
define ( 'TERM_HIERARCHY', 9 );
define ( 'TERM_COMMUNITYTAG', 10 );
define ( 'TERM_FORUM', 11 );
2018-09-06 23:40:13 +00:00
define ( 'TERM_EMOJI', 12 );
2013-06-20 01:06:14 +00:00
define ( 'TERM_OBJ_POST', 1 );
define ( 'TERM_OBJ_PHOTO', 2 );
define ( 'TERM_OBJ_PROFILE', 3 );
define ( 'TERM_OBJ_CHANNEL', 4 );
define ( 'TERM_OBJ_OBJECT', 5 );
define ( 'TERM_OBJ_THING', 6 );
2014-05-18 00:18:56 +00:00
define ( 'TERM_OBJ_APP', 7 );
2015-07-03 21:56:48 +00:00
2010-12-10 12:04:35 +00:00
/**
* various namespaces we may need to parse
*/
define ( 'PROTOCOL_NOMAD', 'http://purl.org/nomad' );
2016-04-03 04:06:41 +00:00
define ( 'PROTOCOL_ZOT', 'http://purl.org/zot/protocol' );
2018-05-18 10:09:38 +00:00
define ( 'PROTOCOL_ZOT6', 'http://purl.org/zot/protocol/6.0' );
2012-07-20 01:53:26 +00:00
define ( 'NAMESPACE_ZOT', 'http://purl.org/zot' );
define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' );
2010-09-10 00:55:59 +00:00
define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' );
define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' );
define ( 'NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/' );
define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' );
define ( 'NAMESPACE_MEDIA', 'http://purl.org/syndication/atommedia' );
define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env' );
define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe' );
define ( 'NAMESPACE_GEORSS', 'http://www.georss.org/georss' );
define ( 'NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0' );
define ( 'NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from' );
2011-06-21 02:08:40 +00:00
define ( 'NAMESPACE_OSTATUS', 'http://ostatus.org/schema/1.0' );
define ( 'NAMESPACE_STATUSNET', 'http://status.net/schema/api/1/' );
2011-07-21 06:14:43 +00:00
define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
define ( 'NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/' );
// We should be using versioned jsonld contexts so that signatures will be slightly more reliable.
// Why signatures are unreliable by design is a problem nobody seems to care about
2018-11-19 05:53:09 +00:00
// "because it's a W3C standard". .
// Anyway, if you use versioned contexts, communication with Mastodon fails. Have not yet investigated
// the reason for the dependency but for the current time, use the standard non-versioned context.
//define ( 'ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams-history/v1.8.jsonld' );
define ( 'ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams' );
2020-12-22 23:30:52 +00:00
define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.21' );
2019-09-21 22:26:55 +00:00
2010-12-10 12:04:35 +00:00
/**
* activity stream defines
*/
2010-10-13 09:47:32 +00:00
2019-05-28 03:50:05 +00:00
define ( 'ACTIVITY_PUBLIC_INBOX', 'https://www.w3.org/ns/activitystreams#Public' );
2019-05-28 23:42:32 +00:00
2017-07-20 01:32:16 +00:00
2018-05-29 02:42:40 +00:00
define ( 'ACTIVITY_POST', 'Create' );
2018-05-30 06:30:18 +00:00
define ( 'ACTIVITY_CREATE', 'Create' );
2018-05-29 02:42:40 +00:00
define ( 'ACTIVITY_UPDATE', 'Update' );
define ( 'ACTIVITY_LIKE', 'Like' );
define ( 'ACTIVITY_DISLIKE', 'Dislike' );
define ( 'ACTIVITY_SHARE', 'Announce' );
define ( 'ACTIVITY_FOLLOW', 'Follow' );
define ( 'ACTIVITY_IGNORE', 'Ignore');
2018-05-29 02:42:40 +00:00
define ( 'ACTIVITY_OBJ_COMMENT', 'Note' );
define ( 'ACTIVITY_OBJ_NOTE', 'Note' );
2018-07-12 01:02:25 +00:00
define ( 'ACTIVITY_OBJ_ARTICLE', 'Article' );
2018-05-29 02:42:40 +00:00
define ( 'ACTIVITY_OBJ_PERSON', 'Person' );
define ( 'ACTIVITY_OBJ_PHOTO', 'Image');
define ( 'ACTIVITY_OBJ_P_PHOTO', 'Icon' );
define ( 'ACTIVITY_OBJ_PROFILE', 'Profile');
define ( 'ACTIVITY_OBJ_EVENT', 'Event' );
2019-07-07 23:32:48 +00:00
define ( 'ACTIVITY_OBJ_POLL', 'Question');
define ( 'ACTIVITY_OBJ_FILE', 'Document');
2018-05-29 02:42:40 +00:00
2016-06-03 01:42:51 +00:00
define ( 'ACTIVITY_REACT', NAMESPACE_ZOT . '/activity/react' );
define ( 'ACTIVITY_AGREE', NAMESPACE_ZOT . '/activity/agree' );
define ( 'ACTIVITY_DISAGREE', NAMESPACE_ZOT . '/activity/disagree' );
define ( 'ACTIVITY_ABSTAIN', NAMESPACE_ZOT . '/activity/abstain' );
2015-02-10 08:11:37 +00:00
define ( 'ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes' );
define ( 'ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno' );
define ( 'ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe' );
define ( 'ACTIVITY_POLLRESPONSE', NAMESPACE_ZOT . '/activity/pollresponse' );
2012-11-06 05:05:51 +00:00
define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_ZOT . '/activity/heart' );
2010-09-10 00:55:59 +00:00
2010-09-09 03:14:17 +00:00
define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
2011-10-02 23:18:01 +00:00
define ( 'ACTIVITY_REQ_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'request-friend' );
define ( 'ACTIVITY_UNFRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'remove-friend' );
define ( 'ACTIVITY_JOIN', NAMESPACE_ACTIVITY_SCHEMA . 'join' );
2012-01-25 00:23:30 +00:00
define ( 'ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite' );
2018-09-20 03:45:42 +00:00
//define ( 'ACTIVITY_CREATE', NAMESPACE_ACTIVITY_SCHEMA . 'create' );
define ( 'ACTIVITY_DELETE', NAMESPACE_ACTIVITY_SCHEMA . 'delete' );
define ( 'ACTIVITY_WIN', NAMESPACE_ACTIVITY_SCHEMA . 'win' );
define ( 'ACTIVITY_LOSE', NAMESPACE_ACTIVITY_SCHEMA . 'lose' );
define ( 'ACTIVITY_TIE', NAMESPACE_ACTIVITY_SCHEMA . 'tie' );
define ( 'ACTIVITY_COMPLETE', NAMESPACE_ACTIVITY_SCHEMA . 'complete' );
2018-05-29 02:42:40 +00:00
define ( 'ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag' );
2010-09-09 03:14:17 +00:00
2012-07-20 01:53:26 +00:00
define ( 'ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke' );
2012-08-24 03:00:10 +00:00
define ( 'ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood' );
2012-07-20 01:53:26 +00:00
2018-05-29 02:42:40 +00:00
2017-06-17 02:30:02 +00:00
define ( 'ACTIVITY_OBJ_ACTIVITY',NAMESPACE_ACTIVITY_SCHEMA . 'activity' );
2010-09-09 03:14:17 +00:00
define ( 'ACTIVITY_OBJ_ALBUM', NAMESPACE_ACTIVITY_SCHEMA . 'photo-album' );
define ( 'ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group' );
define ( 'ACTIVITY_OBJ_GAME', NAMESPACE_ACTIVITY_SCHEMA . 'game' );
define ( 'ACTIVITY_OBJ_WIKI', NAMESPACE_ACTIVITY_SCHEMA . 'wiki' );
2012-11-06 05:05:51 +00:00
define ( 'ACTIVITY_OBJ_TAGTERM', NAMESPACE_ZOT . '/activity/tagterm' );
define ( 'ACTIVITY_OBJ_THING', NAMESPACE_ZOT . '/activity/thing' );
define ( 'ACTIVITY_OBJ_LOCATION',NAMESPACE_ZOT . '/activity/location' );
// define ( 'ACTIVITY_OBJ_FILE', NAMESPACE_ZOT . '/activity/file' );
define ( 'ACTIVITY_OBJ_CARD', NAMESPACE_ZOT . '/activity/card' );
2010-09-09 03:14:17 +00:00
2012-07-21 11:05:30 +00:00
/**
* Account Flags
*/
define ( 'ACCOUNT_OK', 0x0000 );
define ( 'ACCOUNT_UNVERIFIED', 0x0001 );
define ( 'ACCOUNT_BLOCKED', 0x0002 );
define ( 'ACCOUNT_EXPIRED', 0x0004 );
define ( 'ACCOUNT_REMOVED', 0x0008 );
define ( 'ACCOUNT_PENDING', 0x0010 );
2012-07-21 11:05:30 +00:00
/**
* Account roles
*/
define ( 'ACCOUNT_ROLE_SYSTEM', 0x0002 );
define ( 'ACCOUNT_ROLE_DEVELOPER', 0x0004 );
define ( 'ACCOUNT_ROLE_ADMIN', 0x1000 );
2012-07-21 11:05:30 +00:00
2012-10-06 08:51:59 +00:00
/**
* Item visibility
*/
define ( 'ITEM_VISIBLE', 0x0000);
2017-03-14 07:22:57 +00:00
define ( 'ITEM_HIDDEN', 0x0001);
2012-10-06 08:51:59 +00:00
define ( 'ITEM_BLOCKED', 0x0002);
define ( 'ITEM_MODERATED', 0x0004);
define ( 'ITEM_SPAM', 0x0008);
2017-03-14 07:22:57 +00:00
define ( 'ITEM_DELETED', 0x0010);
define ( 'ITEM_UNPUBLISHED', 0x0020);
2017-03-14 07:22:57 +00:00
define ( 'ITEM_WEBPAGE', 0x0040); // is a static web page, not a conversational item
2014-04-10 03:11:52 +00:00
define ( 'ITEM_DELAYED_PUBLISH', 0x0080);
2013-12-22 20:47:57 +00:00
define ( 'ITEM_BUILDBLOCK', 0x0100); // Named thusly to make sure nobody confuses this with ITEM_BLOCKED
2017-03-14 07:22:57 +00:00
define ( 'ITEM_PDL', 0x0200); // Page Description Language - e.g. Comanche
2013-12-22 20:47:57 +00:00
define ( 'ITEM_BUG', 0x0400); // Is a bug, can be used by the internal bug tracker
define ( 'ITEM_PENDING_REMOVE', 0x0800); // deleted, notification period has lapsed
define ( 'ITEM_DOC', 0x1000); // hubzilla only, define here so that item import does the right thing
2017-08-24 00:46:20 +00:00
define ( 'ITEM_CARD', 0x2000);
2017-11-22 19:49:28 +00:00
define ( 'ITEM_ARTICLE', 0x4000);
2017-08-24 00:46:20 +00:00
2015-01-29 22:51:41 +00:00
define ( 'ITEM_TYPE_POST', 0 );
define ( 'ITEM_TYPE_BLOCK', 1 );
define ( 'ITEM_TYPE_PDL', 2 );
define ( 'ITEM_TYPE_WEBPAGE', 3 );
2015-06-10 23:59:04 +00:00
define ( 'ITEM_TYPE_BUG', 4 );
2015-07-03 21:56:48 +00:00
define ( 'ITEM_TYPE_DOC', 5 );
define ( 'ITEM_TYPE_CARD', 6 );
2017-11-22 19:49:28 +00:00
define ( 'ITEM_TYPE_ARTICLE', 7 );
define ( 'ITEM_TYPE_MAIL', 8 );
2019-08-13 02:28:27 +00:00
define ( 'ITEM_TYPE_CUSTOM', 9 );
2019-08-13 01:16:46 +00:00
define ( 'ITEM_TYPE_REPORT', 10 );
2015-01-29 22:51:41 +00:00
2016-01-27 07:44:15 +00:00
define ( 'ITEM_IS_STICKY', 1000 );
2020-03-12 23:47:36 +00:00
define ( 'BLOCKTYPE_CHANNEL', 0 );
define ( 'BLOCKTYPE_SERVER', 1 );
2016-01-27 07:44:15 +00:00
define ( 'DBTYPE_MYSQL', 0 );
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
define ( 'DBTYPE_POSTGRES', 1 );
function sys_boot() {
// this file may not exist
@include('.htstartup.php');
// our central App object
2016-05-27 00:51:59 +00:00
App::init();
/*
* Load the configuration file which contains our DB credentials.
* Ignore errors. If the file doesn't exist or is empty, we are running in
* installation mode.
*/
2016-05-27 00:51:59 +00:00
App::$install = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? false : true);
2021-12-02 22:33:36 +00:00
$db_host = $db_user = $db_pass = $db_data = EMPTY_STR;
$db_port = $db_type = 0;
@include('.htconfig.php');
2021-03-09 03:54:24 +00:00
// allow somebody to set some initial settings
2021-03-09 03:54:24 +00:00
if (file_exists('.htpreconfig.php')) {
@include('.htpreconfig.php');
2021-03-09 03:54:24 +00:00
}
2021-12-02 22:33:36 +00:00
if (isset($default_timezone)) {
2016-08-08 00:40:56 +00:00
App::$config['system']['timezone'] = $default_timezone;
}
2021-03-09 03:54:24 +00:00
App::$timezone = (isset(App::$config['system']['timezone']) ? App::$config['system']['timezone'] : 'UTC');
2016-05-27 00:51:59 +00:00
date_default_timezone_set(App::$timezone);
2021-03-09 03:54:24 +00:00
if (! defined('DEFAULT_PLATFORM_ICON')) {
define( 'DEFAULT_PLATFORM_ICON', '/images/z1-32.png' );
}
2021-03-09 03:54:24 +00:00
if (! defined('DEFAULT_NOTIFY_ICON')) {
define( 'DEFAULT_NOTIFY_ICON', '/images/z1-64.png' );
}
/*
* Try to open the database;
*/
require_once('include/dba/dba_driver.php');
2021-03-09 03:54:24 +00:00
if (! App::$install) {
2016-05-27 00:51:59 +00:00
DBA::dba_factory($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type, App::$install);
2021-03-09 03:54:24 +00:00
if (! DBA::$dba->connected) {
system_unavailable();
}
unset($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type);
/*
* Load configs from db. Overwrite configs from .htconfig.php
*/
load_config('system');
load_config('feature');
2019-04-12 03:26:38 +00:00
App::$session = new Session();
2016-05-27 00:51:59 +00:00
App::$session->init();
load_hooks();
/**
2018-05-30 06:30:18 +00:00
* @hooks 'startup'
*/
2018-05-18 10:50:04 +00:00
$arr = [];
call_hooks('startup',$arr);
}
}
2011-07-18 04:34:02 +00:00
function startup() {
2021-03-09 01:51:41 +00:00
error_reporting(E_ERROR | E_PARSE);
// Some hosting providers block/disable this
@set_time_limit(0);
2011-09-23 00:35:49 +00:00
2019-04-12 03:26:38 +00:00
if (function_exists ('ini_set')) {
// This has to be quite large
@ini_set('pcre.backtrack_limit', 5000000);
// Use cookies to store the session ID on the client side
@ini_set('session.use_only_cookies', 1);
// Disable transparent Session ID support
@ini_set('session.use_trans_sid', 0);
}
2010-11-24 07:42:45 +00:00
}
2010-12-10 12:04:35 +00:00
/**
* class: App
*
* @brief Our main application structure for the life of this page.
*
2010-12-10 12:04:35 +00:00
* Primarily deals with the URL that got us here
* and tries to make some sense of it, and
2010-12-10 12:04:35 +00:00
* stores our page contents and config storage
* and anything else that might need to be passed around
* before we spit the page out.
2010-12-10 12:04:35 +00:00
*
*/
2013-02-26 23:49:37 +00:00
class App {
2016-03-31 20:00:04 +00:00
public static $install = false; // true if we are installing the software
public static $account = null; // account record of the logged-in account
public static $channel = null; // channel record of the current channel of the logged-in account
public static $observer = null; // xchan record of the page observer
public static $profile_uid = 0; // If applicable, the channel_id of the "page owner"
2021-09-23 22:26:31 +00:00
public static $sys_channel = null; // cache sys channel lookups here
2021-07-22 10:58:54 +00:00
public static $poi = null; // "person of interest", generally a referenced connection or directory entry
2016-03-31 20:00:04 +00:00
private static $oauth_key = null; // consumer_id of oauth request, if used
2019-04-12 03:26:38 +00:00
public static $layout = []; // Comanche parsed template
2016-03-31 20:00:04 +00:00
public static $pdl = null; // Comanche page description
private static $perms = null; // observer permissions
2019-04-12 03:26:38 +00:00
private static $widgets = []; // widgets for this page
public static $config = []; // config cache
public static $override_intltext_templates = [];
public static $override_markup_templates = [];
public static $override_templateroot = null;
public static $override_helproot = null;
public static $override_helpfiles = [];
2016-03-31 20:00:04 +00:00
public static $session = null;
2016-03-31 20:00:04 +00:00
public static $groups;
public static $language;
2016-04-01 06:41:20 +00:00
public static $langsave;
public static $rtl = false;
2016-04-01 06:41:20 +00:00
public static $plugins_admin;
2016-03-31 20:00:04 +00:00
public static $module_loaded = false;
public static $query_string;
public static $page;
public static $profile;
public static $user;
public static $cid;
public static $contact;
public static $contacts;
public static $content;
2019-04-12 03:26:38 +00:00
public static $data = [];
2016-03-31 20:00:04 +00:00
public static $error = false;
public static $emojitab = false;
2016-03-31 20:00:04 +00:00
public static $cmd;
public static $argv;
public static $argc;
public static $module;
public static $pager;
public static $strings;
public static $stringsave; // used in push_lang() and pop_lang()
2016-03-31 20:00:04 +00:00
public static $hooks;
public static $timezone;
public static $interactive = true;
public static $plugins;
2019-04-12 03:26:38 +00:00
private static $apps = [];
2016-03-31 20:00:04 +00:00
public static $identities;
2019-04-12 03:26:38 +00:00
public static $css_sources = [];
public static $js_sources = [];
public static $linkrel = [];
public static $theme_info = [];
2016-03-31 20:00:04 +00:00
public static $is_sys = false;
public static $nav_sel;
public static $comanche;
2018-05-30 04:08:52 +00:00
public static $httpheaders = null;
public static $httpsig = null;
2019-04-12 03:26:38 +00:00
public static $channel_links;
2016-03-31 20:00:04 +00:00
public static $category;
2013-02-26 23:49:37 +00:00
// Allow themes to control internal parameters
// by changing App values in theme.php
2016-03-31 20:00:04 +00:00
public static $sourcename = '';
public static $videowidth = 425;
public static $videoheight = 350;
public static $force_max_items = 0;
public static $theme_thread_allow = true;
2013-02-26 23:49:37 +00:00
2019-06-30 00:54:48 +00:00
public static $meta;
/**
* @brief An array for all theme-controllable parameters
*
* Mostly unimplemented yet. Only options 'template_engine' and
* beyond are used.
*/
2019-04-12 03:26:38 +00:00
private static $theme = [
'sourcename' => '',
'videowidth' => 425,
'videoheight' => 350,
2013-02-26 23:49:37 +00:00
'force_max_items' => 0,
2019-04-12 03:26:38 +00:00
'thread_allow' => true,
'stylesheet' => '',
'template_engine' => 'smarty3',
2019-04-12 03:26:38 +00:00
];
2013-01-06 21:42:51 +00:00
/**
* @brief An array of registered template engines ('name'=>'class name')
*/
2019-04-12 03:26:38 +00:00
public static $template_engines = [];
/**
* @brief An array of instanced template engines ('name'=>'instance')
*/
2019-04-12 03:26:38 +00:00
public static $template_engine_instance = [];
2014-04-10 03:11:52 +00:00
2019-04-12 03:26:38 +00:00
private static $ldelim = [
2013-02-26 23:49:37 +00:00
'internal' => '',
'smarty3' => '{{'
2019-04-12 03:26:38 +00:00
];
private static $rdelim = [
2013-02-26 23:49:37 +00:00
'internal' => '',
'smarty3' => '}}'
2019-04-12 03:26:38 +00:00
];
// These represent the URL which was used to access the page
2016-03-31 20:00:04 +00:00
private static $scheme;
private static $hostname;
private static $path;
// This is our standardised URL - regardless of what was used
// to access the page
2016-03-31 20:00:04 +00:00
private static $baseurl;
/**
* App constructor.
*/
2019-06-02 03:08:09 +00:00
2016-06-04 02:46:48 +00:00
public static function init() {
// we'll reset this after we read our config file
date_default_timezone_set('UTC');
2019-04-12 03:26:38 +00:00
self::$config = [
'system' => []
];
self::$page = [];
self::$pager= [];
2016-03-31 20:00:04 +00:00
self::$query_string = '';
2010-07-01 23:48:07 +00:00
2013-02-26 23:49:37 +00:00
startup();
set_include_path(
'include' . PATH_SEPARATOR
. 'library' . PATH_SEPARATOR
2019-06-02 03:08:09 +00:00
. '.'
);
2021-01-25 21:56:45 +00:00
// normally self::$hostname (also scheme and port) will be filled in during startup.
// Set it manually from $_SERVER variables only if it wasn't.
2021-12-15 08:36:57 +00:00
2021-01-25 21:56:45 +00:00
if (! self::$hostname) {
self::$hostname = punify(get_host());
self::$scheme = 'http';
2021-12-15 08:36:57 +00:00
2021-03-09 03:54:24 +00:00
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) {
2021-01-25 21:56:45 +00:00
self::$scheme = 'https';
2021-03-09 03:54:24 +00:00
}
elseif (isset($_SERVER['SERVER_PORT']) && (intval($_SERVER['SERVER_PORT']) === 443)) {
2021-01-25 21:56:45 +00:00
self::$scheme = 'https';
2021-03-09 03:54:24 +00:00
}
2010-10-30 20:25:37 +00:00
2021-03-09 03:54:24 +00:00
if (isset($_SERVER['SERVER_PORT']) && intval($_SERVER['SERVER_PORT']) !== 80 && intval($_SERVER['SERVER_PORT']) !== 443) {
2016-03-31 20:00:04 +00:00
self::$hostname .= ':' . $_SERVER['SERVER_PORT'];
2021-03-09 03:54:24 +00:00
}
2013-02-26 23:49:37 +00:00
}
2010-12-11 04:21:34 +00:00
2021-01-25 21:56:45 +00:00
/*
* Figure out if we are running at the top of a domain
* or in a sub-directory and adjust accordingly
*/
$path = trim(dirname($_SERVER['SCRIPT_NAME']),'/\\');
2021-03-09 03:54:24 +00:00
if (isset($path) && strlen($path) && ($path != self::$path)) {
2021-01-25 21:56:45 +00:00
self::$path = $path;
2021-03-09 03:54:24 +00:00
}
2021-01-25 21:56:45 +00:00
2021-07-22 10:58:54 +00:00
// Rewrite rules on the server will convert incoming paths to a request parameter.
// Strip this path information from our stored copy of the query_string, in case
// we need to re-use the rest of the original query.
2021-12-15 08:36:57 +00:00
2021-03-09 03:54:24 +00:00
if (isset($_SERVER['QUERY_STRING']) && substr($_SERVER['QUERY_STRING'], 0, 4) === "req=") {
self::$query_string = str_replace(['<','>'],['&lt;','&gt;'],substr($_SERVER['QUERY_STRING'], 4));
2021-07-22 10:58:54 +00:00
// removing leading '/' - maybe a nginx problem
2018-07-19 01:55:28 +00:00
if (substr(self::$query_string, 0, 1) == "/") {
2016-03-31 20:00:04 +00:00
self::$query_string = substr(self::$query_string, 1);
}
// change the first & to ?
self::$query_string = preg_replace('/&/','?',self::$query_string,1);
2013-02-26 23:49:37 +00:00
}
2018-07-19 00:48:23 +00:00
2021-07-22 10:58:54 +00:00
// Here is where start breaking out the URL path information to both route the
// web request based on the leading path component, and also to use remaining
// path components as C-style arguments to our individual controller modules.
2021-12-15 08:36:57 +00:00
2021-03-09 03:54:24 +00:00
if (isset($_GET['req'])) {
self::$cmd = escape_tags(trim($_GET['req'],'/\\'));
2021-03-09 03:54:24 +00:00
}
2021-03-09 03:54:24 +00:00
// support both unix and fediverse style "homedir"
2021-03-09 03:54:24 +00:00
if ((substr(self::$cmd, 0, 1) === '~') || (substr(self::$cmd, 0, 1) === '@')) {
2016-03-31 20:00:04 +00:00
self::$cmd = 'channel/' . substr(self::$cmd, 1);
2021-03-09 03:54:24 +00:00
}
/*
2013-02-26 23:49:37 +00:00
* Break the URL path into C style argc/argv style arguments for our
2016-03-31 20:00:04 +00:00
* modules. Given "http://example.com/module/arg1/arg2", self::$argc
* will be 3 (integer) and self::$argv will contain:
2013-02-26 23:49:37 +00:00
* [0] => 'module'
* [1] => 'arg1'
* [2] => 'arg2'
*
* There will always be one argument. If provided a naked domain
2016-03-31 20:00:04 +00:00
* URL, self::$argv[0] is set to "home".
*
* If $argv[0] has a period in it, for example foo.json; rewrite
* to module = 'foo' and set $_REQUEST['module_format'] = 'json';
2021-07-22 10:58:54 +00:00
*
* As a result, say you offered a feed for member bob. Most applications
* would address it as /feed/bob.xml or /feed/bob.json
* We would address it as /feed.xml/bob and /feed.json/bob because
* you're altering the output format of the feed module, and bob is
* just an identifier or variable.
2013-02-26 23:49:37 +00:00
*/
2016-03-31 20:00:04 +00:00
self::$argv = explode('/', self::$cmd);
2016-03-31 20:00:04 +00:00
self::$argc = count(self::$argv);
if ((array_key_exists('0', self::$argv)) && strlen(self::$argv[0])) {
if(strpos(self::$argv[0],'.')) {
$_REQUEST['module_format'] = substr(self::$argv[0],strpos(self::$argv[0],'.')+1);
self::$argv[0] = substr(self::$argv[0],0,strpos(self::$argv[0],'.'));
}
2016-03-31 20:00:04 +00:00
self::$module = str_replace(".", "_", self::$argv[0]);
self::$module = str_replace("-", "_", self::$module);
if(strpos(self::$module,'_') === 0)
self::$module = substr(self::$module,1);
} else {
2016-03-31 20:00:04 +00:00
self::$argc = 1;
self::$argv = array('home');
self::$module = 'home';
2013-02-26 23:49:37 +00:00
}
/*
2013-02-26 23:49:37 +00:00
* See if there is any page number information, and initialise
* pagination
*/
2010-12-11 04:21:34 +00:00
self::$pager['unset'] = ((array_key_exists('page',$_REQUEST)) ? false : true);
2019-04-12 03:26:38 +00:00
self::$pager['page'] = ((x($_GET,'page') && intval($_GET['page']) > 0) ? intval($_GET['page']) : 1);
2016-03-31 20:00:04 +00:00
self::$pager['itemspage'] = 60;
2019-04-12 03:26:38 +00:00
self::$pager['start'] = (self::$pager['page'] * self::$pager['itemspage']) - self::$pager['itemspage'];
self::$pager['total'] = 0;
if (self::$pager['start'] < 0) {
2016-03-31 20:00:04 +00:00
self::$pager['start'] = 0;
2019-04-12 03:26:38 +00:00
}
self::$meta = new HttpMeta();
/*
2019-04-12 03:26:38 +00:00
* register template engines (probably just smarty, but this can be extended)
*/
2016-05-21 02:11:14 +00:00
2021-12-02 23:02:31 +00:00
self::register_template_engine(get_class(new SmartyTemplate()));
2013-02-26 23:49:37 +00:00
}
2010-11-11 10:49:28 +00:00
2016-03-31 20:00:04 +00:00
public static function get_baseurl($ssl = false) {
if(is_array(self::$config)
&& array_key_exists('system',self::$config)
&& is_array(self::$config['system'])
&& array_key_exists('baseurl',self::$config['system'])
&& strlen(self::$config['system']['baseurl'])) {
// get_baseurl() is a heavily used function.
// Do not use punify() here until we find a library that performs better than what we have now.
2019-04-12 03:26:38 +00:00
// $url = punify(self::$config['system']['baseurl']);
$url = self::$config['system']['baseurl'];
$url = trim($url,'\\/');
return $url;
}
2016-03-31 20:00:04 +00:00
$scheme = self::$scheme;
self::$baseurl = $scheme . "://" . punify(self::$hostname) . ((isset(self::$path) && strlen(self::$path)) ? '/' . self::$path : '' );
2016-03-31 20:00:04 +00:00
return self::$baseurl;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function set_baseurl($url) {
if(is_array(self::$config)
&& array_key_exists('system',self::$config)
&& is_array(self::$config['system'])
&& array_key_exists('baseurl',self::$config['system'])
&& strlen(self::$config['system']['baseurl'])) {
$url = punify(self::$config['system']['baseurl']);
$url = trim($url,'\\/');
2013-02-26 23:49:37 +00:00
}
2010-07-19 03:49:10 +00:00
2013-02-26 23:49:37 +00:00
$parsed = @parse_url($url);
2016-03-31 20:00:04 +00:00
self::$baseurl = $url;
2018-01-31 02:16:20 +00:00
if($parsed !== false) {
2016-03-31 20:00:04 +00:00
self::$scheme = $parsed['scheme'];
self::$hostname = punify($parsed['host']);
2013-02-26 23:49:37 +00:00
if(x($parsed,'port'))
2016-03-31 20:00:04 +00:00
self::$hostname .= ':' . $parsed['port'];
2013-02-26 23:49:37 +00:00
if(x($parsed,'path'))
2016-03-31 20:00:04 +00:00
self::$path = trim($parsed['path'],'\\/');
}
2013-02-26 23:49:37 +00:00
}
2010-07-01 23:48:07 +00:00
2016-03-31 20:00:04 +00:00
public static function get_scheme() {
return self::$scheme;
}
2016-03-31 20:00:04 +00:00
public static function get_hostname() {
return self::$hostname;
2013-02-26 23:49:37 +00:00
}
2010-07-19 06:23:18 +00:00
2016-03-31 20:00:04 +00:00
public static function set_hostname($h) {
self::$hostname = $h;
2013-02-26 23:49:37 +00:00
}
2010-07-19 03:49:10 +00:00
2016-03-31 20:00:04 +00:00
public static function set_path($p) {
self::$path = trim(trim($p), '/');
2013-02-26 23:49:37 +00:00
}
2010-07-01 23:48:07 +00:00
2016-03-31 20:00:04 +00:00
public static function get_path() {
return self::$path;
2013-02-26 23:49:37 +00:00
}
public static function get_channel_links() {
$s = '';
$x = self::$channel_links;
2019-04-12 03:26:38 +00:00
if ($x && is_array($x) && count($x)) {
foreach ($x as $y) {
if ($s) {
$s .= ',';
}
2021-03-11 00:51:42 +00:00
$s .= '<' . $y['href'] . '>; rel="' . $y['rel'] . '"; type="' . $y['type'] . '"';
}
}
return $s;
}
2016-03-31 20:00:04 +00:00
public static function set_account($acct) {
self::$account = $acct;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function get_account() {
return self::$account;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function set_channel($channel) {
self::$channel = $channel;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function get_channel() {
return self::$channel;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function set_observer($xchan) {
self::$observer = $xchan;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function get_observer() {
return self::$observer;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function set_perms($perms) {
self::$perms = $perms;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function get_perms() {
return self::$perms;
2013-02-26 23:49:37 +00:00
}
2012-10-22 05:11:02 +00:00
2016-03-31 20:00:04 +00:00
public static function set_oauth_key($consumer_id) {
self::$oauth_key = $consumer_id;
}
2016-03-31 20:00:04 +00:00
public static function get_oauth_key() {
return self::$oauth_key;
}
2016-03-31 20:00:04 +00:00
public static function get_apps() {
return self::$apps;
2013-02-26 23:49:37 +00:00
}
2012-10-22 05:11:02 +00:00
2016-03-31 20:00:04 +00:00
public static function set_apps($arr) {
self::$apps = $arr;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function set_groups($g) {
self::$groups = $g;
2013-02-26 23:49:37 +00:00
}
2012-10-22 05:11:02 +00:00
2016-03-31 20:00:04 +00:00
public static function get_groups() {
return self::$groups;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function set_pager_total($n) {
self::$pager['total'] = intval($n);
2013-02-26 23:49:37 +00:00
}
2010-07-01 23:48:07 +00:00
2016-03-31 20:00:04 +00:00
public static function set_pager_itemspage($n) {
self::$pager['itemspage'] = ((intval($n) > 0) ? intval($n) : 0);
self::$pager['start'] = (self::$pager['page'] * self::$pager['itemspage']) - self::$pager['itemspage'];
2013-02-26 23:49:37 +00:00
}
2013-01-06 21:42:51 +00:00
2016-03-31 20:00:04 +00:00
public static function build_pagehead() {
2013-01-06 21:42:51 +00:00
$user_scalable = ((local_channel()) ? get_pconfig(local_channel(),'system','user_scalable', 0) : 0);
$preload_images = ((local_channel()) ? get_pconfig(local_channel(),'system','preload_images',0) : 0);
2021-08-24 04:52:21 +00:00
$interval = ((local_channel()) ? get_pconfig(local_channel(),'system','update_interval', 30000) : 30000);
if ($interval < 15000) {
$interval = 15000;
}
$alerts_interval = intval(get_config('system','alerts_interval',10000));
if ($alerts_interval < 5000) {
$alerts_interval = 5000;
}
2013-01-06 21:42:51 +00:00
if (! x(self::$page,'title')) {
self::$page['title'] = ((array_path_exists('system/sitename',self::$config)) ? self::$config['system']['sitename'] : EMPTY_STR);
}
if (! self::$meta->get_field('og:title')) {
2016-03-31 20:00:04 +00:00
self::$meta->set('og:title',self::$page['title']);
}
// webmanifest
2021-08-16 22:02:39 +00:00
head_add_link( [ 'rel' => 'manifest', 'href' => z_root() . '/manifest.webmanifest' ] );
self::$meta->set('application-name', System::get_platform_name() );
2019-04-12 03:26:38 +00:00
self::$meta->set('generator', System::get_platform_name());
2016-03-09 00:21:35 +00:00
$i = head_get_icon();
2019-05-06 04:06:02 +00:00
if (! $i) {
2020-09-17 01:03:14 +00:00
$i = System::get_site_icon();
2019-05-06 04:06:02 +00:00
}
if ($i) {
2019-05-06 04:06:02 +00:00
head_add_link(['rel' => 'shortcut icon', 'href' => $i ]);
2021-08-16 21:21:42 +00:00
head_add_link(['rel' => 'icon', 'sizes' => '64x64', 'href' => System::get_site_icon() ]);
2021-08-16 22:02:39 +00:00
head_add_link(['rel' => 'icon', 'sizes' => '192x192', 'href' => 'images/' . System::get_platform_name() . '.svg' ]);
}
2017-02-02 22:49:51 +00:00
$x = [ 'header' => '' ];
/**
* @hooks build_pagehead
* Called when creating the HTML page header.
* * \e string \b header - Return the HTML header which should be added
*/
call_hooks('build_pagehead', $x);
2017-02-02 22:49:51 +00:00
2013-02-26 23:49:37 +00:00
/* put the head template at the beginning of page['htmlhead']
* since the code added by the modules frequently depends on it
* being first
*/
2017-03-12 23:30:05 +00:00
if (! isset(self::$page['htmlhead'])) {
self::$page['htmlhead'] = EMPTY_STR; // needed to silence warning
}
self::$page['htmlhead'] = replace_macros(get_markup_template('head.tpl'),
2017-03-12 23:30:05 +00:00
[
'$preload_images' => $preload_images,
'$user_scalable' => $user_scalable,
'$query' => urlencode(self::$query_string),
'$baseurl' => self::get_baseurl(),
'$local_channel' => local_channel(),
'$metas' => self::$meta->get(),
'$plugins' => $x['header'],
'$update_interval' => $interval,
'$alerts_interval' => $alerts_interval,
2017-03-12 23:30:05 +00:00
'$head_css' => head_get_css(),
'$head_js' => head_get_js(),
'$linkrel' => head_get_links(),
'$js_strings' => js_strings(),
2022-01-25 01:26:12 +00:00
'$zid' => Channel::get_my_address(),
2021-03-11 05:31:13 +00:00
'$channel_id' => ((isset(self::$profile) && is_array(self::$profile) && array_key_exists('uid',self::$profile)) ? self::$profile['uid'] : '')
2017-03-12 23:30:05 +00:00
]
) . self::$page['htmlhead'];
2014-06-14 00:33:03 +00:00
// always put main.js at the end
2016-03-31 20:00:04 +00:00
self::$page['htmlhead'] .= head_get_main_js();
2013-02-26 23:49:37 +00:00
}
/**
* @brief Register template engine class.
*
* If $name is "", is used class static property $class::$name.
*
* @param string $class
* @param string $name
*/
2016-03-31 20:00:04 +00:00
public static function register_template_engine($class, $name = '') {
if (! $name) {
2017-03-12 23:30:05 +00:00
$v = get_class_vars($class);
if (x($v, "name")) {
2017-03-12 23:30:05 +00:00
$name = $v['name'];
}
2014-04-10 03:11:52 +00:00
}
2017-03-12 23:30:05 +00:00
if (! $name) {
2021-12-02 22:33:36 +00:00
echo "template engine <b>$class</b> cannot be registered without a name.\n";
2014-04-10 03:11:52 +00:00
killme();
}
2016-03-31 20:00:04 +00:00
self::$template_engines[$name] = $class;
}
/**
* @brief Return template engine instance.
*
* If $name is not defined, return engine defined by theme, or default.
2014-04-10 03:11:52 +00:00
*
* @param string $name Template engine name
*
2021-12-02 22:33:36 +00:00
* @return void Template Engine instance
*/
2019-04-12 03:26:38 +00:00
public static function template_engine($name = '') {
if ($name !== '') {
2014-04-10 03:11:52 +00:00
$template_engine = $name;
2017-03-12 23:30:05 +00:00
}
else {
2014-04-10 03:11:52 +00:00
$template_engine = 'smarty3';
if (x(self::$theme, 'template_engine')) {
2016-03-31 20:00:04 +00:00
$template_engine = self::$theme['template_engine'];
2014-04-10 03:11:52 +00:00
}
}
2019-04-12 03:26:38 +00:00
if (isset(self::$template_engines[$template_engine])) {
if (isset(self::$template_engine_instance[$template_engine])) {
2016-03-31 20:00:04 +00:00
return self::$template_engine_instance[$template_engine];
2017-03-12 23:30:05 +00:00
}
else {
2016-03-31 20:00:04 +00:00
$class = self::$template_engines[$template_engine];
2021-12-02 23:02:31 +00:00
$obj = new $class();
2016-03-31 20:00:04 +00:00
self::$template_engine_instance[$template_engine] = $obj;
2014-04-10 03:11:52 +00:00
return $obj;
}
}
2019-04-12 03:26:38 +00:00
// If we fell through to this step, it is considered fatal.
2021-12-02 22:33:36 +00:00
echo "template engine <b>$template_engine</b> is not registered!\n";
2017-03-12 23:30:05 +00:00
killme();
2014-04-10 03:11:52 +00:00
}
/**
* @brief Returns the active template engine.
*
* @return string
*/
2016-03-31 20:00:04 +00:00
public static function get_template_engine() {
return self::$theme['template_engine'];
2013-02-26 23:49:37 +00:00
}
2013-01-06 21:42:51 +00:00
2016-03-31 20:00:04 +00:00
public static function set_template_engine($engine = 'smarty3') {
self::$theme['template_engine'] = $engine;
2013-02-26 23:49:37 +00:00
}
2016-03-31 20:00:04 +00:00
public static function get_template_ldelim($engine = 'smarty3') {
return self::$ldelim[$engine];
2013-02-26 23:49:37 +00:00
}
2013-01-06 21:42:51 +00:00
2016-03-31 20:00:04 +00:00
public static function get_template_rdelim($engine = 'smarty3') {
return self::$rdelim[$engine];
2013-02-26 23:49:37 +00:00
}
2013-01-06 21:42:51 +00:00
2016-03-31 20:00:04 +00:00
public static function head_set_icon($icon) {
self::$data['pageicon'] = $icon;
}
2016-03-31 20:00:04 +00:00
public static function head_get_icon() {
$icon = self::$data['pageicon'];
if ($icon && ! strpos($icon,'://')) {
$icon = z_root() . $icon;
}
return $icon;
}
} // End App class
2010-07-01 23:48:07 +00:00
/**
* @brief Multi-purpose function to check variable state.
*
2021-09-23 22:26:31 +00:00
* Usage: x($var) or x($array, 'key')
*
* returns false if variable/key is not set
2021-09-23 22:26:31 +00:00
* if variable is set, returns 1 if variable contains 'truthy' value, otherwise returns 0.
* e.g. x('') or x(0) returns 0;
*
* @param string|array $s variable to check
* @param string $k key inside the array to check
*
* @return bool|int
*/
function x($s, $k = null) {
if($k != null) {
if((is_array($s)) && (array_key_exists($k, $s))) {
if($s[$k])
return (int) 1;
return (int) 0;
}
return false;
}
else {
if(isset($s)) {
if($s) {
return (int) 1;
2010-07-01 23:48:07 +00:00
}
return (int) 0;
2010-07-01 23:48:07 +00:00
}
return false;
2010-07-01 23:48:07 +00:00
}
}
2010-07-01 23:48:07 +00:00
/**
* @brief Called from db initialisation if db is dead.
*
* @ref include/system_unavailable.php will handle everything further.
*/
function system_unavailable() {
include('include/system_unavailable.php');
system_down();
killme();
}
2010-07-01 23:48:07 +00:00
2011-06-14 09:16:27 +00:00
function clean_urls() {
2016-03-31 23:06:03 +00:00
// if(App::$config['system']['clean_urls'])
return true;
// return false;
}
function z_path() {
2016-03-31 05:13:24 +00:00
$base = z_root();
if(! clean_urls())
$base .= '/?q=';
return $base;
}
/**
* @brief Returns the baseurl.
*
* @see App::get_baseurl()
*
* @return string
*/
function z_root() {
2016-03-31 23:06:03 +00:00
return App::get_baseurl();
}
/**
* @brief Return absolute URL for given $path.
*
* @param string $path
*
* @return string
*/
function absurl($path) {
2021-12-15 08:36:57 +00:00
if (strpos($path, '/') === 0) {
return z_path() . $path;
2021-12-15 08:36:57 +00:00
}
return $path;
}
function os_mkdir($path, $mode = 0777, $recursive = false) {
$oldumask = @umask(0);
2015-03-29 23:05:08 +00:00
$result = @mkdir($path, $mode, $recursive);
@umask($oldumask);
return $result;
}
/**
* @brief Recursively delete a directory.
*
* @param string $path
2021-12-02 23:02:31 +00:00
* @return bool
*/
function rrmdir($path) {
2019-04-12 03:26:38 +00:00
if (is_dir($path) === true) {
$files = array_diff(scandir($path), array('.', '..'));
2019-04-12 03:26:38 +00:00
foreach ($files as $file) {
rrmdir(realpath($path) . '/' . $file);
}
return rmdir($path);
}
2019-04-12 03:26:38 +00:00
elseif (is_file($path) === true) {
return unlink($path);
}
return false;
}
/**
* @brief Function to check if request was an AJAX (xmlhttprequest) request.
*
2021-12-02 23:02:31 +00:00
* @return bool
*/
function is_ajax() {
return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
}
function killme_if_ajax() {
2019-04-12 03:26:38 +00:00
if (is_ajax()) {
killme();
}
}
/**
* Primarily involved with database upgrade, but also sets the
* base url for use in cmdline programs which don't have
* $_SERVER variables, and synchronising the state of installed plugins.
*/
2017-03-24 04:49:20 +00:00
function check_config() {
$saved = get_config('system','urlverify');
2019-04-12 03:26:38 +00:00
if (! $saved) {
set_config('system','urlverify', bin2hex(z_root()));
}
if(($saved) && ($saved != bin2hex(z_root()))) {
// our URL changed. Do something.
$oldurl = hex2bin($saved);
logger('Baseurl changed!');
2014-04-10 03:11:52 +00:00
$oldhost = substr($oldurl, strpos($oldurl, '//') + 2);
$host = substr(z_root(), strpos(z_root(), '//') + 2);
$is_ip_addr = ((preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$host)) ? true : false);
$was_ip_addr = ((preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$oldhost)) ? true : false);
// only change the url to an ip address if it was already an ip and not a dns name
if((! $is_ip_addr) || ($is_ip_addr && $was_ip_addr)) {
fix_system_urls($oldurl,z_root());
set_config('system', 'urlverify', bin2hex(z_root()));
}
else
2014-04-10 03:11:52 +00:00
logger('Attempt to change baseurl from a DNS name to an IP address was refused.');
}
2014-04-10 03:11:52 +00:00
// This will actually set the url to the one stored in .htconfig, and ignore what
// we're passing - unless we are installing and it has never been set.
2016-03-31 23:06:03 +00:00
App::set_baseurl(z_root());
2021-09-24 19:55:17 +00:00
// Ensure the site has a system channel and that it has been upgraded.
// This function will only do work if work is required.
2022-01-25 01:26:12 +00:00
Channel::create_system();
2021-09-21 05:51:28 +00:00
2019-04-12 03:26:38 +00:00
$x = new DB_Upgrade(DB_UPDATE_VERSION);
2018-02-03 20:50:07 +00:00
plugins_sync();
2011-03-09 10:12:32 +00:00
2013-02-26 23:49:37 +00:00
load_hooks();
2016-02-20 00:19:15 +00:00
check_cron_broken();
2013-02-26 23:49:37 +00:00
}
function fix_system_urls($oldurl, $newurl) {
2013-03-11 01:45:58 +00:00
logger('fix_system_urls: renaming ' . $oldurl . ' to ' . $newurl);
2013-03-11 01:45:58 +00:00
// Basically a site rename, but this can happen if you change from http to https for instance - even if the site name didn't change
// This should fix URL changes on our site, but other sites will end up with orphan hublocs which they will try to contact and will
// cause wasted communications.
// What we need to do after fixing this up is to send a revocation of the old URL to every other site that we communicate with so
// that they can clean up their hubloc tables (this includes directories).
// It's a very expensive operation so you don't want to have to do it often or after your site gets to be large.
$r = q("select xchan.*, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_url like '%s'",
2013-08-25 00:05:01 +00:00
dbesc($oldurl . '%')
2013-03-11 01:45:58 +00:00
);
2013-03-11 01:45:58 +00:00
if($r) {
2016-08-15 05:44:25 +00:00
foreach($r as $rv) {
$channel_address = substr($rv['hubloc_addr'],0,strpos($rv['hubloc_addr'],'@'));
// get the associated channel. If we don't have a local channel, do nothing for this entry.
$c = q("select * from channel where channel_hash = '%s' limit 1",
2016-08-15 05:44:25 +00:00
dbesc($rv['hubloc_hash'])
);
if(! $c)
continue;
2013-09-10 02:02:38 +00:00
$parsed = @parse_url($newurl);
2013-03-11 01:45:58 +00:00
if(! $parsed)
continue;
$newhost = $parsed['host'];
2013-08-27 01:15:30 +00:00
// sometimes parse_url returns unexpected results.
if(strpos($newhost,'/') !== false)
$newhost = substr($newhost,0,strpos($newhost,'/'));
2013-08-27 01:15:30 +00:00
$rhs = $newhost . (($parsed['port']) ? ':' . $parsed['port'] : '');
// paths aren't going to work. You have to be at the (sub)domain root
// . (($parsed['path']) ? $parsed['path'] : '');
2013-03-11 01:45:58 +00:00
// The xchan_url might point to another nomadic identity clone
2016-08-15 05:44:25 +00:00
$replace_xchan_url = ((strpos($rv['xchan_url'],$oldurl) !== false) ? true : false);
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$x = q("update xchan set xchan_addr = '%s', xchan_url = '%s', xchan_connurl = '%s', xchan_follow = '%s', xchan_connpage = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
dbesc($channel_address . '@' . $rhs),
2016-08-15 05:44:25 +00:00
dbesc(($replace_xchan_url) ? str_replace($oldurl,$newurl,$rv['xchan_url']) : $rv['xchan_url']),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_connurl'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_follow'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_connpage'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_l'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_m'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_s'])),
2013-09-05 23:26:40 +00:00
dbesc(datetime_convert()),
2016-08-15 05:44:25 +00:00
dbesc($rv['xchan_hash'])
2013-03-11 01:45:58 +00:00
);
$y = q("update hubloc set hubloc_addr = '%s', hubloc_url = '%s', hubloc_id_url = '%s', hubloc_url_sig = '%s', hubloc_site_id = '%s', hubloc_host = '%s', hubloc_callback = '%s' where hubloc_hash = '%s' and hubloc_url = '%s'",
dbesc($channel_address . '@' . $rhs),
2013-03-11 01:45:58 +00:00
dbesc($newurl),
2019-04-26 22:15:15 +00:00
dbesc(str_replace($oldurl,$newurl,$rv['hubloc_id_url'])),
2018-06-01 02:42:13 +00:00
dbesc(Libzot::sign($newurl,$c[0]['channel_prvkey'])),
dbesc(Libzot::make_xchan_hash($newurl,Config::Get('system','pubkey'))),
2013-03-11 01:45:58 +00:00
dbesc($newhost),
dbesc($newurl . '/post'),
2016-08-15 05:44:25 +00:00
dbesc($rv['xchan_hash']),
2013-03-11 01:45:58 +00:00
dbesc($oldurl)
);
$z = q("update profile set photo = '%s', thumb = '%s' where uid = %d",
2016-08-15 05:44:25 +00:00
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_l'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_m'])),
intval($c[0]['channel_id'])
);
2014-04-10 03:11:52 +00:00
$m = q("select abook_id, abook_instance from abook where abook_instance like '%s' and abook_channel = %d",
dbesc('%' . $oldurl . '%'),
intval($c[0]['channel_id'])
);
if($m) {
foreach($m as $mm) {
q("update abook set abook_instance = '%s' where abook_id = %d",
dbesc(str_replace($oldurl,$newurl,$mm['abook_instance'])),
intval($mm['abook_id'])
);
}
}
Run::Summon( [ 'Notifier', 'refresh_all', $c[0]['channel_id'] ]);
2013-03-11 01:45:58 +00:00
}
}
// fix links in apps
$a = q("select id, app_url, app_photo from app where app_url like '%s' OR app_photo like '%s'",
dbesc('%' . $oldurl . '%'),
dbesc('%' . $oldurl . '%')
);
if($a) {
foreach($a as $aa) {
q("update app set app_url = '%s', app_photo = '%s' where id = %d",
dbesc(str_replace($oldurl,$newurl,$aa['app_url'])),
dbesc(str_replace($oldurl,$newurl,$aa['app_photo'])),
intval($aa['id'])
);
}
}
// now replace any remote xchans whose photos are stored locally (which will be most if not all remote xchans)
$r = q("select * from xchan where xchan_photo_l like '%s'",
dbesc($oldurl . '%')
);
if($r) {
2016-08-15 05:44:25 +00:00
foreach($r as $rv) {
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
2016-08-15 05:44:25 +00:00
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_l'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_m'])),
dbesc(str_replace($oldurl,$newurl,$rv['xchan_photo_s'])),
dbesc($rv['xchan_hash'])
);
}
}
2013-03-11 01:45:58 +00:00
}
/**
* @brief Wrapper for adding a login box.
*
* If $register == true provide a registration link. This will most always depend
* on the value of App::$config['system']['register_policy'].
* Returns the complete html for inserting into the page
*
2021-12-02 23:02:31 +00:00
* @param bool $register (optional) default false
* @param string $form_id (optional) default \e main-login
2021-12-02 23:02:31 +00:00
* @param bool $hiddens (optional) default false
* @param bool $login_page (optional) default true
* @return string Parsed HTML code.
*/
function login($register = false, $form_id = 'main-login', $hiddens = false, $login_page = true) {
$o = '';
$reg = null;
// Here's the current description of how the register link works (2018-05-15)
// Register links are enabled on the site home page and login page and navbar.
// They are not shown by default on other pages which may require login.
// system.register_link can over-ride the default behaviour and redirect to an arbitrary
// webpage for paid/custom or organisational registrations, regardless of whether
// registration is allowed.
// system.register_link may or may not be the same destination as system.sellpage
// system.sellpage is the destination linked from the /pubsites page on other sites. If
// system.sellpage is not set, the 'register' link in /pubsites will go to 'register' on your
// site.
// If system.register_link is set to the word 'none', no registration link will be shown on
// your site.
2019-05-24 05:51:39 +00:00
// If the site supports SSL and this isn't a secure connection, reload the page using https
if (intval($_SERVER['SERVER_PORT']) === 80 && strpos(z_root(), 'https://') !== false) {
goaway(z_root() . '/' . App::$query_string);
}
$register_policy = get_config('system','register_policy');
2020-08-31 04:08:39 +00:00
$reglink = get_config('system', 'register_link', z_root() . '/register');
if($reglink !== 'none') {
$reg = [
'title' => t('Create an account to access services and applications'),
'desc' => t('Register'),
'link' => $reglink
];
}
2010-07-01 23:48:07 +00:00
2016-03-31 23:06:03 +00:00
$dest_url = z_root() . '/' . App::$query_string;
2015-01-29 04:56:04 +00:00
if(local_channel()) {
2019-05-24 05:51:39 +00:00
$tpl = get_markup_template('logout.tpl');
2013-02-26 23:49:37 +00:00
}
else {
2019-05-24 05:51:39 +00:00
$tpl = get_markup_template('login.tpl');
2016-03-31 23:06:03 +00:00
if(strlen(App::$query_string))
$_SESSION['login_return_url'] = App::$query_string;
2013-02-26 23:49:37 +00:00
}
2011-05-01 00:24:37 +00:00
2019-05-24 05:51:39 +00:00
$o .= replace_macros($tpl, [
2013-02-26 23:49:37 +00:00
'$dest_url' => $dest_url,
'$login_page' => $login_page,
2013-02-26 23:49:37 +00:00
'$logout' => t('Logout'),
'$login' => t('Login'),
'$remote_login' => t('Remote Authentication'),
2013-02-26 23:49:37 +00:00
'$form_id' => $form_id,
2019-05-24 05:51:39 +00:00
'$lname' => [ 'username', t('Login/Email') , '', '' ],
'$lpassword' => [ 'password', t('Password'), '', '' ],
'$remember_me' => [ (($login_page) ? 'remember' : 'remember_me'), t('Remember me'), '', '', [ t('No'),t('Yes') ] ],
2013-02-26 23:49:37 +00:00
'$hiddens' => $hiddens,
'$register' => $reg,
'$lostpass' => t('Forgot your password?'),
'$lostlink' => t('Password Reset'),
2019-05-24 05:51:39 +00:00
]);
/**
* @hooks login_hook
* Called when generating the login form.
* * \e string with parsed HTML
*/
call_hooks('login_hook', $o);
2011-09-01 13:29:29 +00:00
2013-02-26 23:49:37 +00:00
return $o;
}
2010-07-01 23:48:07 +00:00
/**
* @brief Used to end the current process, after saving session state.
*/
2013-02-26 23:49:37 +00:00
function killme() {
register_shutdown_function('shutdown');
2013-02-26 23:49:37 +00:00
exit;
}
/**
* @brief Redirect to another URL and terminate this process.
*/
2013-02-26 23:49:37 +00:00
function goaway($s) {
header("Location: $s");
killme();
}
2016-05-10 02:13:27 +00:00
function shutdown() {
2016-05-25 03:49:23 +00:00
2016-05-10 02:13:27 +00:00
}
/**
* @brief Returns the entity id of locally logged in account or false.
*
2018-06-14 04:38:07 +00:00
* Returns numeric account_id if authenticated or false. It is possible to be
* authenticated and not connected to a channel.
*
* @return int|bool account_id or false
*/
2018-06-14 04:38:07 +00:00
2012-08-27 06:05:00 +00:00
function get_account_id() {
2021-03-09 01:51:41 +00:00
if(isset($_SESSION['account_id']) && intval($_SESSION['account_id']))
return intval($_SESSION['account_id']);
2016-03-31 23:06:03 +00:00
if(App::$account)
return intval(App::$account['account_id']);
2012-08-27 06:05:00 +00:00
return false;
}
/**
* @brief Returns the entity id (channel_id) of locally logged in channel or false.
*
* Returns authenticated numeric channel_id if authenticated and connected to
* a channel or 0. Sometimes referred to as $uid in the code.
*
* Before 2.1 this function was called local_user().
*
* @since 2.1
* @return int|bool channel_id or false
*/
2018-06-14 04:38:07 +00:00
2015-01-29 04:56:04 +00:00
function local_channel() {
if(session_id()
&& array_key_exists('authenticated',$_SESSION) && $_SESSION['authenticated']
&& array_key_exists('uid',$_SESSION) && intval($_SESSION['uid']))
2013-02-26 23:49:37 +00:00
return intval($_SESSION['uid']);
2013-02-26 23:49:37 +00:00
return false;
}
/**
* @brief Returns a xchan_hash (visitor_id) of remote authenticated visitor
* or false.
*
* Returns authenticated string hash of Red global identifier (xchan_hash), if
* authenticated via remote auth, or an empty string.
*
* Before 2.1 this function was called remote_user().
*
* @since 2.1
* @return string|bool visitor_id or false
*/
2015-01-29 04:58:59 +00:00
function remote_channel() {
if(session_id()
&& array_key_exists('authenticated',$_SESSION) && $_SESSION['authenticated']
&& array_key_exists('visitor_id',$_SESSION) && $_SESSION['visitor_id'])
2013-02-26 23:49:37 +00:00
return $_SESSION['visitor_id'];
2013-02-26 23:49:37 +00:00
return false;
}
function can_view_public_stream() {
2019-04-18 04:40:35 +00:00
if (observer_prohibited(true)) {
return false;
}
2018-07-13 07:34:48 +00:00
if (! (intval(get_config('system','open_pubstream',0)))) {
2019-04-18 04:40:35 +00:00
if (! local_channel()) {
return false;
}
}
$public_stream_mode = intval(get_config('system','public_stream_mode',PUBLIC_STREAM_NONE));
return (($public_stream_mode) ? true : false);
}
/**
* @brief Show an error or alert text on next page load.
*
* Contents of $s are displayed prominently on the page the next time
* a page is loaded. Usually used for errors or alerts.
*
* For informational text use info().
*
* @param string $s Text to display
*/
2013-02-26 23:49:37 +00:00
function notice($s) {
2021-08-29 01:51:12 +00:00
if (! session_id()) {
return;
2021-08-29 01:51:12 +00:00
}
2021-08-29 01:51:12 +00:00
if (! x($_SESSION, 'sysmsg')) {
$_SESSION['sysmsg'] = [];
}
// ignore duplicated error messages which haven't yet been displayed
// - typically seen as multiple 'permission denied' messages
// as a result of auto-reloading a protected page with &JS=1
2021-08-29 01:51:12 +00:00
if (in_array($s, $_SESSION['sysmsg'])) {
return;
2021-08-29 01:51:12 +00:00
}
2021-08-29 01:51:12 +00:00
if (App::$interactive) {
2013-02-26 23:49:37 +00:00
$_SESSION['sysmsg'][] = $s;
2014-04-10 03:11:52 +00:00
}
2013-02-26 23:49:37 +00:00
}
/**
* @brief Show an information text on next page load.
*
* Contents of $s are displayed prominently on the page the next time a page is
* loaded. Usually used for information.
*
* For error and alerts use notice().
*
* @param string $s Text to display
*/
2013-02-26 23:49:37 +00:00
function info($s) {
2021-08-29 01:51:12 +00:00
if (! session_id()) {
return;
2021-08-29 01:51:12 +00:00
}
if (! x($_SESSION, 'sysmsg_info')) {
2019-04-12 03:26:38 +00:00
$_SESSION['sysmsg_info'] = [];
2021-08-29 01:51:12 +00:00
}
2021-08-29 01:51:12 +00:00
if (in_array($s, $_SESSION['sysmsg_info'])) {
return;
2021-08-29 01:51:12 +00:00
}
2021-08-29 01:51:12 +00:00
if (App::$interactive) {
2013-02-26 23:49:37 +00:00
$_SESSION['sysmsg_info'][] = $s;
2021-08-29 01:51:12 +00:00
}
2013-02-26 23:49:37 +00:00
}
/**
* @brief Wrapper around config to limit the text length of an incoming message.
*
* @return int
*/
2013-02-26 23:49:37 +00:00
function get_max_import_size() {
return(intval(get_config('system', 'max_import_size')));
2013-02-26 23:49:37 +00:00
}
/**
* @brief Wrap calls to proc_close(proc_open()) and call hook
* so plugins can take part in process :)
*
* args:
* $cmd program to run
* next args are passed as $cmd command line
*
* e.g.:
* @code{.php}proc_run("ls", "-la", "/tmp");@endcode
*
* $cmd and string args are surrounded with ""
*/
2019-04-12 03:26:38 +00:00
function proc_run() {
2013-02-26 23:49:37 +00:00
$args = func_get_args();
2012-05-21 01:30:02 +00:00
2021-11-12 04:29:37 +00:00
if (! count($args))
2013-02-26 23:49:37 +00:00
return;
2012-05-21 01:30:02 +00:00
$args = flatten_array_recursive($args);
2014-04-10 03:11:52 +00:00
$arr = [
2019-04-12 03:26:38 +00:00
'args' => $args,
'run_cmd' => true
];
2019-04-12 03:26:38 +00:00
/**
* @hooks proc_run
* Called when invoking PHP sub processes.
* * \e array \b args
* * \e boolean \b run_cmd
*/
2019-04-12 03:26:38 +00:00
call_hooks('proc_run', $arr);
2021-11-12 04:29:37 +00:00
if (! $arr['run_cmd']) {
2013-02-26 23:49:37 +00:00
return;
2021-11-12 04:29:37 +00:00
}
2011-02-23 23:16:12 +00:00
2021-11-12 04:29:37 +00:00
if (count($args) > 1 && $args[0] === 'php') {
$php = check_php_cli();
if (! $php) {
return;
}
$args[0] = $php;
}
2016-05-20 04:32:19 +00:00
$args = array_map('escapeshellarg',$args);
2021-01-20 02:21:48 +00:00
$cmdline = implode(' ', $args);
2019-04-12 03:26:38 +00:00
if (is_windows()) {
$cwd = getcwd();
$cmd = "cmd /c start \"title\" /D \"$cwd\" /b $cmdline";
2019-04-12 03:26:38 +00:00
proc_close(proc_open($cmd, [], $foo));
}
2016-01-24 00:25:38 +00:00
else {
2019-04-12 03:26:38 +00:00
if (get_config('system','use_proc_open'))
proc_close(proc_open($cmdline ." &", [], $foo));
else
exec($cmdline . ' > /dev/null &');
2016-01-24 00:25:38 +00:00
}
2013-02-26 23:49:37 +00:00
}
2021-11-12 04:29:37 +00:00
function check_php_cli() {
$cfg = (isset(App::$config['system']['php_path']))
? App::$config['system']['php_path']
: NULL;
if (isset($cfg) && is_executable(realpath($cfg))) {
return realpath($cfg);
}
$path = shell_exec('which php');
if ($path && is_executable(realpath(trim($path)))) {
return realpath(trim($path));
}
logger('PHP command line interpreter not found.');
throw new Exception('interpreter not found.');
}
/**
* @brief Checks if we are running on M$ Windows.
*
* @return bool true if we run on M$ Windows
*
* It's possible you might be able to run on WAMP or XAMPP, and this
* has been accomplished, but is not officially supported. Good luck.
*
*/
2014-02-02 22:06:36 +00:00
function is_windows() {
return ((strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? true : false);
2014-02-02 22:06:36 +00:00
}
/**
* @brief Check if current user has admin role.
*
* Check if the current user has ACCOUNT_ROLE_ADMIN.
*
* @return bool true if user is an admin
*/
2012-08-30 06:03:03 +00:00
function is_site_admin() {
if(! session_id())
return false;
2021-02-23 02:36:54 +00:00
if(isset($_SESSION['delegate']))
2015-03-10 09:23:14 +00:00
return false;
2021-02-23 02:36:54 +00:00
if(isset($_SESSION['authenticated']) && intval($_SESSION['authenticated'])
&& is_array(App::$account)
2016-03-31 23:06:03 +00:00
&& (App::$account['account_roles'] & ACCOUNT_ROLE_ADMIN))
2012-08-30 06:03:03 +00:00
return true;
2012-08-30 06:03:03 +00:00
return false;
}
/**
* @brief Check if current user has developer role.
*
* Check if the current user has ACCOUNT_ROLE_DEVELOPER.
*
* @return bool true if user is a developer
*/
function is_developer() {
2016-05-25 03:49:23 +00:00
if(! session_id())
return false;
2021-02-23 02:36:54 +00:00
if(isset($_SESSION['authenticated'])
&& (intval($_SESSION['authenticated']))
2016-03-31 23:06:03 +00:00
&& (is_array(App::$account))
&& (App::$account['account_roles'] & ACCOUNT_ROLE_DEVELOPER))
return true;
return false;
}
2013-02-26 23:49:37 +00:00
function load_contact_links($uid) {
2011-07-31 23:35:53 +00:00
2019-04-12 03:26:38 +00:00
$ret = [];
2011-07-31 23:35:53 +00:00
2016-03-31 23:06:03 +00:00
if(! $uid || x(App::$contacts,'empty'))
2013-02-26 23:49:37 +00:00
return;
2011-07-31 23:35:53 +00:00
// logger('load_contact_links');
$r = q("SELECT abook_id, abook_flags, abook_self, abook_incl, abook_excl, abook_my_perms, abook_their_perms, xchan_hash, xchan_photo_m, xchan_name, xchan_url, xchan_addr, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d ",
intval($uid)
2013-02-26 23:49:37 +00:00
);
if($r) {
2018-06-14 04:38:07 +00:00
foreach($r as $rv) {
2016-08-15 05:44:25 +00:00
$ret[$rv['xchan_hash']] = $rv;
2011-07-31 23:35:53 +00:00
}
}
2013-02-26 23:49:37 +00:00
else
$ret['empty'] = true;
2016-03-31 23:06:03 +00:00
App::$contacts = $ret;
2013-02-26 23:49:37 +00:00
}
2012-06-14 14:04:13 +00:00
/**
* @brief Returns querystring as string from a mapped array.
2013-02-26 23:49:37 +00:00
*
* @param array $params mapped array with query parameters
* @param string $name of parameter, default null
*
2013-02-26 23:49:37 +00:00
* @return string
*/
function build_querystring($params, $name = null) {
$ret = '';
foreach($params as $key => $val) {
2014-04-10 03:11:52 +00:00
if(is_array($val)) {
if($name === null) {
2014-04-10 03:11:52 +00:00
$ret .= build_querystring($val, $key);
} else {
$ret .= build_querystring($val, $name . "[$key]");
2014-04-10 03:11:52 +00:00
}
} else {
$val = urlencode($val);
if($name != null) {
2014-04-10 03:11:52 +00:00
$ret .= $name . "[$key]" . "=$val&";
} else {
$ret .= "$key=$val&";
}
}
}
2014-04-10 03:11:52 +00:00
return $ret;
2012-06-14 14:04:13 +00:00
}
2012-07-22 12:13:29 +00:00
/**
* @brief Much better way of dealing with c-style args.
*/
2012-07-22 12:13:29 +00:00
function argc() {
2016-03-31 23:06:03 +00:00
return App::$argc;
2012-07-22 12:13:29 +00:00
}
function argv($x) {
2016-03-31 23:06:03 +00:00
if(array_key_exists($x,App::$argv))
return App::$argv[$x];
return '';
2012-07-22 12:13:29 +00:00
}
function dba_timer() {
return microtime(true);
}
/**
* @brief Returns xchan_hash from the observer.
*
* Observer can be a local or remote channel.
*
* @return string xchan_hash from observer, otherwise empty string if no observer
*/
function get_observer_hash() {
2016-03-31 23:06:03 +00:00
$observer = App::get_observer();
2020-05-06 04:34:31 +00:00
if (is_array($observer)) {
return $observer['xchan_hash'];
2020-05-06 04:34:31 +00:00
}
return '';
}
/**
* @brief Returns the complete URL of the current page, e.g.: http(s)://something.com/network
*
* Taken from http://webcheatsheet.com/php/get_current_page_url.php
*
* @return string
*/
function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {
$pageURL .= "s";
}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80" && $_SERVER["SERVER_PORT"] != "443") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $pageURL;
}
/**
* @brief Returns a custom navigation by name???
*
* If no $navname provided load default page['nav']
*
* @todo not fully implemented yet
*
* @param string $navname
*
* @return mixed
*/
function get_custom_nav($navname) {
if (! $navname)
2016-03-31 23:06:03 +00:00
return App::$page['nav'];
// load custom nav menu by name here
2021-12-02 22:33:36 +00:00
return EMPTY_STR;
}
/**
* @brief Loads a page definition file for a module.
*
* If there is no parsed Comanche template already load a module's pdl file
* and parse it with Comanche.
*
*/
function load_pdl() {
2016-05-06 06:07:35 +00:00
2019-04-12 03:26:38 +00:00
App::$comanche = new Comanche();
2016-05-06 06:07:35 +00:00
2016-03-31 23:06:03 +00:00
if (! count(App::$layout)) {
2015-08-22 21:28:33 +00:00
$arr = [
2018-08-06 06:19:33 +00:00
'module' => App::$module,
'layout' => ''
];
/**
* @hooks load_pdl
* Called when we load a PDL file or description.
* * \e string \b module
* * \e string \b layout
*/
call_hooks('load_pdl', $arr);
2016-01-15 04:51:59 +00:00
$layout = $arr['layout'];
2015-08-22 21:28:33 +00:00
2016-03-31 23:06:03 +00:00
$n = 'mod_' . App::$module . '.pdl' ;
2016-05-06 06:07:35 +00:00
$u = App::$comanche->get_channel_id();
if($u)
$s = get_pconfig($u, 'system', $n);
2021-03-09 01:51:41 +00:00
if(! (isset($s) && $s))
2016-01-15 04:51:59 +00:00
$s = $layout;
if((! $s) && (($p = theme_include($n)) != ''))
$s = @file_get_contents($p);
elseif(file_exists('addon/'. App::$module . '/' . $n))
$s = @file_get_contents('addon/'. App::$module . '/' . $n);
2018-08-06 06:19:33 +00:00
$arr = [
'module' => App::$module,
'layout' => $s
];
call_hooks('alter_pdl',$arr);
$s = $arr['layout'];
if($s) {
2016-05-06 06:07:35 +00:00
App::$comanche->parse($s);
2016-03-31 23:06:03 +00:00
App::$pdl = $s;
}
}
}
function exec_pdl() {
2016-03-31 23:06:03 +00:00
if(App::$pdl) {
2016-05-06 06:07:35 +00:00
App::$comanche->parse(App::$pdl,1);
}
}
/**
* @brief build the page.
*
* Build the page - now that we have all the components
*
*/
function construct_page() {
2021-07-22 10:16:58 +00:00
call_hooks('page_end', App::$page['content']);
exec_pdl();
2021-03-09 23:36:07 +00:00
$comanche = ((isset(App::$layout) && is_array(App::$layout) && count(App::$layout)) ? true : false);
require_once(theme_include('theme_init.php'));
$installing = false;
$uid = ((App::$profile_uid) ? App::$profile_uid : local_channel());
$navbar = get_config('system','navbar','default');
if($uid) {
$navbar = get_pconfig($uid,'system','navbar',$navbar);
2017-10-08 23:48:24 +00:00
}
2021-03-09 23:36:07 +00:00
if($comanche && isset(App::$layout['navbar'])) {
2017-10-08 23:48:24 +00:00
$navbar = App::$layout['navbar'];
}
2016-03-31 23:06:03 +00:00
if (App::$module == 'setup') {
$installing = true;
2021-03-09 23:36:07 +00:00
}
else {
2017-10-08 23:48:24 +00:00
nav($navbar);
2014-04-10 03:11:52 +00:00
}
2019-04-12 03:26:38 +00:00
$current_theme = Theme::current();
// logger('current_theme: ' . print_r($current_theme,true));
2019-04-12 03:26:38 +00:00
// Theme::debug();
if (($p = theme_include($current_theme[0] . '.js')) != '')
head_add_js('/' . $p);
2016-03-31 23:06:03 +00:00
if (($p = theme_include('mod_' . App::$module . '.php')) != '')
require_once($p);
require_once('include/js_strings.php');
2021-03-09 23:36:07 +00:00
if (isset(App::$page['template_style']))
2016-03-31 23:06:03 +00:00
head_add_css(App::$page['template_style'] . '.css');
else
2021-03-09 23:36:07 +00:00
head_add_css(((isset(App::$page['template'])) ? App::$page['template'] : 'default' ) . '.css');
if (($p = theme_include('mod_' . App::$module . '.css')) != '')
head_add_css('mod_' . App::$module . '.css');
2019-04-12 03:26:38 +00:00
head_add_css(Theme::url($installing));
if (($p = theme_include('mod_' . App::$module . '.js')) != '')
head_add_js('mod_' . App::$module . '.js');
2016-03-31 23:06:03 +00:00
App::build_pagehead();
2021-03-09 23:36:07 +00:00
if (isset(App::$page['pdl_content']) && App::$page['pdl_content']) {
2016-05-06 06:07:35 +00:00
App::$page['content'] = App::$comanche->region(App::$page['content']);
2015-11-13 01:47:38 +00:00
}
// Let's say we have a comanche declaration '[region=nav][/region][region=content]$nav $content[/region]'.
2014-04-10 03:11:52 +00:00
// The text 'region=' identifies a section of the layout by that name. So what we want to do here is leave
2016-03-31 23:06:03 +00:00
// App::$page['nav'] empty and put the default content from App::$page['nav'] and App::$page['section']
// into a new region called App::$data['content']. It is presumed that the chosen layout file for this comanche page
2014-04-10 03:11:52 +00:00
// has a '<content>' element instead of a '<section>'.
// This way the Comanche layout can include any existing content, alter the layout by adding stuff around it or changing the
// layout completely with a new layout definition, or replace/remove existing content.
2021-03-09 23:36:07 +00:00
if ($comanche) {
$arr = [
'module' => App::$module,
'layout' => App::$layout
];
/**
* @hooks construct_page
* General purpose hook to provide content to certain page regions.
* Called when constructing the Comanche page.
* * \e string \b module
* * \e string \b layout
*/
call_hooks('construct_page', $arr);
2021-03-09 23:36:07 +00:00
App::$layout = ((isset($arr['layout']) && is_array($arr['layout'])) ? $arr['layout'] : []);
2013-12-13 09:13:35 +00:00
2016-03-31 23:06:03 +00:00
foreach(App::$layout as $k => $v) {
if((strpos($k, 'region_') === 0) && strlen($v)) {
if(strpos($v, '$region_') !== false) {
2016-05-06 06:07:35 +00:00
$v = preg_replace_callback('/\$region_([a-zA-Z0-9]+)/ism', array(App::$comanche,'replace_region'), $v);
}
// And a couple of convenience macros
if(strpos($v, '$htmlhead') !== false) {
2016-03-31 23:06:03 +00:00
$v = str_replace('$htmlhead', App::$page['htmlhead'], $v);
}
if(strpos($v, '$nav') !== false) {
2016-03-31 23:06:03 +00:00
$v = str_replace('$nav', App::$page['nav'], $v);
}
if(strpos($v, '$content') !== false) {
2016-03-31 23:06:03 +00:00
$v = str_replace('$content', App::$page['content'], $v);
}
2016-03-31 23:06:03 +00:00
App::$page[substr($k, 7)] = $v;
}
}
2014-04-10 03:11:52 +00:00
}
2016-03-31 23:06:03 +00:00
$page = App::$page;
$profile = App::$profile;
// There's some experimental support for right-to-left text in the view/php/default.php page template.
// In v1.9 we started providing direction preference in the per language hstrings.php file
// This requires somebody with fluency in a RTL language to make happen
$page['direction'] = 0; // ((App::$rtl) ? 1 : 0);
header("Content-type: text/html; charset=utf-8");
// security headers - see https://securityheaders.io
2021-03-09 23:36:07 +00:00
if (App::get_scheme() === 'https' && isset(App::$config['system']['transport_security_header']) && App::$config['system']['transport_security_header']) {
header("Strict-Transport-Security: max-age=31536000");
2021-03-09 23:36:07 +00:00
}
2021-03-09 23:36:07 +00:00
if (isset(App::$config['system']['content_security_policy']) && App::$config['system']['content_security_policy']) {
2018-07-13 07:34:48 +00:00
$cspsettings = Array (
'script-src' => Array ("'self'","'unsafe-inline'","'unsafe-eval'"),
'style-src' => Array ("'self'","'unsafe-inline'")
);
call_hooks('content_security_policy',$cspsettings);
// Legitimate CSP directives (cxref: https://content-security-policy.com/)
$validcspdirectives=Array(
"default-src", "script-src", "style-src",
"img-src", "connect-src", "font-src",
"object-src", "media-src", 'frame-src',
'sandbox', 'report-uri', 'child-src',
'form-action', 'frame-ancestors', 'plugin-types'
);
$cspheader = "Content-Security-Policy:";
foreach ($cspsettings as $cspdirective => $csp) {
2021-03-09 23:36:07 +00:00
if (! in_array($cspdirective,$validcspdirectives)) {
logger("INVALID CSP DIRECTIVE: ".$cspdirective,LOGGER_DEBUG);
2018-07-13 07:34:48 +00:00
continue;
}
2021-03-09 23:36:07 +00:00
$cspsettingsarray = array_unique($cspsettings[$cspdirective]);
2018-07-13 07:34:48 +00:00
$cspsetpolicy = implode(' ',$cspsettingsarray);
if ($cspsetpolicy) {
2021-03-09 23:36:07 +00:00
$cspheader .= " $cspdirective $cspsetpolicy;";
2018-07-13 07:34:48 +00:00
}
}
header($cspheader);
}
2021-03-09 23:36:07 +00:00
if (isset(App::$config['system']['x_security_headers']) && App::$config['system']['x-security_headers']) {
header("X-Frame-Options: SAMEORIGIN");
header("X-Xss-Protection: 1; mode=block;");
header("X-Content-Type-Options: nosniff");
}
if (isset(App::$config['system']['perm_policy_header']) && App::$config['system']['perm_policy_header']) {
header("Permissions-Policy: " . App::$config['system']['perm_policy_header']);
}
else {
// opt-out this site from federated browser surveillance
header("Permissions-Policy: interest-cohort=()");
}
2021-04-15 20:43:46 +00:00
2021-03-09 23:36:07 +00:00
if (isset(App::$config['system']['public_key_pins']) && App::$config['system']['public_key_pins']) {
2016-03-31 23:06:03 +00:00
header("Public-Key-Pins: " . App::$config['system']['public_key_pins']);
}
require_once(theme_include(
2021-03-09 23:36:07 +00:00
((isset(App::$page['template']) && App::$page['template']) ? App::$page['template'] : 'default' ) . '.php' )
2014-04-10 03:11:52 +00:00
);
2013-01-06 21:42:51 +00:00
}
/**
2017-03-14 07:22:57 +00:00
* @brief Returns appplication root directory.
*
* @return string
*/
function appdirpath() {
return dirname(__FILE__);
}
/**
* @brief Set a pageicon.
*
* @param string $icon
*/
function head_set_icon($icon) {
2016-03-31 23:06:03 +00:00
App::$data['pageicon'] = $icon;
2017-03-14 07:22:57 +00:00
}
/**
* @brief Get the pageicon.
*
* @return string absolut path to pageicon
*/
function head_get_icon() {
$icon = ((isset(App::$data['pageicon'])) ? App::$data['pageicon'] : EMPTY_STR);
if($icon && ! strpos($icon, '://'))
$icon = z_root() . $icon;
return $icon;
}
/**
* @brief Return the Realm of the directory.
*
* @return string
*/
function get_directory_realm() {
if($x = get_config('system', 'directory_realm'))
return $x;
return DIRECTORY_REALM;
2014-09-13 17:45:26 +00:00
}
/**
* @brief Return relative date of last completed poller execution.
*
* @return string relative date of last completed poller execution
*/
function get_poller_runtime() {
$t = get_config('system', 'lastpoll');
return relative_date($t);
2014-12-26 08:13:22 +00:00
}
function z_get_upload_dir() {
$upload_dir = get_config('system','uploaddir');
if(! $upload_dir)
$upload_dir = ini_get('upload_tmp_dir');
if(! $upload_dir)
$upload_dir = sys_get_temp_dir();
return $upload_dir;
}
function z_get_temp_dir() {
$temp_dir = get_config('system','tempdir');
if(! $temp_dir)
$temp_dir = sys_get_temp_dir();
2021-12-02 22:33:36 +00:00
return $temp_dir;
2015-01-03 07:07:37 +00:00
}
2016-05-25 03:49:23 +00:00
/**
* @brief Check if server certificate is valid.
*
* Notify admin if not.
*/
function z_check_cert() {
if(strpos(z_root(), 'https://') !== false) {
2017-03-14 07:22:57 +00:00
$x = z_fetch_url(z_root() . '/siteinfo.json');
if(! $x['success']) {
$recurse = 0;
$y = z_fetch_url(z_root() . '/siteinfo.json', false, $recurse, ['novalidate' => true]);
if($y['success'])
cert_bad_email();
}
}
}
/**
* @brief Send email to admin if server has an invalid certificate.
*
2017-03-14 07:22:57 +00:00
* If a hub is available over https it must have a publicly valid certificate.
*/
function cert_bad_email() {
return z_mail(
[
2019-04-12 03:26:38 +00:00
'toEmail' => App::$config['system']['admin_email'],
'messageSubject' => sprintf(t('[$Projectname] Website SSL error for %s'), App::get_hostname()),
'textVersion' => replace_macros(get_intltext_template('cert_bad_eml.tpl'),
[
'$sitename' => App::$config['system']['sitename'],
'$siteurl' => z_root(),
'$error' => t('Website SSL certificate is not valid. Please correct.')
]
)
]
);
}
/**
* @brief Send warnings every 3-5 days if cron is not running.
*/
function check_cron_broken() {
$d = get_config('system','lastcron');
if((! $d) || ($d < datetime_convert('UTC','UTC','now - 4 hours'))) {
2021-04-13 03:49:58 +00:00
Run::Summon( [ 'Cron' ] );
2016-07-20 03:49:54 +00:00
set_config('system','lastcron',datetime_convert());
}
$t = get_config('system','lastcroncheck');
if(! $t) {
// never checked before. Start the timer.
set_config('system','lastcroncheck',datetime_convert());
2021-12-02 22:33:36 +00:00
return true;
}
if($t > datetime_convert('UTC','UTC','now - 3 days')) {
// Wait for 3 days before we do anything so as not to swamp the admin with messages
2021-12-02 22:33:36 +00:00
return true;
}
2016-07-19 05:33:26 +00:00
set_config('system','lastcroncheck',datetime_convert());
if(($d) && ($d > datetime_convert('UTC','UTC','now - 3 days'))) {
// Scheduled tasks have run successfully in the last 3 days.
2021-12-02 22:33:36 +00:00
return true;
}
return z_mail(
[
2019-04-12 03:26:38 +00:00
'toEmail' => App::$config['system']['admin_email'],
'messageSubject' => sprintf(t('[$Projectname] Cron tasks not running on %s'), App::get_hostname()),
'textVersion' => replace_macros(get_intltext_template('cron_bad_eml.tpl'),
[
'$sitename' => App::$config['system']['sitename'],
'$siteurl' => z_root(),
'$error' => t('Cron/Scheduled tasks not running.'),
'$lastdate' => (($d)? $d : t('never'))
]
)
]
);
2015-03-03 10:32:54 +00:00
}
2016-01-18 00:29:32 +00:00
/**
* @brief
*
2021-12-02 23:02:31 +00:00
* @param bool $allow_account (optional) default false
* @return bool
*/
function observer_prohibited($allow_account = false) {
2018-05-07 01:10:43 +00:00
if($allow_account) {
return (((get_config('system', 'block_public')) && (! get_account_id()) && (! remote_channel())) ? true : false );
2018-05-07 01:10:43 +00:00
}
return (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false );
}
2019-10-03 20:22:59 +00:00
function get_safemode() {
if (! array_key_exists('safemode', $_SESSION)) {
$_SESSION['safemode'] = 1;
}
return intval($_SESSION['safemode']);
2019-10-11 01:34:44 +00:00
}
2020-05-06 04:34:31 +00:00
function supported_imagetype($x) {
return in_array($x, [ IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_WEBP ]);
2021-01-25 21:56:45 +00:00
}
function get_host() {
2021-03-09 23:36:07 +00:00
if ($host = ((isset($_SERVER['HTTP_X_FORWARDED_HOST']) && $_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : EMPTY_STR)) {
2021-01-25 21:56:45 +00:00
$elements = explode(',', $host);
$host = trim(end($elements));
}
else {
2021-03-09 23:36:07 +00:00
if (! $host = ((isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : EMPTY_STR)) {
if (! $host = ((isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : EMPTY_STR)) {
$host = ((isset($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '');
2021-01-25 21:56:45 +00:00
}
}
}
// Remove port number from host
if (strpos($host,':') !== false) {
$host = substr($host,0,strpos($host,':'));
}
2021-01-25 21:56:45 +00:00
return trim($host);
}
2021-05-27 11:04:16 +00:00
function get_loadtime($module) {
$n = 'loadtime_' . $module;
if (isset($_SESSION[$n])) {
return $_SESSION[$n];
}
if (local_channel()) {
$x = PConfig::Get(local_channel(),'system',$n, false);
if ($x) {
return ($x);
}
}
return datetime_convert();
}