Merge https://github.com/friendica/red into pending_merge
This commit is contained in:
		
							
								
								
									
										79
									
								
								boot.php
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								boot.php
									
									
									
									
									
								
							| @@ -52,13 +52,11 @@ define ( 'ZOT_REVISION',            1     ); | ||||
| define ( 'DB_UPDATE_VERSION',       1140  ); | ||||
|  | ||||
| /** | ||||
|  * Constant with a HTML line break. | ||||
|  * @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. | ||||
|  * This can be used in HTML and JavaScript where needed a line break. | ||||
|  * | ||||
|  * @var string | ||||
|  */ | ||||
| define ( 'EOL',                    '<br>' . "\r\n"        ); | ||||
| define ( 'ATOM_TIME',              'Y-m-d\TH:i:s\Z'       ); | ||||
| @@ -707,8 +705,6 @@ class App { | ||||
| 	 * | ||||
| 	 * Mostly unimplemented yet. Only options 'template_engine' and | ||||
| 	 * beyond are used. | ||||
| 	 * | ||||
| 	 * @var array | ||||
| 	 */ | ||||
| 	private $theme = array( | ||||
| 		'sourcename' => '', | ||||
| @@ -721,15 +717,11 @@ class App { | ||||
| 	); | ||||
|  | ||||
| 	/** | ||||
| 	 * array of registered template engines ('name'=>'class name') | ||||
| 	 * | ||||
| 	 * @var array | ||||
| 	 * @brief An array of registered template engines ('name'=>'class name') | ||||
| 	 */ | ||||
| 	public $template_engines = array(); | ||||
| 	/** | ||||
| 	 * array of instanced template engines ('name'=>'instance') | ||||
| 	 * | ||||
| 	 * @var array | ||||
| 	 * @brief An array of instanced template engines ('name'=>'instance') | ||||
| 	 */ | ||||
| 	public $template_engine_instance = array(); | ||||
|  | ||||
| @@ -806,9 +798,7 @@ class App { | ||||
| 		if(substr($this->cmd, 0, 1) === '~') | ||||
| 			$this->cmd = 'channel/' . substr($this->cmd, 1); | ||||
|  | ||||
|  | ||||
| 		/** | ||||
| 		 * | ||||
| 		/* | ||||
| 		 * Break the URL path into C style argc/argv style arguments for our | ||||
| 		 * modules. Given "http://example.com/module/arg1/arg2", $this->argc | ||||
| 		 * will be 3 (integer) and $this->argv will contain: | ||||
| @@ -816,25 +806,22 @@ class App { | ||||
| 		 *   [1] => 'arg1' | ||||
| 		 *   [2] => 'arg2' | ||||
| 		 * | ||||
| 		 * | ||||
| 		 * There will always be one argument. If provided a naked domain | ||||
| 		 * URL, $this->argv[0] is set to "home". | ||||
| 		 * | ||||
| 		 */ | ||||
|  | ||||
| 		$this->argv = explode('/',$this->cmd); | ||||
| 		$this->argv = explode('/', $this->cmd); | ||||
| 		$this->argc = count($this->argv); | ||||
| 		if((array_key_exists('0',$this->argv)) && strlen($this->argv[0])) { | ||||
| 		if ((array_key_exists('0', $this->argv)) && strlen($this->argv[0])) { | ||||
| 			$this->module = str_replace(".", "_", $this->argv[0]); | ||||
| 			$this->module = str_replace("-", "_", $this->module); | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			$this->argc = 1; | ||||
| 			$this->argv = array('home'); | ||||
| 			$this->module = 'home'; | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * See if there is any page number information, and initialise | ||||
| 		 * pagination | ||||
| 		 */ | ||||
| @@ -846,7 +833,7 @@ class App { | ||||
| 			$this->pager['start'] = 0; | ||||
| 		$this->pager['total'] = 0; | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * Detect mobile devices | ||||
| 		 */ | ||||
|  | ||||
| @@ -858,7 +845,7 @@ class App { | ||||
|  | ||||
| 		BaseObject::set_app($this); | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * register template engines | ||||
| 		 */ | ||||
| 		$dc = get_declared_classes(); | ||||
| @@ -2029,7 +2016,7 @@ function curPageURL() { | ||||
|  * @return mixed | ||||
|  */ | ||||
| function get_custom_nav(&$a, $navname) { | ||||
| 	if(! $navname) | ||||
| 	if (! $navname) | ||||
| 		return $a->page['nav']; | ||||
| 	// load custom nav menu by name here | ||||
| } | ||||
| @@ -2045,7 +2032,7 @@ function get_custom_nav(&$a, $navname) { | ||||
| function load_pdl(&$a) { | ||||
| 	require_once('include/comanche.php'); | ||||
|  | ||||
| 	if(! count($a->layout)) { | ||||
| 	if (! count($a->layout)) { | ||||
| 		$n = 'mod_' . $a->module . '.pdl' ; | ||||
| 		$u = comanche_get_channel_id(); | ||||
| 		if($u) | ||||
| @@ -2071,7 +2058,6 @@ function exec_pdl(&$a) { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief build the page. | ||||
|  * | ||||
| @@ -2081,7 +2067,6 @@ function exec_pdl(&$a) { | ||||
|  */ | ||||
| function construct_page(&$a) { | ||||
|  | ||||
|  | ||||
| 	exec_pdl($a); | ||||
|  | ||||
| 	$comanche = ((count($a->layout)) ? true : false); | ||||
| @@ -2090,28 +2075,27 @@ function construct_page(&$a) { | ||||
|  | ||||
| 	$installing = false; | ||||
|  | ||||
| 	if($a->module == 'setup') { | ||||
| 	if ($a->module == 'setup') { | ||||
| 		$installing = true; | ||||
| 	} else { | ||||
| 		nav($a); | ||||
| 	} | ||||
|  | ||||
| 	if($comanche) { | ||||
|  | ||||
| 		if($a->layout['nav']) { | ||||
| 	if ($comanche) { | ||||
| 		if ($a->layout['nav']) { | ||||
| 			$a->page['nav'] = get_custom_nav($a, $a->layout['nav']); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(($p = theme_include(current_theme() . '.js')) != '') | ||||
| 	if (($p = theme_include(current_theme() . '.js')) != '') | ||||
| 		head_add_js($p); | ||||
|  | ||||
| 	if(($p = theme_include('mod_' . $a->module . '.php')) != '') | ||||
| 	if (($p = theme_include('mod_' . $a->module . '.php')) != '') | ||||
| 		require_once($p); | ||||
|  | ||||
| 	require_once('include/js_strings.php'); | ||||
|  | ||||
| 	if(x($a->page, 'template_style')) | ||||
| 	if (x($a->page, 'template_style')) | ||||
| 		head_add_css($a->page['template_style'] . '.css'); | ||||
| 	else | ||||
| 		head_add_css(((x($a->page, 'template')) ? $a->page['template'] : 'default' ) . '.css'); | ||||
| @@ -2148,7 +2132,6 @@ function construct_page(&$a) { | ||||
| 		call_hooks('construct_page', $arr); | ||||
| 		$a->layout = $arr['layout']; | ||||
|  | ||||
|  | ||||
| 		foreach($a->layout as $k => $v) { | ||||
| 			if((strpos($k, 'region_') === 0) && strlen($v)) { | ||||
| 				if(strpos($v, '$region_') !== false) { | ||||
| @@ -2250,11 +2233,11 @@ function get_directory_realm() { | ||||
|  */ | ||||
| function get_directory_primary() { | ||||
|  | ||||
|    $dirmode = intval(get_config('system','directory_mode')); | ||||
| 	$dirmode = intval(get_config('system','directory_mode')); | ||||
|  | ||||
|     if($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_PRIMARY) { | ||||
| 	if($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_PRIMARY) { | ||||
| 		return z_root(); | ||||
|     } | ||||
| 	} | ||||
|  | ||||
| 	if($x = get_config('system', 'directory_primary')) | ||||
| 		return $x; | ||||
| @@ -2263,13 +2246,11 @@ function get_directory_primary() { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief return relative date of last completed poller execution | ||||
|  * @brief return relative date of last completed poller execution. | ||||
|  */ | ||||
|  | ||||
| function get_poller_runtime() { | ||||
| 	$t = get_config('system','lastpoll'); | ||||
| 	$t = get_config('system', 'lastpoll'); | ||||
| 	return relative_date($t); | ||||
| } | ||||
|  | ||||
| @@ -2303,7 +2284,12 @@ function z_check_cert() { | ||||
| }  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Send email to admin if server has an invalid certificate. | ||||
|  * | ||||
|  * If a RedMatrix hub is available over https it must have a publicly valid | ||||
|  * certificate. | ||||
|  */ | ||||
| function cert_bad_email() { | ||||
|  | ||||
| 	$a = get_app(); | ||||
| @@ -2320,13 +2306,12 @@ function cert_bad_email() { | ||||
| 		'From: Administrator' . '@' . $a->get_hostname() . "\n" | ||||
| 		. 'Content-type: text/plain; charset=UTF-8' . "\n" | ||||
| 		. 'Content-transfer-encoding: 8bit' ); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| // send warnings every 3-5 days if cron is not running. | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Send warnings every 3-5 days if cron is not running. | ||||
|  */ | ||||
| function check_cron_broken() { | ||||
|  | ||||
| 	$t = get_config('system','lastpollcheck'); | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| <?php | ||||
| require_once 'boot.php'; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Interface for template engines | ||||
|  * @brief Interface for template engines. | ||||
|  */ | ||||
| interface ITemplateEngine { | ||||
| 	public function replace_macros($s,$v); | ||||
| 	public function replace_macros($s, $v); | ||||
| 	public function get_markup_template($file, $root=''); | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,8 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/account.php | ||||
|  * @brief Somme account related functions. | ||||
|  */ | ||||
|  | ||||
| require_once('include/config.php'); | ||||
| require_once('include/network.php'); | ||||
| @@ -51,7 +55,6 @@ function check_account_password($password) { | ||||
| 	call_hooks('check_account_password', $arr); | ||||
|  | ||||
| 	return $arr['result']; | ||||
|  | ||||
| } | ||||
|  | ||||
| function check_account_invite($invite_code) { | ||||
| @@ -75,7 +78,6 @@ function check_account_invite($invite_code) { | ||||
| 	call_hooks('check_account_invite', $arr); | ||||
|  | ||||
| 	return $arr['result']; | ||||
|  | ||||
| } | ||||
|  | ||||
| function check_account_admin($arr) { | ||||
| @@ -132,16 +134,16 @@ function create_account($arr) { | ||||
| 	// allow the admin_email account to be admin, but only if it's the first account. | ||||
|  | ||||
| 	$c = account_total(); | ||||
| 	if(($c === 0) && (check_account_admin($arr))) | ||||
| 	if (($c === 0) && (check_account_admin($arr))) | ||||
| 		$roles |= ACCOUNT_ROLE_ADMIN; | ||||
|  | ||||
|     // Ensure that there is a host keypair. | ||||
| 	// Ensure that there is a host keypair. | ||||
|  | ||||
|     if((! get_config('system','pubkey')) && (! get_config('system','prvkey'))) { | ||||
|         $hostkey = new_keypair(4096); | ||||
|         set_config('system','pubkey',$hostkey['pubkey']); | ||||
|         set_config('system','prvkey',$hostkey['prvkey']); | ||||
|     } | ||||
| 	if ((! get_config('system', 'pubkey')) && (! get_config('system', 'prvkey'))) { | ||||
| 		$hostkey = new_keypair(4096); | ||||
| 		set_config('system', 'pubkey', $hostkey['pubkey']); | ||||
| 		set_config('system', 'prvkey', $hostkey['prvkey']); | ||||
| 	} | ||||
|  | ||||
| 	$invite_result = check_account_invite($invite_code); | ||||
| 	if($invite_result['error']) { | ||||
| @@ -180,7 +182,6 @@ function create_account($arr) { | ||||
| 		dbesc($roles), | ||||
| 		dbesc($expires), | ||||
| 		dbesc($default_service_class) | ||||
|  | ||||
| 	); | ||||
| 	if(! $r) { | ||||
| 		logger('create_account: DB INSERT failed.'); | ||||
| @@ -215,8 +216,8 @@ function create_account($arr) { | ||||
| 	$result['success']  = true; | ||||
| 	$result['email']    = $email; | ||||
| 	$result['password'] = $password; | ||||
| 	return $result; | ||||
|  | ||||
| 	return $result; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -255,7 +256,6 @@ function verify_email_address($arr) { | ||||
| 		logger('send_reg_approval_email: failed to ' . $admin['email'] . 'account_id: ' . $arr['account']['account_id']); | ||||
|  | ||||
| 	return $res; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -292,7 +292,6 @@ function send_reg_approval_email($arr) { | ||||
|  | ||||
| 	$details = (($ip) ? $ip . ' [' . gethostbyaddr($ip) . ']' : '[unknown or stealth IP]'); | ||||
|  | ||||
|  | ||||
| 	$delivered = 0; | ||||
|  | ||||
| 	foreach($admins as $admin) { | ||||
| @@ -346,11 +345,14 @@ function send_verification_email($email,$password) { | ||||
| 	return($res ? true : false); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Allows a user registration. | ||||
|  * | ||||
|  * @param string $hash | ||||
|  * @return array|boolean | ||||
|  */ | ||||
| function user_allow($hash) { | ||||
|  | ||||
| 	$a = get_app(); | ||||
|  | ||||
| 	$ret = array('success' => false); | ||||
|  | ||||
| 	$register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", | ||||
| @@ -402,18 +404,23 @@ function user_allow($hash) { | ||||
|  | ||||
| 	pop_lang(); | ||||
|  | ||||
| 	if($res) { | ||||
| 	if ($res) { | ||||
| 		info( t('Account approved.') . EOL ); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| // This does not have to go through user_remove() and save the nickname | ||||
| // permanently against re-registration, as the person was not yet | ||||
| // allowed to have friends on this system | ||||
|  | ||||
| /** | ||||
|  * @brief Denies a user registration. | ||||
|  * | ||||
|  * This does not have to go through user_remove() and save the nickname | ||||
|  * permanently against re-registration, as the person was not yet | ||||
|  * allowed to have friends on this system | ||||
|  * | ||||
|  * @param string $hash | ||||
|  * @return boolean | ||||
|  */ | ||||
| function user_deny($hash) { | ||||
|  | ||||
| 	$register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1", | ||||
| @@ -438,6 +445,7 @@ function user_deny($hash) { | ||||
| 		dbesc($register[0]['id']) | ||||
| 	); | ||||
| 	notice( sprintf(t('Registration revoked for %s'), $account[0]['account_email']) . EOL); | ||||
|  | ||||
| 	return true; | ||||
|  | ||||
| } | ||||
| @@ -445,8 +453,6 @@ function user_deny($hash) { | ||||
|  | ||||
| function user_approve($hash) { | ||||
|  | ||||
| 	$a = get_app(); | ||||
|  | ||||
| 	$ret = array('success' => false); | ||||
|  | ||||
| 	$register = q("SELECT * FROM `register` WHERE `hash` = '%s' and password = 'verify' LIMIT 1", | ||||
| @@ -486,17 +492,12 @@ function user_approve($hash) { | ||||
| 	info( t('Account verified. Please login.') . EOL ); | ||||
|  | ||||
| 	return true; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function downgrade_accounts() | ||||
|  *    Checks for accounts that have past their expiration date. | ||||
|  * @brief Checks for accounts that have past their expiration date. | ||||
|  * | ||||
|  * If the account has a service class which is not the site default,  | ||||
|  * the service class is reset to the site default and expiration reset to never. | ||||
|  * If the account has no service class it is expired and subsequently disabled. | ||||
| @@ -506,8 +507,6 @@ function user_approve($hash) { | ||||
|  * not the job of this function, but this can be implemented by plugin if desired.  | ||||
|  * Default behaviour is to stop allowing additional resources to be consumed.  | ||||
|  */ | ||||
|   | ||||
|  | ||||
| function downgrade_accounts() { | ||||
|  | ||||
| 	$r = q("select * from account where not ( account_flags & %d )>0  | ||||
| @@ -604,7 +603,7 @@ function service_class_allows($uid, $property, $usage = false) { | ||||
|  * | ||||
|  * @param int $aid The account_id to check | ||||
|  * @param string $property The service class property to check for | ||||
|  * @param int|boolean $usage, (optional) The value to check against | ||||
|  * @param int|boolean $usage (optional) The value to check against | ||||
|  * @return boolean | ||||
|  */ | ||||
| function account_service_class_allows($aid, $property, $usage = false) { | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| /** @file | ||||
| /** | ||||
|  * @file include/attach.php | ||||
|  * | ||||
|  * @brief File/attach API with the potential for revision control. | ||||
|  * | ||||
|  * TODO: a filesystem storage abstraction which maintains security (and 'data' contains a system filename | ||||
|  * @TODO: a filesystem storage abstraction which maintains security (and 'data' contains a system filename | ||||
|  * which is inaccessible from the web). This could get around PHP storage limits and store videos and larger | ||||
|  * items, using fread or OS methods or native code to read/write or chunk it through. | ||||
|  * Also an 'append' option to the storage function might be a useful addition.  | ||||
| @@ -118,22 +118,21 @@ function z_mime_content_type($filename) { | ||||
| /** | ||||
|  * @brief Count files/attachments. | ||||
|  * | ||||
|  *  | ||||
|  * @param $channel_id | ||||
|  * @param $observer | ||||
|  * @param $hash (optional) | ||||
|  * @param $filename (optional) | ||||
|  * @param $filetype (optional) | ||||
|  * @return array | ||||
|  * 	$ret['success'] boolean | ||||
|  * 	$ret['results'] amount of found results, or false | ||||
|  * 	$ret['message'] string with error messages if any | ||||
|  * @param int $channel_id | ||||
|  * @param string $observer | ||||
|  * @param string $hash (optional) | ||||
|  * @param string $filename (optional) | ||||
|  * @param string $filetype (optional) | ||||
|  * @return assoziative array with: | ||||
|  *  * \e boolean \b success | ||||
|  *  * \e int|boolean \b results amount of found results, or false | ||||
|  *  * \e string \b message with error messages if any | ||||
|  */ | ||||
| function attach_count_files($channel_id, $observer, $hash = '', $filename = '', $filetype = '') { | ||||
|  | ||||
| 	$ret = array('success' => false); | ||||
|  | ||||
| 	if(! perm_is_allowed($channel_id,$observer, 'read_storage')) { | ||||
| 	if(! perm_is_allowed($channel_id, $observer, 'read_storage')) { | ||||
| 		$ret['message'] = t('Permission denied.'); | ||||
| 		return $ret; | ||||
| 	} | ||||
| @@ -219,8 +218,9 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $ | ||||
|  *  | ||||
|  * This could exhaust memory so most useful only when immediately sending the data. | ||||
|  *  | ||||
|  * @param $hash | ||||
|  * @param $rev | ||||
|  * @param string $hash | ||||
|  * @param int $rev Revision | ||||
|  * @return array | ||||
|  */ | ||||
| function attach_by_hash($hash, $rev = 0) { | ||||
|  | ||||
| @@ -234,7 +234,6 @@ function attach_by_hash($hash, $rev = 0) { | ||||
| 	elseif($rev) | ||||
| 		$sql_extra = " and revision = " . intval($rev) . " "; | ||||
|  | ||||
|  | ||||
| 	$r = q("SELECT uid FROM attach WHERE hash = '%s' $sql_extra LIMIT 1", | ||||
| 		dbesc($hash) | ||||
| 	); | ||||
| @@ -579,24 +578,22 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function attach_mkdir($channel,$observer_hash,$arr); | ||||
|  * | ||||
|  * @brief Create directory. | ||||
|  * | ||||
|  * @param array $channel channel array of owner | ||||
|  * @param string $observer_hash hash of current observer | ||||
|  * @param array $arr parameter array to fulfil request | ||||
|  * Required: | ||||
|  *    $arr['filename'] | ||||
|  *    $arr['folder'] // hash of parent directory, empty string for root directory | ||||
|  * Optional: | ||||
|  *    $arr['hash']  // precumputed hash for this node | ||||
|  *    $arr['allow_cid'] | ||||
|  *    $arr['allow_gid'] | ||||
|  *    $arr['deny_cid'] | ||||
|  *    $arr['deny_gid'] | ||||
|  * - Required: | ||||
|  *  * \e string \b filename | ||||
|  *  * \e string \b folder hash of parent directory, empty string for root directory | ||||
|  * - Optional: | ||||
|  *  * \e string \b hash precumputed hash for this node | ||||
|  *  * \e tring  \b allow_cid | ||||
|  *  * \e string \b allow_gid | ||||
|  *  * \e string \b deny_cid | ||||
|  *  * \e string \b deny_gid | ||||
|  * @return array | ||||
|  */ | ||||
|  | ||||
| function attach_mkdir($channel, $observer_hash, $arr = null) { | ||||
|  | ||||
| 	$ret = array('success' => false); | ||||
| @@ -720,13 +717,13 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { | ||||
| /** | ||||
|  * @brief Changes permissions of a file. | ||||
|  *  | ||||
|  * @param $channel_id | ||||
|  * @param $resource | ||||
|  * @param $allow_cid | ||||
|  * @param $allow_gid | ||||
|  * @param $deny_cid | ||||
|  * @param $deny_gid | ||||
|  * @param $recurse | ||||
|  * @param int $channel_id | ||||
|  * @param array $resource | ||||
|  * @param string $allow_cid | ||||
|  * @param string $allow_gid | ||||
|  * @param string $deny_cid | ||||
|  * @param string $deny_gid | ||||
|  * @param boolean $recurse (optional) default false | ||||
|  */ | ||||
| function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) { | ||||
|  | ||||
| @@ -836,7 +833,6 @@ function attach_delete($channel_id, $resource) { | ||||
| 	); | ||||
|  | ||||
| 	file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $no_activity=false); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -845,7 +841,7 @@ function attach_delete($channel_id, $resource) { | ||||
|  * @warning This function cannot be used with mod/dav as it always returns a | ||||
|  * path valid under mod/cloud. | ||||
|  * | ||||
|  * @param array assoziative array with: | ||||
|  * @param array $arr assoziative array with: | ||||
|  *  * \e int \b uid the channel's uid | ||||
|  *  * \e string \b folder | ||||
|  *  * \e string \b filename | ||||
| @@ -973,20 +969,21 @@ function pipe_streams($in, $out) { | ||||
| 	$size = 0; | ||||
| 	while (!feof($in)) | ||||
| 		$size += fwrite($out, fread($in, 8192)); | ||||
|  | ||||
| 	return $size; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Activity for files | ||||
|  * @brief Activity for files. | ||||
|  * | ||||
|  * @param $channel_id | ||||
|  * @param $object | ||||
|  * @param $allow_cid | ||||
|  * @param $allow_gid | ||||
|  * @param $deny_cid | ||||
|  * @param $deny_gid | ||||
|  * @param $verb | ||||
|  * @param $no_activity | ||||
|  * @param int $channel_id | ||||
|  * @param array $object | ||||
|  * @param string $allow_cid | ||||
|  * @param string $allow_gid | ||||
|  * @param string $deny_cid | ||||
|  * @param string $deny_gid | ||||
|  * @param string $verb | ||||
|  * @param boolean $no_activity | ||||
|  */ | ||||
| function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $no_activity) { | ||||
|  | ||||
| @@ -1028,7 +1025,6 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, | ||||
|  | ||||
| 		//filter out receivers which do not have permission to view filestorage | ||||
| 		$arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	$mid = item_message_id(); | ||||
| @@ -1109,7 +1105,6 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, | ||||
| 		$update = false; | ||||
|  | ||||
| 		//notice( t('File activity updated') . EOL); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	if($no_activity) { | ||||
| @@ -1152,15 +1147,14 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, | ||||
| 	//(($verb === 'post') ?  notice( t('File activity posted') . EOL) : notice( t('File activity dropped') . EOL)); | ||||
|  | ||||
| 	return; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Create file activity object | ||||
|  * | ||||
|  * @param $channel_id | ||||
|  * @param $hash | ||||
|  * @param $cloudpath | ||||
|  * @param int $channel_id | ||||
|  * @param string $hash | ||||
|  * @param string $cloudpath | ||||
|  */ | ||||
| function get_file_activity_object($channel_id, $hash, $cloudpath) { | ||||
|  | ||||
| @@ -1199,8 +1193,8 @@ function get_file_activity_object($channel_id, $hash, $cloudpath) { | ||||
| 		'deny_cid'	=> $x[0]['deny_cid'], | ||||
| 		'deny_gid'	=> $x[0]['deny_gid'] | ||||
| 	); | ||||
| 	return $object; | ||||
|  | ||||
| 	return $object; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -101,7 +101,7 @@ function comanche_parser(&$a, $s, $pass = 0) { | ||||
| } | ||||
|  | ||||
|  | ||||
| function comanche_menu($name,$class = '') { | ||||
| function comanche_menu($name, $class = '') { | ||||
| 	$channel_id = comanche_get_channel_id(); | ||||
| 	if($channel_id) { | ||||
| 		$m = menu_fetch($name,$channel_id, get_observer_hash()); | ||||
| @@ -111,20 +111,23 @@ function comanche_menu($name,$class = '') { | ||||
|  | ||||
| function comanche_replace_region($match) { | ||||
| 	$a = get_app(); | ||||
| 	if(array_key_exists($match[1], $a->page)) { | ||||
| 	if (array_key_exists($match[1], $a->page)) { | ||||
| 		return $a->page[$match[1]]; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function comanche_get_channel_id() | ||||
|  *    Returns the channel_id of the profile owner of the page, or the local_channel if there is no profile owner. | ||||
|  * Otherwise returns 0 | ||||
|  * @brief Returns the channel_id of the profile owner of the page. | ||||
|  * | ||||
|  * Returns the channel_id of the profile owner of the page, or the local_channel | ||||
|  * if there is no profile owner. Otherwise returns 0. | ||||
|  * | ||||
|  * @return channel_id | ||||
|  */ | ||||
|  | ||||
| function comanche_get_channel_id() { | ||||
| 	$channel_id = ((is_array(get_app()->profile)) ? get_app()->profile['profile_uid'] : 0); | ||||
| 	if((! $channel_id) && (local_channel())) | ||||
|  | ||||
| 	if ((! $channel_id) && (local_channel())) | ||||
| 		$channel_id = local_channel(); | ||||
|  | ||||
| 	return $channel_id; | ||||
| @@ -173,23 +176,26 @@ function comanche_webpage(&$a,$s) { | ||||
| } | ||||
|  | ||||
|  | ||||
| // Widgets will have to get any operational arguments from the session, | ||||
| // the global app environment, or config storage until we implement argument passing | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Widgets will have to get any operational arguments from the session, the | ||||
|  * global app environment, or config storage until we implement argument passing | ||||
|  * | ||||
|  * @param string $name | ||||
|  * @param string $text | ||||
|  */ | ||||
| function comanche_widget($name, $text) { | ||||
| 	$vars = array(); | ||||
| 	$matches = array(); | ||||
|  | ||||
| 	$cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $text, $matches, PREG_SET_ORDER); | ||||
| 	if($cnt) { | ||||
| 		foreach($matches as $mtch) { | ||||
| 	if ($cnt) { | ||||
| 		foreach ($matches as $mtch) { | ||||
| 			$vars[$mtch[1]] = $mtch[2]; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	$func = 'widget_' . trim($name); | ||||
| 	if(function_exists($func)) | ||||
| 	if (function_exists($func)) | ||||
| 		return $func($vars); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,8 +3,7 @@ | ||||
|  * @file include/config.php | ||||
|  * @brief Arbitrary configuration storage. | ||||
|  * | ||||
|  * Note: | ||||
|  * Please do not store booleans - convert to 0/1 integer values | ||||
|  * @note Please do not store booleans - convert to 0/1 integer values. | ||||
|  * The get_?config() functions return boolean false for keys that are unset, | ||||
|  * and this could lead to subtle bugs. | ||||
|  * | ||||
| @@ -18,19 +17,20 @@ | ||||
|  * - <b>pconfig</b> is used for channel specific configurations and takes a | ||||
|  * <i>channel_id</i> as identifier. It stores for example which features are | ||||
|  * enabled per channel. The storage is of size MEDIUMTEXT. | ||||
|  * @code $var = get_pconfig(local_channel(), 'category', 'key');@endcode | ||||
|  * @code{.php} $var = get_pconfig(local_channel(), 'category', 'key');@endcode | ||||
|  * - <b>xconfig</b> is the same as pconfig, except that it uses <i>xchan</i> as | ||||
|  * an identifier. This is for example for people who do not have a local account. | ||||
|  * The storage is of size MEDIUMTEXT. | ||||
|  * @code $observer = $a->get_observer_hash(); | ||||
|  * @code{.php} | ||||
|  * $observer = $a->get_observer_hash(); | ||||
|  * if ($observer) { | ||||
|  *     $var = get_xconfig($observer, 'category', 'key'); | ||||
|  * }@endcode | ||||
|  * | ||||
|  * - get_config() and set_config() can also be done through the command line tool | ||||
|  * @ref util/config | ||||
|  * @ref util/config.md "util/config" | ||||
|  * - get_pconfig() and set_pconfig() can also be done through the command line tool | ||||
|  * @ref util/pconfig and takes a channel_id as first argument.  | ||||
|  * @ref util/pconfig.md "util/pconfig" and takes a channel_id as first argument.  | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| @@ -123,7 +123,7 @@ function get_config_from_storage($family, $key) { | ||||
|  * | ||||
|  * Stores a config value ($value) in the category ($family) under the key ($key). | ||||
|  * | ||||
|  * Please do not store booleans - convert to 0/1 integer values! | ||||
|  * @note Please do not store booleans - convert to 0/1 integer values! | ||||
|  * | ||||
|  * @param string $family | ||||
|  *  The category of the configuration value | ||||
| @@ -272,14 +272,16 @@ function get_pconfig($uid, $family, $key, $instore = false) { | ||||
|  * Stores a config value ($value) in the category ($family) under the key ($key) | ||||
|  * for the channel_id $uid. | ||||
|  * | ||||
|  * Please do not store booleans - convert to 0/1 integer values! | ||||
|  * @note Please do not store booleans - convert to 0/1 integer values! | ||||
|  * | ||||
|  * @param string $uid | ||||
|  *  The channel_id | ||||
|  * @param string $family | ||||
|  *  The category of the configuration value | ||||
|  * @param string $key | ||||
|  *  The configuration key to query | ||||
|  *  The configuration key to set | ||||
|  * @param string $value | ||||
|  *  The value to store | ||||
|  * @return mixed Stored $value or false | ||||
|  */ | ||||
| function set_pconfig($uid, $family, $key, $value) { | ||||
| @@ -315,6 +317,7 @@ function set_pconfig($uid, $family, $key, $value) { | ||||
| 		); | ||||
| 		if($ret) | ||||
| 			return $value; | ||||
|  | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| @@ -339,6 +342,7 @@ function set_pconfig($uid, $family, $key, $value) { | ||||
|  | ||||
| 	if($ret) | ||||
| 		return $value; | ||||
|  | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
| @@ -360,13 +364,14 @@ function del_pconfig($uid, $family, $key) { | ||||
| 	global $a; | ||||
| 	$ret = false; | ||||
|  | ||||
| 	if(x($a->config[$uid][$family], $key)) | ||||
| 	if (x($a->config[$uid][$family], $key)) | ||||
| 		unset($a->config[$uid][$family][$key]); | ||||
| 		$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'", | ||||
| 		intval($uid), | ||||
| 		dbesc($family), | ||||
| 		dbesc($key) | ||||
| 	); | ||||
|  | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
| @@ -448,7 +453,7 @@ function get_xconfig($xchan, $family, $key) { | ||||
|  * Stores a config value ($value) in the category ($family) under the key ($key) | ||||
|  * for the observer's $xchan hash. | ||||
|  * | ||||
|  * Please do not store booleans - convert to 0/1 integer values! | ||||
|  * @note Please do not store booleans - convert to 0/1 integer values! | ||||
|  * | ||||
|  * @param string $xchan | ||||
|  *  The observer's hash | ||||
| @@ -456,6 +461,8 @@ function get_xconfig($xchan, $family, $key) { | ||||
|  *  The category of the configuration value | ||||
|  * @param string $key | ||||
|  *  The configuration key to set | ||||
|  * @param string $value | ||||
|  *  The value to store | ||||
|  * @return mixed Stored $value or false | ||||
|  */ | ||||
| function set_xconfig($xchan, $family, $key, $value) { | ||||
|   | ||||
| @@ -1044,7 +1044,6 @@ function builtin_activity_puller($item, &$conv_responses) { | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1053,7 +1052,7 @@ function builtin_activity_puller($item, &$conv_responses) { | ||||
|  * | ||||
|  * @param int $cnt number of people who like/dislike the item | ||||
|  * @param array $arr array of pre-linked names of likers/dislikers | ||||
|  * @param string $typ eone of 'like, 'dislike' | ||||
|  * @param string $type one of 'like, 'dislike' | ||||
|  * @param int $id item id | ||||
|  * @return string formatted text | ||||
|  */ | ||||
| @@ -1146,7 +1145,6 @@ function status_editor($a, $x, $popup = false) { | ||||
| 		'$expireswhen' => t('Expires YYYY-MM-DD HH:MM') | ||||
| 	)); | ||||
|  | ||||
|  | ||||
| 	$tpl = get_markup_template('jot.tpl'); | ||||
|  | ||||
| 	$jotplugins = ''; | ||||
| @@ -1461,8 +1459,8 @@ function network_tabs() { | ||||
|  | ||||
| 	if ($no_active=='active' && x($_GET,'order')) { | ||||
| 		switch($_GET['order']){ | ||||
| 		 case 'post': $postord_active = 'active'; $no_active=''; break; | ||||
| 		 case 'comment' : $all_active = 'active'; $no_active=''; break; | ||||
| 			case 'post': $postord_active = 'active'; $no_active=''; break; | ||||
| 			case 'comment' : $all_active = 'active'; $no_active=''; break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -1,54 +1,71 @@ | ||||
| <?php /** @file */ | ||||
|  | ||||
| // two-level sort for timezones. | ||||
| <?php | ||||
| /** | ||||
|  * @file include/datetime.php | ||||
|  * @brief Some functions for date and time related tasks. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Two-level sort for timezones. | ||||
|  * | ||||
|  * @param string $a | ||||
|  * @param string $b | ||||
|  * @return number | ||||
|  */ | ||||
| function timezone_cmp($a, $b) { | ||||
| 	if(strstr($a,'/') && strstr($b,'/')) { | ||||
| 		if ( t($a) == t($b)) return 0; | ||||
| 		return ( t($a) < t($b)) ? -1 : 1; | ||||
| 	} | ||||
| 	if(strstr($a,'/')) return -1; | ||||
| 	if(strstr($b,'/')) return  1; | ||||
| 	if (strstr($a,'/')) return -1; | ||||
| 	if (strstr($b,'/')) return  1; | ||||
| 	if ( t($a) == t($b)) return 0; | ||||
|  | ||||
| 	return ( t($a) < t($b)) ? -1 : 1; | ||||
| } | ||||
|  | ||||
| // Return timezones grouped (primarily) by continent | ||||
| /** | ||||
|  * @brief Return timezones grouped (primarily) by continent. | ||||
|  * | ||||
|  * @return array | ||||
|  */ | ||||
| function get_timezones( ){ | ||||
| 	$timezone_identifiers = DateTimeZone::listIdentifiers(); | ||||
|  | ||||
| 	usort($timezone_identifiers, 'timezone_cmp'); | ||||
| 	$continent = ''; | ||||
| 	$continents = array(); | ||||
| 	foreach($timezone_identifiers as $value) { | ||||
| 	foreach ($timezone_identifiers as $value) { | ||||
| 		$ex = explode("/", $value); | ||||
| 		if(count($ex) > 1) { | ||||
| 		if (count($ex) > 1) { | ||||
| 			$continent = t($ex[0]); | ||||
| 			if(count($ex) > 2) | ||||
| 				$city = substr($value,strpos($value,'/')+1); | ||||
| 			if (count($ex) > 2) | ||||
| 				$city = substr($value, strpos($value, '/')+1); | ||||
| 			else | ||||
| 				$city = $ex[1]; | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			$city = $ex[0]; | ||||
| 			$continent = t('Miscellaneous'); | ||||
| 		} | ||||
| 		$city = str_replace('_', ' ',  t($city)); | ||||
|  | ||||
| 		if(!x($continents,$ex[0])) $continents[$ex[0]] = array(); | ||||
| 		if (!x($continents, $ex[0])) $continents[$ex[0]] = array(); | ||||
| 		$continents[$continent][$value] = $city; | ||||
| 	} | ||||
|  | ||||
| 	return $continents; | ||||
| } | ||||
|  | ||||
| // General purpose date parse/convert function. | ||||
| // $from = source timezone | ||||
| // $to   = dest timezone | ||||
| // $s    = some parseable date/time string | ||||
| // $fmt  = output format | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief General purpose date parse/convert function. | ||||
|  * | ||||
|  * @param string $from source timezone | ||||
|  * @param string $to dest timezone | ||||
|  * @param string $s some parseable date/time string | ||||
|  * @param string $fmt output format recognised from php's DateTime class | ||||
|  *   http://www.php.net/manual/en/datetime.format.php | ||||
|  * @return string | ||||
|  */ | ||||
| function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d H:i:s") { | ||||
|  | ||||
| 	// Defaults to UTC if nothing is set, but throws an exception if set to empty string. | ||||
| @@ -68,44 +85,46 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d | ||||
|  | ||||
| 	if(substr($s,0,10) == '0000-00-00') { | ||||
| 		$d = new DateTime($s . ' + 32 days', new DateTimeZone('UTC')); | ||||
| 		return str_replace('1','0',$d->format($fmt)); | ||||
| 		return str_replace('1', '0', $d->format($fmt)); | ||||
| 	} | ||||
|  | ||||
| 	try { | ||||
| 		$from_obj = new DateTimeZone($from); | ||||
| 	} | ||||
| 	catch(Exception $e) { | ||||
| 	} catch(Exception $e) { | ||||
| 		$from_obj = new DateTimeZone('UTC'); | ||||
| 	} | ||||
|  | ||||
| 	try { | ||||
| 		$d = new DateTime($s, $from_obj); | ||||
| 	} | ||||
| 	catch(Exception $e) { | ||||
| 	} catch(Exception $e) { | ||||
| 		logger('datetime_convert: exception: ' . $e->getMessage()); | ||||
| 		$d = new DateTime('now', $from_obj); | ||||
| 	} | ||||
|  | ||||
| 	try { | ||||
| 		$to_obj = new DateTimeZone($to); | ||||
| 	} | ||||
| 	catch(Exception $e) { | ||||
| 	} catch(Exception $e) { | ||||
| 		$to_obj = new DateTimeZone('UTC'); | ||||
| 	} | ||||
|  | ||||
| 	$d->setTimeZone($to_obj); | ||||
|  | ||||
| 	return($d->format($fmt)); | ||||
| } | ||||
|  | ||||
| // wrapper for date selector, tailored for use in birthday fields | ||||
|  | ||||
| /** | ||||
|  * @brief Wrapper for date selector, tailored for use in birthday fields. | ||||
|  * | ||||
|  * @param string $dob Date of Birth | ||||
|  * @return string | ||||
|  */ | ||||
| function dob($dob) { | ||||
| 	list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d'); | ||||
| 	$f = get_config('system','birthday_input_format'); | ||||
| 	if(! $f) | ||||
| 	list($year, $month, $day) = sscanf($dob, '%4d-%2d-%2d'); | ||||
| 	$f = get_config('system', 'birthday_input_format'); | ||||
| 	if (! $f) | ||||
| 		$f = 'ymd'; | ||||
|  | ||||
| 	if($dob === '0000-00-00') | ||||
| 	if ($dob === '0000-00-00') | ||||
| 		$value = ''; | ||||
| 	else | ||||
| 		$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d')); | ||||
| @@ -120,7 +139,6 @@ function dob($dob) { | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * returns a date selector | ||||
|  * @param $format | ||||
| @@ -135,7 +153,7 @@ function dob($dob) { | ||||
|  *  id and name of datetimepicker (defaults to "datetimepicker") | ||||
|  */ | ||||
| function datesel($format, $min, $max, $default, $id = 'datepicker') { | ||||
| 	return datetimesel($format,$min,$max,$default,$id,true,false, '',''); | ||||
| 	return datetimesel($format, $min, $max, $default, $id,true, false, '', ''); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -154,7 +172,8 @@ function timesel($format, $h, $m, $id='timepicker') { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * returns a datetime selector | ||||
|  * @brief Returns a datetime selector. | ||||
|  * | ||||
|  * @param $format | ||||
|  *  format string, e.g. 'ymd' or 'mdy'. Not currently supported | ||||
|  * @param $min | ||||
| @@ -163,23 +182,25 @@ function timesel($format, $h, $m, $id='timepicker') { | ||||
|  *  unix timestap of maximum date | ||||
|  * @param $default | ||||
|  *  unix timestamp of default date | ||||
|  * @param $id | ||||
|  * @param string $id | ||||
|  *  id and name of datetimepicker (defaults to "datetimepicker") | ||||
|  * @param $pickdate | ||||
|  * @param boolean $pickdate | ||||
|  *  true to show date picker (default) | ||||
|  * @param $picktime | ||||
|  * @param boolean $picktime | ||||
|  *  true to show time picker (default) | ||||
|  * @param $minfrom | ||||
|  *  set minimum date from picker with id $minfrom (none by default) | ||||
|  * @param $maxfrom | ||||
|  *  set maximum date from picker with id $maxfrom (none by default) | ||||
|  * @param boolean $required default false | ||||
|  * @return string Parsed HTML output. | ||||
|  *  | ||||
|  * @todo Once browser support is better this could probably be replaced with | ||||
|  * native HTML5 date picker. | ||||
|  */ | ||||
| function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '',$required = false) { | ||||
| function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) { | ||||
|  | ||||
|  | ||||
| 	// Once browser support is better this could probably be replaced with native HTML5 date picker | ||||
| 	$o = ''; | ||||
|  | ||||
| 	$dateformat = ''; | ||||
|  | ||||
| 	if($pickdate) $dateformat .= 'Y-m-d'; | ||||
| @@ -214,23 +235,31 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic | ||||
| 	$o .= (($required) ? '<span class="required" title="' . t('Required') . '" >*</span>' : ''); | ||||
| 	$o .= '</div>'; | ||||
| 	$o .= "<script type='text/javascript'>\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})</script>"; | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
| // implements "3 seconds ago" etc. | ||||
| // based on $posted_date, (UTC). | ||||
| // Results relative to current timezone | ||||
| // Limited to range of timestamps | ||||
| /** | ||||
|  * @brief Returns a relative date string. | ||||
|  * | ||||
|  * Implements "3 seconds ago" etc. | ||||
|  * Based on $posted_date, (UTC). | ||||
|  * Results relative to current timezone. | ||||
|  * Limited to range of timestamps. | ||||
|  * | ||||
|  * @param string $posted_date | ||||
|  * @param string $format (optional) parsed with sprintf() | ||||
|  *    <tt>%1$d %2$s ago</tt>, e.g. 22 hours ago, 1 minute ago | ||||
|  * @return string with relative date | ||||
|  */ | ||||
| function relative_date($posted_date, $format = null) { | ||||
|  | ||||
|  | ||||
| function relative_date($posted_date,$format = null) { | ||||
|  | ||||
| 	$localtime = datetime_convert('UTC',date_default_timezone_get(),$posted_date);  | ||||
| 	$localtime = datetime_convert('UTC', date_default_timezone_get(), $posted_date);  | ||||
|  | ||||
| 	$abs = strtotime($localtime); | ||||
|  | ||||
|     if (is_null($posted_date) || $posted_date === NULL_DATE || $abs === False) { | ||||
| 		 return t('never'); | ||||
| 	if (is_null($posted_date) || $posted_date === NULL_DATE || $abs === false) { | ||||
| 		return t('never'); | ||||
| 	} | ||||
|  | ||||
| 	$etime = time() - $abs; | ||||
| @@ -252,226 +281,251 @@ function relative_date($posted_date,$format = null) { | ||||
| 		$d = $etime / $secs; | ||||
| 		if ($d >= 1) { | ||||
| 			$r = round($d); | ||||
| 			// translators - e.g. 22 hours ago, 1 minute ago | ||||
| 			if(! $format) | ||||
| 				$format = t('%1$d %2$s ago'); | ||||
| 			return sprintf( $format,$r, (($r == 1) ? $str[0] : $str[1])); | ||||
|         } | ||||
|     } | ||||
| 			if (! $format) | ||||
| 				$format = t('%1$d %2$s ago', 'e.g. 22 hours ago, 1 minute ago'); | ||||
|  | ||||
| 			return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1])); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // Returns age in years, given a date of birth, | ||||
| // the timezone of the person whose date of birth is provided, | ||||
| // and the timezone of the person viewing the result. | ||||
| // Why? Bear with me. Let's say I live in Mittagong, Australia, and my  | ||||
| // birthday is on New Year's. You live in San Bruno, California. | ||||
| // When exactly are you going to see my age increase? | ||||
| // A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start  | ||||
| // celebrating and become a year older. If you wish me happy birthday  | ||||
| // on January 1 (San Bruno time), you'll be a day late.  | ||||
|     | ||||
| function age($dob,$owner_tz = '',$viewer_tz = '') { | ||||
| 	if(! intval($dob)) | ||||
| /** | ||||
|  * @brief Returns timezone correct age in years. | ||||
|  * | ||||
|  * Returns the age in years, given a date of birth, the timezone of the person | ||||
|  * whose date of birth is provided, and the timezone of the person viewing the | ||||
|  * result. | ||||
|  * | ||||
|  * Why? Bear with me. Let's say I live in Mittagong, Australia, and my birthday | ||||
|  * is on New Year's. You live in San Bruno, California. | ||||
|  * When exactly are you going to see my age increase? | ||||
|  * | ||||
|  * A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start celebrating | ||||
|  * and become a year older. If you wish me happy birthday on January 1 | ||||
|  * (San Bruno time), you'll be a day late. | ||||
|  * | ||||
|  * @param string $dob Date of Birth | ||||
|  * @param string $owner_tz (optional) timezone of the person of interest | ||||
|  * @param string $viewer_tz (optional) timezone of the person viewing | ||||
|  * @return number | ||||
|  */ | ||||
| function age($dob, $owner_tz = '', $viewer_tz = '') { | ||||
| 	if (! intval($dob)) | ||||
| 		return 0; | ||||
| 	if(! $owner_tz) | ||||
| 	if (! $owner_tz) | ||||
| 		$owner_tz = date_default_timezone_get(); | ||||
| 	if(! $viewer_tz) | ||||
| 	if (! $viewer_tz) | ||||
| 		$viewer_tz = date_default_timezone_get(); | ||||
|  | ||||
| 	$birthdate = datetime_convert('UTC',$owner_tz,$dob . ' 00:00:00+00:00','Y-m-d'); | ||||
| 	list($year,$month,$day) = explode("-",$birthdate); | ||||
| 	$year_diff  = datetime_convert('UTC',$viewer_tz,'now','Y') - $year; | ||||
| 	$curr_month = datetime_convert('UTC',$viewer_tz,'now','m'); | ||||
| 	$curr_day   = datetime_convert('UTC',$viewer_tz,'now','d'); | ||||
| 	$birthdate = datetime_convert('UTC', $owner_tz, $dob . ' 00:00:00+00:00','Y-m-d'); | ||||
| 	list($year,$month,$day) = explode("-", $birthdate); | ||||
| 	$year_diff  = datetime_convert('UTC', $viewer_tz, 'now', 'Y') - $year; | ||||
| 	$curr_month = datetime_convert('UTC', $viewer_tz, 'now', 'm'); | ||||
| 	$curr_day   = datetime_convert('UTC', $viewer_tz, 'now', 'd'); | ||||
|  | ||||
| 	if(($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day))) | ||||
| 	if (($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day))) | ||||
| 		$year_diff--; | ||||
|  | ||||
| 	return $year_diff; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Get days of a month in a given year. | ||||
|  * | ||||
|  * Returns number of days in the month of the given year. | ||||
|  * $m = 1 is 'January' to match human usage. | ||||
|  * | ||||
|  * @param int $y year | ||||
|  * @param int $m month (1=January, 12=December) | ||||
|  * @return int number of days in the given month | ||||
|  */ | ||||
| function get_dim($y, $m) { | ||||
| 	$dim = array( 0, | ||||
| 			31, 28, 31, 30, 31, 30, | ||||
| 			31, 31, 30, 31, 30, 31 | ||||
| 	); | ||||
|  | ||||
| 	if ($m != 2) | ||||
| 		return $dim[$m]; | ||||
|  | ||||
| // Get days in month | ||||
| // get_dim($year, $month); | ||||
| // returns number of days. | ||||
| // $month[1] = 'January';  | ||||
| //   to match human usage. | ||||
| 	if (((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0)) | ||||
| 		return 29; | ||||
|  | ||||
|  | ||||
| function get_dim($y,$m) { | ||||
|  | ||||
|   $dim = array( 0, | ||||
|     31, 28, 31, 30, 31, 30, | ||||
|     31, 31, 30, 31, 30, 31); | ||||
|   | ||||
|   if($m != 2) | ||||
|     return $dim[$m]; | ||||
|   if(((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0)) | ||||
|     return 29; | ||||
|   return $dim[2]; | ||||
| 	return $dim[2]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Returns the first day in month for a given month, year. | ||||
|  * | ||||
|  * Months start at 1. | ||||
|  * | ||||
|  * @param int $y Year | ||||
|  * @param int $m Month (1=January, 12=December) | ||||
|  * @return day 0 = Sunday through 6 = Saturday | ||||
|  */ | ||||
| function get_first_dim($y, $m) { | ||||
| 	$d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m)); | ||||
|  | ||||
| // Returns the first day in month for a given month, year | ||||
| // get_first_dim($year,$month) | ||||
| // returns 0 = Sunday through 6 = Saturday | ||||
| // Months start at 1. | ||||
|  | ||||
|  | ||||
| function get_first_dim($y,$m) { | ||||
|   $d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m)); | ||||
|   return datetime_convert('UTC','UTC',$d,'w'); | ||||
| 	return datetime_convert('UTC', 'UTC', $d, 'w'); | ||||
| } | ||||
|  | ||||
| // output a calendar for the given month, year. | ||||
| // if $links are provided (array), e.g. $links[12] => 'http://mylink' ,  | ||||
| // date 12 will be linked appropriately. Today's date is also noted by  | ||||
| // altering td class. | ||||
| // Months count from 1. | ||||
|  | ||||
|  | ||||
| // TODO: provide (prev,next) links, define class variations for different size calendars | ||||
|  | ||||
| function cal($y = 0,$m = 0, $links = false, $class='') { | ||||
|  | ||||
| /** | ||||
|  * @brief Output a calendar for the given month, year. | ||||
|  * | ||||
|  * If $links are provided (array), e.g. $links[12] => 'http://mylink' , | ||||
|  * date 12 will be linked appropriately. Today's date is also noted by | ||||
|  * altering td class. | ||||
|  * Months count from 1. | ||||
|  * | ||||
|  * @param number $y Year | ||||
|  * @param number $m Month | ||||
|  * @param string $links (default false) | ||||
|  * @param string $class | ||||
|  * @return string | ||||
|  * | ||||
|  * @todo provide (prev,next) links, define class variations for different size calendars | ||||
|  */ | ||||
| function cal($y = 0, $m = 0, $links = false, $class='') { | ||||
|  | ||||
| 	// month table - start at 1 to match human usage. | ||||
|  | ||||
| 	$mtab = array(' ', | ||||
| 	  'January','February','March', | ||||
| 	  'April','May','June', | ||||
| 	  'July','August','September', | ||||
| 	  'October','November','December' | ||||
| 		'January','February','March', | ||||
| 		'April','May','June', | ||||
| 		'July','August','September', | ||||
| 		'October','November','December' | ||||
| 	); | ||||
|  | ||||
| 	$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); | ||||
| 	$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); | ||||
| 	if(! $y) | ||||
| 	if (! $y) | ||||
| 		$y = $thisyear; | ||||
| 	if(! $m) | ||||
| 	if (! $m) | ||||
| 		$m = intval($thismonth); | ||||
|  | ||||
|   $dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); | ||||
|   $f = get_first_dim($y,$m); | ||||
|   $l = get_dim($y,$m); | ||||
|   $d = 1; | ||||
|   $dow = 0; | ||||
|   $started = false; | ||||
| 	$dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); | ||||
| 	$f = get_first_dim($y, $m); | ||||
| 	$l = get_dim($y, $m); | ||||
| 	$d = 1; | ||||
| 	$dow = 0; | ||||
| 	$started = false; | ||||
|  | ||||
|   if(($y == $thisyear) && ($m == $thismonth)) | ||||
|     $tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j')); | ||||
| 	if (($y == $thisyear) && ($m == $thismonth)) | ||||
| 		$tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j')); | ||||
|  | ||||
| 	$str_month = day_translate($mtab[$m]); | ||||
|   $o = '<table class="calendar' . $class . '">'; | ||||
|   $o .= "<caption>$str_month $y</caption><tr>"; | ||||
|   for($a = 0; $a < 7; $a ++) | ||||
|      $o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>'; | ||||
|   $o .= '</tr><tr>'; | ||||
| 	$o = '<table class="calendar' . $class . '">'; | ||||
| 	$o .= "<caption>$str_month $y</caption><tr>"; | ||||
| 	for ($a = 0; $a < 7; $a ++) | ||||
| 		$o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>'; | ||||
|  | ||||
|   while($d <= $l) { | ||||
|     if(($dow == $f) && (! $started)) | ||||
|       $started = true; | ||||
|     $today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : ''); | ||||
|     $o .= "<td $today>"; | ||||
| 	$day = str_replace(' ',' ',sprintf('%2.2d', $d)); | ||||
|     if($started) { | ||||
|       if(is_array($links) && isset($links[$d])) | ||||
|         $o .=  "<a href=\"{$links[$d]}\">$day</a>"; | ||||
|       else | ||||
|         $o .= $day; | ||||
|       $d ++; | ||||
|     } | ||||
|     else | ||||
|       $o .= ' '; | ||||
|     $o .= '</td>'; | ||||
|     $dow ++; | ||||
|     if(($dow == 7) && ($d <= $l)) { | ||||
|       $dow = 0; | ||||
|       $o .= '</tr><tr>'; | ||||
|     } | ||||
|   } | ||||
|   if($dow) | ||||
|     for($a = $dow; $a < 7; $a ++) | ||||
|        $o .= '<td> </td>'; | ||||
|   $o .= '</tr></table>'."\r\n";   | ||||
| 	$o .= '</tr><tr>'; | ||||
|  | ||||
|   return $o; | ||||
| 	while ($d <= $l) { | ||||
| 		if (($dow == $f) && (! $started)) | ||||
| 			$started = true; | ||||
|  | ||||
| 		$today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : ''); | ||||
| 		$o .= "<td $today>"; | ||||
| 		$day = str_replace(' ',' ',sprintf('%2.2d', $d)); | ||||
| 		if ($started) { | ||||
| 			if (is_array($links) && isset($links[$d])) | ||||
| 				$o .=  "<a href=\"{$links[$d]}\">$day</a>"; | ||||
| 			else | ||||
| 				$o .= $day; | ||||
|  | ||||
| 			$d ++; | ||||
| 		} else { | ||||
| 			$o .= ' '; | ||||
| 		} | ||||
|  | ||||
| 		$o .= '</td>'; | ||||
| 		$dow ++; | ||||
| 		if (($dow == 7) && ($d <= $l)) { | ||||
| 			$dow = 0; | ||||
| 			$o .= '</tr><tr>'; | ||||
| 		} | ||||
| 	} | ||||
| 	if ($dow) | ||||
| 		for ($a = $dow; $a < 7; $a ++) | ||||
| 			$o .= '<td> </td>'; | ||||
|  | ||||
| 	$o .= '</tr></table>'."\r\n"; | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return the next birthday, converted from the owner's timezone to UTC.  | ||||
|  * @brief Return the next birthday, converted from the owner's timezone to UTC. | ||||
|  *  | ||||
|  * This makes it globally portable. | ||||
|  * If the provided birthday lacks a month and or day, return an empty string. | ||||
|  * A missing year is acceptable. | ||||
|  * | ||||
|  * @param string $dob Date of Birth | ||||
|  * @param string $tz Timezone | ||||
|  * @param string $format | ||||
|  * @return string | ||||
|  */ | ||||
| function z_birthday($dob, $tz, $format="Y-m-d H:i:s") { | ||||
|  | ||||
|  | ||||
| function z_birthday($dob,$tz,$format="Y-m-d H:i:s") { | ||||
|  | ||||
| 	if(! strlen($tz)) | ||||
| 	if (! strlen($tz)) | ||||
| 		$tz = 'UTC'; | ||||
|  | ||||
| 	$birthday = ''; | ||||
| 	$tmp_dob = substr($dob,5); | ||||
| 	$tmp_d = substr($dob,8); | ||||
| 	if(intval($tmp_dob) && intval($tmp_d)) { | ||||
| 	if (intval($tmp_dob) && intval($tmp_d)) { | ||||
| 		$y = datetime_convert($tz,$tz,'now','Y'); | ||||
| 		$bd = $y . '-' . $tmp_dob . ' 00:00'; | ||||
| 		$t_dob = strtotime($bd); | ||||
| 		$now = strtotime(datetime_convert($tz,$tz,'now')); | ||||
| 		if($t_dob < $now) | ||||
| 		if ($t_dob < $now) | ||||
| 			$bd = $y + 1 . '-' . $tmp_dob . ' 00:00'; | ||||
|  | ||||
| 		$birthday = datetime_convert($tz,'UTC',$bd,$format); | ||||
| 	} | ||||
|  | ||||
| 	return $birthday; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Create a birthday event for any connections with a birthday in the next 1-2 weeks. | ||||
|  * | ||||
|  * Create a birthday event for any connections with a birthday in the next 1-2 weeks. | ||||
|  * Update the year so that we don't create another event until next year. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function update_birthdays() { | ||||
|  | ||||
| 	require_once('include/event.php'); | ||||
| 	require_once('include/permissions.php'); | ||||
|  | ||||
|     $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash  | ||||
| 	$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash  | ||||
| 		WHERE abook_dob > %s + interval %s and abook_dob < %s + interval %s", | ||||
| 		db_utcnow(), db_quoteinterval('7 day'), | ||||
| 		db_utcnow(), db_quoteinterval('14 day') | ||||
| 		); | ||||
| 	if($r) { | ||||
| 		foreach($r as $rr) { | ||||
| 			 | ||||
| 			if(! perm_is_allowed($rr['abook_channel'],$rr['xchan_hash'],'send_stream')) | ||||
| 	); | ||||
| 	if ($r) { | ||||
| 		foreach ($r as $rr) { | ||||
| 			if (! perm_is_allowed($rr['abook_channel'], $rr['xchan_hash'], 'send_stream')) | ||||
| 				continue; | ||||
|  | ||||
| 			$ev = array(); | ||||
| 			$ev['uid'] = $rr['abook_channel']; | ||||
| 			$ev['account'] = $rr['abook_account']; | ||||
| 			$ev['event_xchan'] = $rr['xchan_hash']; | ||||
| 			$ev['start'] = datetime_convert('UTC','UTC', $rr['abook_dob']); | ||||
| 			$ev['finish'] = datetime_convert('UTC','UTC', $rr['abook_dob'] . ' + 1 day '); | ||||
| 			$ev['start'] = datetime_convert('UTC', 'UTC', $rr['abook_dob']); | ||||
| 			$ev['finish'] = datetime_convert('UTC', 'UTC', $rr['abook_dob'] . ' + 1 day '); | ||||
| 			$ev['adjust'] = 1; | ||||
|             $ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']); | ||||
|             $ev['description'] = sprintf( t('Happy Birthday %1$s'),  | ||||
| 			$ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']); | ||||
| 			$ev['description'] = sprintf( t('Happy Birthday %1$s'),  | ||||
| 				'[zrl=' . $rr['xchan_url'] . ']' . $rr['xchan_name'] . '[/zrl]') ; | ||||
| 			$ev['type'] = 'birthday'; | ||||
|  | ||||
| 			$z = event_store_event($ev); | ||||
| 			if($z) { | ||||
| 				$item_id = event_store_item($ev,$z); | ||||
| 			if ($z) { | ||||
| 				$item_id = event_store_item($ev, $z); | ||||
| 				q("update abook set abook_dob = '%s' where abook_id = %d", | ||||
| 					dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'],4)), | ||||
| 					dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'], 4)), | ||||
| 					intval($rr['abook_id']) | ||||
| 				); | ||||
| 			} | ||||
|   | ||||
| @@ -1,14 +1,23 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/dir_fns.php | ||||
|  */ | ||||
|  | ||||
| require_once('include/permissions.php'); | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param int $dirmode | ||||
|  * @return array | ||||
|  */ | ||||
| function find_upstream_directory($dirmode) { | ||||
| 	global $DIRECTORY_FALLBACK_SERVERS; | ||||
|  | ||||
| 	$preferred = get_config('system','directory_server'); | ||||
| 	if(! $preferred) { | ||||
| 	if (! $preferred) { | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * No directory has yet been set. For most sites, pick one at random | ||||
| 		 * from our list of directory servers. However, if we're a directory | ||||
| 		 * server ourself, point at the local instance | ||||
| @@ -18,41 +27,40 @@ function find_upstream_directory($dirmode) { | ||||
| 		 */ | ||||
|  | ||||
| 		$dirmode = intval(get_config('system','directory_mode')); | ||||
| 		if($dirmode == DIRECTORY_MODE_NORMAL) { | ||||
| 		if ($dirmode == DIRECTORY_MODE_NORMAL) { | ||||
| 			$toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS)); | ||||
| 			$preferred = $DIRECTORY_FALLBACK_SERVERS[$toss]; | ||||
| 			set_config('system','directory_server',$preferred); | ||||
| 		} | ||||
| 		else{ | ||||
| 		} else{ | ||||
| 			set_config('system','directory_server',z_root()); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return array('url' => $preferred); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Directories may come and go over time. We will need to check that our | ||||
|  * directory server is still valid occasionally, and reset to something that | ||||
|  * is if our directory has gone offline for any reason | ||||
|  */ | ||||
| function check_upstream_directory() { | ||||
|  | ||||
| 	/** | ||||
| 	* Directories may come and go over time.  We will need to check that our  | ||||
| 	* directory server is still valid occasionally, and reset to something that | ||||
| 	* is if our directory has gone offline for any reason | ||||
| 	*/ | ||||
|  | ||||
| 	$directory = get_config('system','directory_server'); | ||||
| 	$directory = get_config('system', 'directory_server'); | ||||
|  | ||||
| 	// it's possible there is no directory server configured and the local hub is being used. | ||||
| 	// If so, default to preserving the absence of a specific server setting. | ||||
|  | ||||
| 	$isadir = true; | ||||
|  | ||||
| 	if($directory) { | ||||
| 	if ($directory) { | ||||
| 		$h = parse_url($directory); | ||||
| 		if($h) { | ||||
| 		if ($h) { | ||||
| 			$x = zot_finger('[system]@' . $h['host']); | ||||
| 			if($x['success']) { | ||||
| 				$j = json_decode($x['body'],true); | ||||
| 				if(array_key_exists('site',$j) && array_key_exists('directory_mode',$j['site'])) { | ||||
| 					if($j['site']['directory_mode'] === 'normal') { | ||||
| 			if ($x['success']) { | ||||
| 				$j = json_decode($x['body'], true); | ||||
| 				if (array_key_exists('site', $j) && array_key_exists('directory_mode', $j['site'])) { | ||||
| 					if ($j['site']['directory_mode'] === 'normal') { | ||||
| 						$isadir = false; | ||||
| 					} | ||||
| 				} | ||||
| @@ -60,9 +68,8 @@ function check_upstream_directory() { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(! $isadir) | ||||
| 		set_config('system','directory_server',''); | ||||
| 	return; | ||||
| 	if (! $isadir) | ||||
| 		set_config('system', 'directory_server', ''); | ||||
| } | ||||
|  | ||||
| function get_globaldir_setting($observer) { | ||||
| @@ -95,12 +102,8 @@ function get_safemode_setting($observer) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function dir_sort_links() | ||||
|  * Called by the directory_sort widget | ||||
|  * @brief Called by the directory_sort widget. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| 	 | ||||
| function dir_sort_links() { | ||||
|  | ||||
| 	$safe_mode = 1; | ||||
| @@ -110,7 +113,7 @@ function dir_sort_links() { | ||||
| 	$safe_mode = get_safemode_setting($observer); | ||||
| 	$globaldir = get_globaldir_setting($observer); | ||||
|  | ||||
|  	// Build urls without order and pubforums so it's easy to tack on the changed value | ||||
| 	// Build urls without order and pubforums so it's easy to tack on the changed value | ||||
| 	// Probably there's an easier way to do this | ||||
|  | ||||
| 	$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'date'); | ||||
| @@ -145,14 +148,12 @@ function dir_sort_links() { | ||||
| 		'$pubforums' => array('pubforums', t('Public Forums Only'),(x($_REQUEST,'pubforums') ? $_REQUEST['pubforums'] : ''),'','',' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''),  | ||||
| 		'$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'','',' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''), | ||||
| 	)); | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function sync_directories($mode) | ||||
|  *  | ||||
|  * @param int $mode; | ||||
|  * @brief Checks the directory mode of this hub. | ||||
|  * | ||||
|  * Checks the directory mode of this hub to see if it is some form of directory server. If it is, | ||||
|  * get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request | ||||
| @@ -160,23 +161,21 @@ function dir_sort_links() { | ||||
|  * In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored  | ||||
|  * directly if the rater's signature matches. | ||||
|  * | ||||
|  * @param int $dirmode; | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function sync_directories($dirmode) { | ||||
|  | ||||
| 	if($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL) | ||||
| 	if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL) | ||||
| 		return; | ||||
|  | ||||
| 	$realm = get_directory_realm(); | ||||
| 	if($realm == DIRECTORY_REALM) { | ||||
| 	if ($realm == DIRECTORY_REALM) { | ||||
| 		$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and ( site_realm = '%s' or site_realm = '') ", | ||||
| 			intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), | ||||
| 			dbesc(z_root()), | ||||
| 			dbesc($realm) | ||||
| 		); | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' ", | ||||
| 			intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), | ||||
| 			dbesc(z_root()), | ||||
| @@ -185,9 +184,9 @@ function sync_directories($dirmode) { | ||||
| 	} | ||||
|  | ||||
| 	// If there are no directory servers, setup the fallback master | ||||
| 	// FIXME - what to do if we're in a different realm? | ||||
| 	/** @FIXME What to do if we're in a different realm? */ | ||||
|  | ||||
| 	if((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) { | ||||
| 	if ((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) { | ||||
| 		$r = array(); | ||||
| 		$r[] = array( | ||||
| 			'site_url' => DIRECTORY_FALLBACK_MASTER, | ||||
| @@ -211,32 +210,30 @@ function sync_directories($dirmode) { | ||||
| 			intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), | ||||
| 			dbesc(z_root()) | ||||
| 		); | ||||
|  | ||||
| 	} | ||||
| 	if(! $r) | ||||
| 	if (! $r) | ||||
| 		return; | ||||
|  | ||||
| 	foreach($r as $rr) { | ||||
| 		if(! $rr['site_directory']) | ||||
| 	foreach ($r as $rr) { | ||||
| 		if (! $rr['site_directory']) | ||||
| 			continue; | ||||
|  | ||||
| 		logger('sync directories: ' . $rr['site_directory']); | ||||
|  | ||||
| 		// for brand new directory servers, only load the last couple of days. | ||||
| 		// It will take about a month for a new directory to obtain the full current repertoire of channels. | ||||
| 		// FIXME - go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. | ||||
| 		/** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */ | ||||
|  | ||||
| 		$token = get_config('system','realm_token'); | ||||
|  | ||||
|  | ||||
| 		$syncdate = (($rr['site_sync'] === NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']); | ||||
| 		$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : '')); | ||||
|  | ||||
| 		if(! $x['success']) | ||||
| 		if (! $x['success']) | ||||
| 			continue; | ||||
|  | ||||
| 		$j = json_decode($x['body'],true); | ||||
| 		if(!($j['transactions']) || ($j['ratings'])) | ||||
| 		if (!($j['transactions']) || ($j['ratings'])) | ||||
| 			continue; | ||||
|  | ||||
| 		q("update site set site_sync = '%s' where site_url = '%s'", | ||||
| @@ -246,17 +243,18 @@ function sync_directories($dirmode) { | ||||
|  | ||||
| 		logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA); | ||||
|  | ||||
| 		if(is_array($j['transactions']) && count($j['transactions'])) { | ||||
| 			foreach($j['transactions'] as $t) { | ||||
| 		if (is_array($j['transactions']) && count($j['transactions'])) { | ||||
| 			foreach ($j['transactions'] as $t) { | ||||
| 				$r = q("select * from updates where ud_guid = '%s' limit 1", | ||||
| 					dbesc($t['transaction_id']) | ||||
| 				); | ||||
| 				if($r) | ||||
| 					continue; | ||||
|  | ||||
| 				$ud_flags = 0; | ||||
| 				if(is_array($t['flags']) && in_array('deleted',$t['flags'])) | ||||
| 				if (is_array($t['flags']) && in_array('deleted',$t['flags'])) | ||||
| 					$ud_flags |= UPDATE_FLAGS_DELETED; | ||||
| 				if(is_array($t['flags']) && in_array('forced',$t['flags'])) | ||||
| 				if (is_array($t['flags']) && in_array('forced',$t['flags'])) | ||||
| 					$ud_flags |= UPDATE_FLAGS_FORCED; | ||||
|  | ||||
| 				$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) | ||||
| @@ -269,42 +267,41 @@ function sync_directories($dirmode) { | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 		if(is_array($j['ratings']) && count($j['ratings'])) { | ||||
| 			foreach($j['ratings'] as $rr) {		 | ||||
| 		if (is_array($j['ratings']) && count($j['ratings'])) { | ||||
| 			foreach ($j['ratings'] as $rr) { | ||||
| 				$x = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", | ||||
| 					dbesc($rr['channel']), | ||||
| 					dbesc($rr['target']) | ||||
| 				); | ||||
| 				if($x && $x[0]['xlink_updated'] >= $rr['edited']) | ||||
| 				if ($x && $x[0]['xlink_updated'] >= $rr['edited']) | ||||
| 					continue; | ||||
|  | ||||
| 				// Ratings are signed by the rater. We need to verify before we can accept it. | ||||
| 				// TODO - queue or defer if the xchan is not yet present on our site | ||||
| 				/** @TODO Queue or defer if the xchan is not yet present on our site */ | ||||
|  | ||||
| 				$y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", | ||||
| 					dbesc($rr['channel']) | ||||
| 				); | ||||
| 				if(! $y) { | ||||
| 				if (! $y) { | ||||
| 					logger('key unavailable on this site for ' . $rr['channel']); | ||||
| 					continue; | ||||
| 				} | ||||
| 				if(! rsa_verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) { | ||||
| 			        logger('failed to verify rating'); | ||||
| 				if (! rsa_verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) { | ||||
| 					logger('failed to verify rating'); | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				if($x) { | ||||
| 				if ($x) { | ||||
| 					$z = q("update xlink set xlink_rating = %d, xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' where xlink_id = %d", | ||||
| 						intval($rr['rating']), | ||||
| 						dbesc($rr['rating_text']), | ||||
| 						dbesc($rr['signature']), | ||||
| 						dbesc(datetime_convert()), | ||||
| 						intval($x[0]['xlink_id']) | ||||
| 	        		); | ||||
| 			        logger('rating updated'); | ||||
|     			} | ||||
|     			else { | ||||
|         			$z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", | ||||
| 					); | ||||
| 					logger('rating updated'); | ||||
| 				} else { | ||||
| 					$z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", | ||||
| 						dbesc($rr['channel']), | ||||
| 						dbesc($rr['target']), | ||||
| 						intval($rr['rating']), | ||||
| @@ -321,50 +318,51 @@ function sync_directories($dirmode) { | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * $function update_directory_entry($ud) | ||||
|  * @brief | ||||
|  * | ||||
|  * @param array $ud; // Entry from update table | ||||
|  * Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data   | ||||
|  * Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data. | ||||
|  * | ||||
|  * Ignore updating records marked as deleted | ||||
|  * Ignore updating records marked as deleted. | ||||
|  * | ||||
|  * If successful,  | ||||
|  *   sets ud_last in the DB to the current datetime for this reddress/webbie | ||||
|  * If successful, sets ud_last in the DB to the current datetime for this | ||||
|  * reddress/webbie. | ||||
|  * | ||||
|  * @param array $ud Entry from update table | ||||
|  */ | ||||
|  | ||||
| function update_directory_entry($ud) { | ||||
|  | ||||
| 	logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA); | ||||
|  | ||||
| 	if($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) { | ||||
| 	if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) { | ||||
| 		$success = false; | ||||
| 		$x = zot_finger($ud['ud_addr'],''); | ||||
| 		if($x['success']) { | ||||
| 			$j = json_decode($x['body'],true); | ||||
| 			if($j) | ||||
| 		$x = zot_finger($ud['ud_addr'], ''); | ||||
| 		if ($x['success']) { | ||||
| 			$j = json_decode($x['body'], true); | ||||
| 			if ($j) | ||||
| 				$success = true; | ||||
| 			$y = import_xchan($j,0,$ud); | ||||
|  | ||||
| 			$y = import_xchan($j, 0, $ud); | ||||
| 		} | ||||
| 		if(! $success) { | ||||
| 			$r = q("update updates set ud_last = '%s' where ud_addr = '%s'", | ||||
| 		if (! $success) { | ||||
| 			q("update updates set ud_last = '%s' where ud_addr = '%s'", | ||||
| 				dbesc(datetime_convert()), | ||||
| 				dbesc($ud['ud_addr']) | ||||
| 			); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function local_dir_update($uid,$force) | ||||
|  *     push local channel updates to a local directory server | ||||
|  *  This is called from include/directory.php if a profile is to be pushed | ||||
|  *  to the directory and the local hub in this case is any kind of directory server.  | ||||
|  * @brief Push local channel updates to a local directory server. | ||||
|  * | ||||
|  * This is called from include/directory.php if a profile is to be pushed to the | ||||
|  * directory and the local hub in this case is any kind of directory server. | ||||
|  * | ||||
|  * @param int $uid | ||||
|  * @param boolean $force | ||||
|  */ | ||||
|  | ||||
| function local_dir_update($uid,$force) { | ||||
| function local_dir_update($uid, $force) { | ||||
|  | ||||
| 	logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG); | ||||
|  | ||||
| @@ -375,12 +373,12 @@ function local_dir_update($uid,$force) { | ||||
| 	$profile = array(); | ||||
| 	$profile['encoding'] = 'zot'; | ||||
|  | ||||
| 	if($p) { | ||||
| 	if ($p) { | ||||
| 		$hash = $p[0]['channel_hash']; | ||||
|  | ||||
| 		$profile['description'] = $p[0]['pdesc']; | ||||
| 		$profile['birthday']    = $p[0]['dob']; | ||||
| 		if($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))   | ||||
| 		if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))   | ||||
| 			$profile['age'] = $age; | ||||
|  | ||||
| 		$profile['gender']      = $p[0]['gender']; | ||||
| @@ -394,14 +392,15 @@ function local_dir_update($uid,$force) { | ||||
| 		$profile['homepage']    = $p[0]['homepage']; | ||||
| 		$profile['hometown']    = $p[0]['hometown']; | ||||
|  | ||||
| 		if($p[0]['keywords']) { | ||||
| 		if ($p[0]['keywords']) { | ||||
| 			$tags = array(); | ||||
| 			$k = explode(' ',$p[0]['keywords']); | ||||
| 			if($k) | ||||
| 				foreach($k as $kk) | ||||
| 					if(trim($kk)) | ||||
| 			$k = explode(' ', $p[0]['keywords']); | ||||
| 			if ($k) | ||||
| 				foreach ($k as $kk) | ||||
| 					if (trim($kk)) | ||||
| 						$tags[] = trim($kk); | ||||
| 			if($tags) | ||||
|  | ||||
| 			if ($tags) | ||||
| 				$profile['keywords'] = $tags; | ||||
| 		} | ||||
|  | ||||
| @@ -414,26 +413,23 @@ function local_dir_update($uid,$force) { | ||||
| 		); | ||||
|  | ||||
| 		// Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1 | ||||
| 		if(($r[0]['xchan_flags'] & XCHAN_FLAGS_HIDDEN) != $hidden) | ||||
| 		if (($r[0]['xchan_flags'] & XCHAN_FLAGS_HIDDEN) != $hidden) | ||||
| 			$new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_HIDDEN; | ||||
| 		else | ||||
| 			$new_flags = $r[0]['xchan_flags']; | ||||
|  | ||||
| 		if($new_flags != $r[0]['xchan_flags']) {			 | ||||
|  | ||||
| 		if ($new_flags != $r[0]['xchan_flags']) { | ||||
| 			$r = q("update xchan set xchan_flags = %d  where xchan_hash = '%s'", | ||||
| 				intval($new_flags), | ||||
| 				dbesc($p[0]['channel_hash']) | ||||
| 			); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		$address = $p[0]['channel_address'] . '@' . get_app()->get_hostname(); | ||||
|  | ||||
| 		if(perm_is_allowed($uid,'','view_profile')) { | ||||
| 			import_directory_profile($hash,$profile,$address,0); | ||||
| 		} | ||||
| 		else { | ||||
| 		if (perm_is_allowed($uid, '', 'view_profile')) { | ||||
| 			import_directory_profile($hash, $profile, $address, 0); | ||||
| 		} else { | ||||
| 			// they may have made it private | ||||
| 			$r = q("delete from xprof where xprof_hash = '%s'", | ||||
| 				dbesc($hash) | ||||
| @@ -445,7 +441,5 @@ function local_dir_update($uid,$force) { | ||||
| 	} | ||||
|  | ||||
| 	$ud_hash = random_string() . '@' . get_app()->get_hostname(); | ||||
| 	update_modtime($hash,$ud_hash,$p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); | ||||
|  | ||||
| 	update_modtime($hash, $ud_hash, $p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); | ||||
| } | ||||
| 	 | ||||
|   | ||||
| @@ -1,11 +1,20 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/directory.php | ||||
|  * @brief executes directory_run() | ||||
|  */ | ||||
|  | ||||
| require_once('boot.php'); | ||||
| require_once('include/zot.php'); | ||||
| require_once('include/cli_startup.php'); | ||||
| require_once('include/dir_fns.php'); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param array $argv | ||||
|  * @param array $argc | ||||
|  */ | ||||
| function directory_run($argv, $argc){ | ||||
|  | ||||
| 	cli_startup(); | ||||
| @@ -37,7 +46,6 @@ function directory_run($argv, $argc){ | ||||
|  | ||||
| 	$channel = $x[0]; | ||||
|  | ||||
|  | ||||
| 	if($dirmode != DIRECTORY_MODE_NORMAL) { | ||||
|  | ||||
| 		// this is an in-memory update and we don't need to send a network packet. | ||||
| @@ -70,8 +78,9 @@ function directory_run($argv, $argc){ | ||||
|  | ||||
| 	if(! $z['success']) { | ||||
|  | ||||
| 		// FIXME - we aren't updating channel_dirdate if we have to queue | ||||
| 		// the directory packet. That means we'll try again on the next poll run. | ||||
| 		/** @FIXME we aren't updating channel_dirdate if we have to queue | ||||
| 		 * the directory packet. That means we'll try again on the next poll run. | ||||
| 		 */ | ||||
|  | ||||
| 		$hash = random_string(); | ||||
| 		q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg )  | ||||
| @@ -87,8 +96,7 @@ function directory_run($argv, $argc){ | ||||
| 			dbesc($packet), | ||||
| 			dbesc('') | ||||
| 		); | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		q("update channel set channel_dirdate = '%s' where channel_id = %d", | ||||
| 			dbesc(datetime_convert()), | ||||
| 			intval($channel['channel_id']) | ||||
| @@ -101,7 +109,7 @@ function directory_run($argv, $argc){ | ||||
|  | ||||
| } | ||||
|  | ||||
| if (array_search(__file__,get_included_files())===0){ | ||||
|   directory_run($argv,$argc); | ||||
|   killme(); | ||||
| if (array_search(__file__, get_included_files()) === 0) { | ||||
| 	directory_run($argv, $argc); | ||||
| 	killme(); | ||||
| } | ||||
|   | ||||
| @@ -1,33 +1,50 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/enotify.php | ||||
|  * | ||||
|  * @brief File with functions and a class for email notifications. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param array $params an assoziative array with: | ||||
|  *  * \e string \b from_xchan sender xchan hash | ||||
|  *  * \e string \b to_xchan recipient xchan hash | ||||
|  *  * \e array \b item an assoziative array | ||||
|  *  * \e int \b type one of the NOTIFY_* constants from boot.php | ||||
|  *  * \e string \b link | ||||
|  *  * \e string \b parent_mid | ||||
|  *  * \e string \b otype | ||||
|  *  * \e string \b verb | ||||
|  *  * \e string \b activity | ||||
|  */ | ||||
| function notification($params) { | ||||
|  | ||||
| 	logger('notification: entry', LOGGER_DEBUG); | ||||
|  | ||||
| 	// throw a small amount of entropy into the system to breakup duplicates arriving at the same precise instant. | ||||
| 	usleep(mt_rand(0,10000)); | ||||
| 	 | ||||
| 	usleep(mt_rand(0, 10000)); | ||||
|  | ||||
| 	$a = get_app(); | ||||
|  | ||||
|  | ||||
| 	if($params['from_xchan']) { | ||||
| 	if ($params['from_xchan']) { | ||||
| 		$x = q("select * from xchan where xchan_hash = '%s' limit 1", | ||||
| 			dbesc($params['from_xchan']) | ||||
| 		); | ||||
| 	} | ||||
| 	if($params['to_xchan']) { | ||||
| 	if ($params['to_xchan']) { | ||||
| 		$y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id | ||||
| 			where channel_hash = '%s' and not (channel_pageflags & %d)>0 limit 1", | ||||
| 			dbesc($params['to_xchan']), | ||||
| 			intval(PAGE_REMOVED) | ||||
| 		); | ||||
| 	} | ||||
| 	if($x & $y) { | ||||
| 	if ($x & $y) { | ||||
| 		$sender = $x[0]; | ||||
| 		$recip = $y[0]; | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		logger('notification: no sender or recipient.'); | ||||
| 		logger('sender: ' . $params['from_xchan']); | ||||
| 		logger('recip: ' . $params['to_xchan']); | ||||
| @@ -55,10 +72,10 @@ function notification($params) { | ||||
|  | ||||
| 	$additional_mail_header = ""; | ||||
|  | ||||
| 	if(array_key_exists('item',$params)) { | ||||
| 	if (array_key_exists('item', $params)) { | ||||
| 		require_once('include/conversation.php'); | ||||
| 		// if it's a normal item... | ||||
| 		if(array_key_exists('verb',$params['item'])) { | ||||
| 		if (array_key_exists('verb', $params['item'])) { | ||||
| 			// localize_item() alters the original item so make a copy first | ||||
| 			$i = $params['item']; | ||||
| 			logger('calling localize'); | ||||
| @@ -66,13 +83,11 @@ function notification($params) { | ||||
| 			$title = $i['title']; | ||||
| 			$body = $i['body']; | ||||
| 			$private = (($i['item_private']) || ($i['item_flags'] & ITEM_OBSCURED)); | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			$title = $params['item']['title']; | ||||
| 			$body = $params['item']['body']; | ||||
| 		} | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$title = $body = ''; | ||||
| 	} | ||||
|  | ||||
| @@ -80,7 +95,7 @@ function notification($params) { | ||||
| 	// e.g. "your post", "David's photo", etc. | ||||
| 	$possess_desc = t('%s <!item_type!>'); | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_MAIL) { | ||||
| 	if ($params['type'] == NOTIFY_MAIL) { | ||||
| 		logger('notification: mail'); | ||||
| 		$subject = 	sprintf( t('[Red:Notify] New mail received at %s'),$sitename); | ||||
|  | ||||
| @@ -92,15 +107,14 @@ function notification($params) { | ||||
| 		$itemlink = $siteurl . '/mail/' . $params['item']['id']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_COMMENT) { | ||||
| 	if ($params['type'] == NOTIFY_COMMENT) { | ||||
| //		logger("notification: params = " . print_r($params, true), LOGGER_DEBUG); | ||||
|  | ||||
| 		$itemlink =  $params['link']; | ||||
|  | ||||
|  | ||||
| 		// ignore like/unlike activity on posts - they probably require a sepearate notification preference | ||||
|  | ||||
| 		if(array_key_exists('item',$params) && (! visible_activity($params['item']))) | ||||
| 		if (array_key_exists('item',$params) && (! visible_activity($params['item']))) | ||||
| 			return; | ||||
|  | ||||
| 		$parent_mid = $params['parent_mid']; | ||||
| @@ -113,7 +127,7 @@ function notification($params) { | ||||
| 			dbesc($params['link']), | ||||
| 			intval($recip['channel_id']) | ||||
| 		); | ||||
| 		if($p) { | ||||
| 		if ($p) { | ||||
| 			logger('notification: comment already notified'); | ||||
| 			pop_lang(); | ||||
| 			return; | ||||
| @@ -194,14 +208,14 @@ function notification($params) { | ||||
| 		$itemlink =  $params['link']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_TAGSELF) { | ||||
| 	if ($params['type'] == NOTIFY_TAGSELF) { | ||||
|  | ||||
| 		$p = null; | ||||
| 		$p = q("select id from notify where link = '%s' and uid = %d limit 1", | ||||
| 			dbesc($params['link']), | ||||
| 			intval($recip['channel_id']) | ||||
| 		); | ||||
| 		if($p) { | ||||
| 		if ($p) { | ||||
| 			logger('enotify: tag: already notified about this post'); | ||||
| 			pop_lang(); | ||||
| 			return; | ||||
| @@ -220,8 +234,7 @@ function notification($params) { | ||||
| 		$itemlink =  $params['link']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_POKE) { | ||||
|  | ||||
| 	if ($params['type'] == NOTIFY_POKE) { | ||||
| 		$subject =	sprintf( t('[Red:Notify] %1$s poked you') , $sender['xchan_name']); | ||||
| 		$preamble = sprintf( t('%1$s, %2$s poked you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename); | ||||
| 		$epreamble = sprintf( t('%1$s, %2$s [zrl=%2$s]poked you[/zrl].') , | ||||
| @@ -239,7 +252,7 @@ function notification($params) { | ||||
| 		$itemlink =  $params['link']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_TAGSHARE) { | ||||
| 	if ($params['type'] == NOTIFY_TAGSHARE) { | ||||
| 		$subject =	sprintf( t('[Red:Notify] %s tagged your post') , $sender['xchan_name']); | ||||
| 		$preamble = sprintf( t('%1$s, %2$s tagged your post at %3$s') , $recip['channel_name'],$sender['xchan_name'], $sitename); | ||||
| 		$epreamble = sprintf( t('%1$s, %2$s tagged [zrl=%3$s]your post[/zrl]') , | ||||
| @@ -253,7 +266,7 @@ function notification($params) { | ||||
| 		$itemlink =  $params['link']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_INTRO) { | ||||
| 	if ($params['type'] == NOTIFY_INTRO) { | ||||
| 		$subject = sprintf( t('[Red:Notify] Introduction received')); | ||||
| 		$preamble = sprintf( t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);  | ||||
| 		$epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'), | ||||
| @@ -268,7 +281,7 @@ function notification($params) { | ||||
| 		$itemlink =  $params['link']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_SUGGEST) { | ||||
| 	if ($params['type'] == NOTIFY_SUGGEST) { | ||||
| 		$subject = sprintf( t('[Red:Notify] Friend suggestion received')); | ||||
| 		$preamble = sprintf( t('%1$s, you\'ve received a friend suggestion from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);  | ||||
| 		$epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a friend suggestion[/zrl] for %3$s from %4$s.'), | ||||
| @@ -287,12 +300,12 @@ function notification($params) { | ||||
| 		$itemlink =  $params['link']; | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_CONFIRM) { | ||||
|  | ||||
| 	if ($params['type'] == NOTIFY_CONFIRM) { | ||||
| 		// ? | ||||
| 	} | ||||
|  | ||||
| 	if($params['type'] == NOTIFY_SYSTEM) { | ||||
| 		 | ||||
| 	if ($params['type'] == NOTIFY_SYSTEM) { | ||||
| 		// ? | ||||
| 	} | ||||
|  | ||||
| 	$h = array( | ||||
| @@ -307,7 +320,7 @@ function notification($params) { | ||||
| 		'itemlink'  => $itemlink | ||||
| 	); | ||||
|  | ||||
| 	call_hooks('enotify',$h); | ||||
| 	call_hooks('enotify', $h); | ||||
|  | ||||
| 	$subject   = $h['subject']; | ||||
| 	$preamble  = $h['preamble']; | ||||
| @@ -324,11 +337,11 @@ function notification($params) { | ||||
| 	do { | ||||
| 		$dups = false; | ||||
| 		$hash = random_string(); | ||||
|         $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1", | ||||
| 		$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1", | ||||
| 			dbesc($hash)); | ||||
| 		if(count($r)) | ||||
| 		if (count($r)) | ||||
| 			$dups = true; | ||||
| 	} while($dups == true); | ||||
| 	} while ($dups === true); | ||||
|  | ||||
|  | ||||
| 	$datarray = array(); | ||||
| @@ -351,7 +364,7 @@ function notification($params) { | ||||
|  | ||||
| 	call_hooks('enotify_store', $datarray); | ||||
|  | ||||
| 	if($datarray['abort']) { | ||||
| 	if ($datarray['abort']) { | ||||
| 		pop_lang(); | ||||
| 		return; | ||||
| 	} | ||||
| @@ -365,8 +378,8 @@ function notification($params) { | ||||
| 	// So easiest solution to hide them from Notices is to mark them as seen right away. | ||||
| 	// Another option would be to not add them to the DB, and change how emails are handled (probably would be better that way) | ||||
| 	$always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices'); | ||||
| 	if(!$always_show_in_notices) { | ||||
| 		if(($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) { | ||||
| 	if (!$always_show_in_notices) { | ||||
| 		if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) { | ||||
| 			$seen = 1; | ||||
| 		} | ||||
| 	} | ||||
| @@ -392,9 +405,9 @@ function notification($params) { | ||||
| 		dbesc($hash), | ||||
| 		intval($recip['channel_id']) | ||||
| 	); | ||||
| 	if($r) | ||||
| 	if ($r) { | ||||
| 		$notify_id = $r[0]['id']; | ||||
| 	else { | ||||
| 	} else { | ||||
| 		logger('notification not found.'); | ||||
| 		pop_lang(); | ||||
| 		return; | ||||
| @@ -405,7 +418,7 @@ function notification($params) { | ||||
|  | ||||
| 	// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation | ||||
|  | ||||
| 	if(($a->language === 'en' || (! $a->language)) && strpos($msg,', ')) | ||||
| 	if (($a->language === 'en' || (! $a->language)) && strpos($msg,', ')) | ||||
| 		$msg = substr($msg,strpos($msg,', ')+1);	 | ||||
|  | ||||
| 	$r = q("update notify set msg = '%s' where id = %d and uid = %d", | ||||
| @@ -414,11 +427,10 @@ function notification($params) { | ||||
| 		intval($datarray['uid']) | ||||
| 	); | ||||
|  | ||||
|  | ||||
| 	// send email notification if notification preferences permit | ||||
|  | ||||
| 	require_once('bbcode.php'); | ||||
| 	if((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) { | ||||
| 	if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) { | ||||
|  | ||||
| 		logger('notification: sending notification email'); | ||||
|  | ||||
| @@ -429,8 +441,6 @@ function notification($params) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
|  | ||||
|  | ||||
| 		$textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8')); | ||||
|  | ||||
| 		$htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body))); | ||||
| @@ -450,7 +460,6 @@ function notification($params) { | ||||
| 		unset($_SESSION['zid_override']); | ||||
| 		unset($_SESSION['zrl_override']); | ||||
|  | ||||
|  | ||||
| 		$datarray = array(); | ||||
| 		$datarray['banner']       = $banner; | ||||
| 		$datarray['product']      = $product; | ||||
| @@ -485,13 +494,13 @@ function notification($params) { | ||||
|  | ||||
| 		$private_activity = false; | ||||
|  | ||||
| 		if(! $datarray['email_secure']) { | ||||
| 			switch($params['type']) { | ||||
| 		if (! $datarray['email_secure']) { | ||||
| 			switch ($params['type']) { | ||||
| 				case NOTIFY_WALL: | ||||
| 				case NOTIFY_TAGSELF: | ||||
| 				case NOTIFY_POKE: | ||||
| 				case NOTIFY_COMMENT: | ||||
| 					if(! $private) | ||||
| 					if (! $private) | ||||
| 						break; | ||||
| 					$private_activity = true; | ||||
| 				case NOTIFY_MAIL: | ||||
| @@ -503,8 +512,9 @@ function notification($params) { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if($private_activity  | ||||
| 			&& intval(get_pconfig($datarray['uid'],'system','ignore_private_notifications'))) { | ||||
| 		if ($private_activity | ||||
| 			&& intval(get_pconfig($datarray['uid'], 'system', 'ignore_private_notifications'))) { | ||||
|  | ||||
| 			pop_lang(); | ||||
| 			return; | ||||
| 		} | ||||
| @@ -525,13 +535,13 @@ function notification($params) { | ||||
| 			'$hitemlink'    => $datarray['hitemlink'], | ||||
| 			'$thanks'       => $datarray['thanks'], | ||||
| 			'$site_admin'   => $datarray['site_admin'], | ||||
| 			'$title'		=> $datarray['title'], | ||||
| 			'$htmlversion'	=> $datarray['htmlversion'],	 | ||||
| 			'$title'        => $datarray['title'], | ||||
| 			'$htmlversion'  => $datarray['htmlversion'], | ||||
| 		)); | ||||
|  | ||||
| 		// load the template for private message notifications | ||||
| 		$tpl = get_markup_template('email_notify_text.tpl'); | ||||
| 		$email_text_body = replace_macros($tpl,array( | ||||
| 		$email_text_body = replace_macros($tpl, array( | ||||
| 			'$banner'       => $datarray['banner'], | ||||
| 			'$product'      => $datarray['product'], | ||||
| 			'$preamble'     => $datarray['preamble'], | ||||
| @@ -545,8 +555,8 @@ function notification($params) { | ||||
| 			'$titemlink'    => $datarray['titemlink'], | ||||
| 			'$thanks'       => $datarray['thanks'], | ||||
| 			'$site_admin'   => $datarray['site_admin'], | ||||
| 			'$title'		=> $datarray['title'], | ||||
| 			'$textversion'	=> $datarray['textversion'],	 | ||||
| 			'$title'        => $datarray['title'], | ||||
| 			'$textversion'  => $datarray['textversion'], | ||||
| 		)); | ||||
|  | ||||
| //		logger('text: ' . $email_text_body); | ||||
| @@ -570,18 +580,24 @@ function notification($params) { | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief A class for sending email notifications. | ||||
|  * | ||||
|  * @fixme Class names start mostly with capital letter to distinguish them easier. | ||||
|  */ | ||||
| class enotify { | ||||
| 	/** | ||||
| 	 * Send a multipart/alternative message with Text and HTML versions | ||||
| 	 * @brief Send a multipart/alternative message with Text and HTML versions. | ||||
| 	 * | ||||
| 	 * @param fromName			name of the sender | ||||
| 	 * @param fromEmail			email fo the sender | ||||
| 	 * @param replyTo			replyTo address to direct responses | ||||
| 	 * @param toEmail			destination email address | ||||
| 	 * @param messageSubject	subject of the message | ||||
| 	 * @param htmlVersion		html version of the message | ||||
| 	 * @param textVersion		text only version of the message | ||||
| 	 * @param additionalMailHeader	additions to the smtp mail header | ||||
| 	 * @param array $params an assoziative array with: | ||||
| 	 *  * \e string \b fromName        name of the sender | ||||
| 	 *  * \e string \b fromEmail       email of the sender | ||||
| 	 *  * \e string \b replyTo         replyTo address to direct responses | ||||
| 	 *  * \e string \b toEmail         destination email address | ||||
| 	 *  * \e string \b messageSubject  subject of the message | ||||
| 	 *  * \e string \b htmlVersion     html version of the message | ||||
| 	 *  * \e string \b textVersion     text only version of the message | ||||
| 	 *  * \e string \b additionalMailHeader  additions to the smtp mail header | ||||
| 	 */ | ||||
| 	static public function send($params) { | ||||
|  | ||||
| @@ -589,10 +605,10 @@ class enotify { | ||||
| 		$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8'); | ||||
|  | ||||
| 		// generate a mime boundary | ||||
| 		$mimeBoundary   =rand(0,9)."-" | ||||
| 				.rand(10000000000,9999999999)."-" | ||||
| 				.rand(10000000000,9999999999)."=:" | ||||
| 				.rand(10000,99999); | ||||
| 		$mimeBoundary = rand(0, 9) . "-" | ||||
| 				.rand(10000000000, 9999999999) . "-" | ||||
| 				.rand(10000000000, 9999999999) . "=:" | ||||
| 				.rand(10000, 99999); | ||||
|  | ||||
| 		// generate a multipart/alternative message header | ||||
| 		$messageHeader = | ||||
| @@ -603,8 +619,9 @@ class enotify { | ||||
| 			"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\""; | ||||
|  | ||||
| 		// assemble the final multipart message body with the text and html types included | ||||
| 		$textBody	=	chunk_split(base64_encode($params['textVersion'])); | ||||
| 		$htmlBody	=	chunk_split(base64_encode($params['htmlVersion'])); | ||||
| 		$textBody = chunk_split(base64_encode($params['textVersion'])); | ||||
| 		$htmlBody = chunk_split(base64_encode($params['htmlVersion'])); | ||||
|  | ||||
| 		$multipartMessageBody = | ||||
| 			"--" . $mimeBoundary . "\n" .					// plain text section | ||||
| 			"Content-Type: text/plain; charset=UTF-8\n" . | ||||
| @@ -618,12 +635,11 @@ class enotify { | ||||
|  | ||||
| 		// send the message | ||||
| 		$res = mail( | ||||
| 			$params['toEmail'],	 							// send to address | ||||
| 			$params['toEmail'],								// send to address | ||||
| 			$messageSubject,								// subject | ||||
| 			$multipartMessageBody,	 						// message body | ||||
| 			$multipartMessageBody,							// message body | ||||
| 			$messageHeader									// message headers | ||||
| 		); | ||||
| 		logger("notification: enotify::send returns " . $res, LOGGER_DEBUG); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,14 @@ | ||||
| <?php /** @file */ | ||||
|  | ||||
| <?php | ||||
| /** | ||||
|  * @file include/event.php | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @brief Returns an event as HTML | ||||
|  * | ||||
|  * @param array $ev | ||||
|  * @return string | ||||
|  */ | ||||
| function format_event_html($ev) { | ||||
|  | ||||
| 	require_once('include/bbcode.php'); | ||||
| @@ -12,13 +20,12 @@ function format_event_html($ev) { | ||||
|  | ||||
| 	$o = '<div class="vevent">' . "\r\n"; | ||||
|  | ||||
|  | ||||
| 	$o .= '<p class="summary event-summary">' . bbcode($ev['summary']) .  '</p>' . "\r\n"; | ||||
|  | ||||
| 	$o .= '<p class="description event-description">' . bbcode($ev['description']) .  '</p>' . "\r\n"; | ||||
|  | ||||
| 	$o .= '<p class="event-start">' . t('Starts:') . ' <abbr class="dtstart" title="' | ||||
| 		. datetime_convert('UTC','UTC',$ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )) | ||||
| 		. datetime_convert('UTC', 'UTC', $ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )) | ||||
| 		. '" >'  | ||||
| 		. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),  | ||||
| 			$ev['start'] , $bd_format )) | ||||
| @@ -42,11 +49,11 @@ function format_event_html($ev) { | ||||
| 			. '</span></p>' . "\r\n"; | ||||
|  | ||||
| 	$o .= '</div>' . "\r\n"; | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| function ical_wrapper($ev) { | ||||
|  | ||||
| 	if(! ((is_array($ev)) && count($ev))) | ||||
| @@ -56,7 +63,7 @@ function ical_wrapper($ev) { | ||||
| 	$o .= "\nVERSION:2.0"; | ||||
| 	$o .= "\nMETHOD:PUBLISH"; | ||||
| 	$o .= "\nPRODID:-//" . get_config('system','sitename') . "//" . RED_PLATFORM . "//" . strtoupper(get_app()->language). "\n"; | ||||
| 	if(array_key_exists('start',$ev)) | ||||
| 	if(array_key_exists('start', $ev)) | ||||
| 		$o .= format_event_ical($ev); | ||||
| 	else { | ||||
| 		foreach($ev as $e) { | ||||
| @@ -84,13 +91,15 @@ function format_event_ical($ev) { | ||||
| 	if($ev['description'])  | ||||
| 		$o .= "\nDESCRIPTION:" . format_ical_text($ev['description']); | ||||
| 	$o .= "\nEND:VEVENT\n"; | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
| function format_ical_text($s) { | ||||
|  | ||||
| function format_ical_text($s) { | ||||
| 	require_once('include/bbcode.php'); | ||||
| 	require_once('include/html2plain.php'); | ||||
|  | ||||
| 	return(wordwrap(html2plain(bbcode($s)),72,"\n ",true)); | ||||
| } | ||||
|  | ||||
| @@ -117,16 +126,16 @@ function format_event_bbcode($ev) { | ||||
| 	if($ev['adjust']) | ||||
| 		$o .= '[event-adjust]' . $ev['adjust'] . '[/event-adjust]'; | ||||
|  | ||||
|  | ||||
| 	return $o; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| function bbtovcal($s) { | ||||
| 	$o = ''; | ||||
| 	$ev = bbtoevent($s); | ||||
| 	if($ev['description']) | ||||
| 		$o = format_event_html($ev); | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
| @@ -154,27 +163,41 @@ function bbtoevent($s) { | ||||
| 	if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match)) | ||||
| 		$ev['adjust'] = $match[1]; | ||||
| 	$ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); | ||||
| 	return $ev; | ||||
|  | ||||
| 	return $ev; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Sorts the given array of events by date. | ||||
|  * | ||||
|  * @see ev_compare() | ||||
|  * @param array $arr | ||||
|  * @return sorted array | ||||
|  */ | ||||
| function sort_by_date($arr) { | ||||
| 	if(is_array($arr)) | ||||
| 		usort($arr,'ev_compare'); | ||||
| 	if (is_array($arr)) | ||||
| 		usort($arr, 'ev_compare'); | ||||
|  | ||||
| 	return $arr; | ||||
| } | ||||
|  | ||||
|  | ||||
| function ev_compare($a,$b) { | ||||
| /** | ||||
|  * @brief Compare function for events. | ||||
|  * | ||||
|  * @see sort_by_date() | ||||
|  * @param array $a | ||||
|  * @param array $b | ||||
|  * @return number return values like strcmp() | ||||
|  */ | ||||
| function ev_compare($a, $b) { | ||||
|  | ||||
| 	$date_a = (($a['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$a['start']) : $a['start']); | ||||
| 	$date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']); | ||||
|  | ||||
| 	if($date_a === $date_b) | ||||
| 		return strcasecmp($a['description'],$b['description']); | ||||
| 	if ($date_a === $date_b) | ||||
| 		return strcasecmp($a['description'], $b['description']); | ||||
|  | ||||
| 	return strcmp($date_a,$date_b); | ||||
| 	return strcmp($date_a, $date_b); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -185,8 +208,6 @@ function event_store_event($arr) { | ||||
| 	$arr['type']        = (($arr['type'])        ? $arr['type']        : 'event' ); | ||||
| 	$arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : ''); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	// Existing event being modified | ||||
|  | ||||
| 	if($arr['id'] || $arr['event_hash']) { | ||||
| @@ -206,7 +227,6 @@ function event_store_event($arr) { | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		if(! $r) | ||||
| 			return false; | ||||
|  | ||||
| @@ -251,14 +271,12 @@ function event_store_event($arr) { | ||||
| 			intval($r[0]['id']), | ||||
| 			intval($arr['uid']) | ||||
| 		); | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
|  | ||||
| 		// New event. Store it. | ||||
|  | ||||
| 		$hash = random_string(); | ||||
|  | ||||
|  | ||||
| 		$r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type, | ||||
| 			adjust,nofinish,allow_cid,allow_gid,deny_cid,deny_gid) | ||||
| 			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' ) ", | ||||
| @@ -280,7 +298,6 @@ function event_store_event($arr) { | ||||
| 			dbesc($arr['allow_gid']), | ||||
| 			dbesc($arr['deny_cid']), | ||||
| 			dbesc($arr['deny_gid']) | ||||
|  | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| @@ -292,7 +309,6 @@ function event_store_event($arr) { | ||||
| 		return $r[0]; | ||||
|  | ||||
| 	return false; | ||||
|  | ||||
| } | ||||
|  | ||||
| function event_addtocal($item_id, $uid) { | ||||
| @@ -339,22 +355,21 @@ function event_addtocal($item_id, $uid) { | ||||
| 				intval($item['id']), | ||||
| 				intval($channel['channel_id']) | ||||
| 			); | ||||
|  | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| function event_store_item($arr,$event) { | ||||
| function event_store_item($arr, $event) { | ||||
|  | ||||
| 	require_once('include/datetime.php'); | ||||
| 	require_once('include/items.php'); | ||||
| 	require_once('include/bbcode.php'); | ||||
|  | ||||
| 	$a = get_app(); | ||||
|  | ||||
| 	$item = null; | ||||
|  | ||||
| 	if($arr['mid'] && $arr['uid']) { | ||||
| @@ -370,11 +385,11 @@ function event_store_item($arr,$event) { | ||||
|  | ||||
| 	$item_arr = array(); | ||||
| 	$prefix = ''; | ||||
| 	$birthday = false; | ||||
| //	$birthday = false; | ||||
|  | ||||
| 	if($event['type'] === 'birthday') { | ||||
| 		$prefix =  t('This event has been added to your calendar.'); | ||||
| 		$birthday = true; | ||||
| //		$birthday = true; | ||||
|  | ||||
| 		// The event is created on your own site by the system, but appears to belong  | ||||
| 		// to the birthday person. It also isn't propagated - so we need to prevent | ||||
| @@ -386,12 +401,12 @@ function event_store_item($arr,$event) { | ||||
| 	} | ||||
|  | ||||
| 	$r = q("SELECT * FROM item left join xchan on author_xchan = xchan_hash WHERE resource_id = '%s' AND resource_type = 'event' and uid = %d LIMIT 1", | ||||
|         dbesc($event['event_hash']), | ||||
| 		dbesc($event['event_hash']), | ||||
| 		intval($arr['uid']) | ||||
| 	); | ||||
|  | ||||
| 	if($r) { | ||||
| 		$obj = json_encode(array( | ||||
| 		$object = json_encode(array( | ||||
| 			'type'    => ACTIVITY_OBJ_EVENT, | ||||
| 			'id'      => z_root() . '/event/' . $r[0]['resource_id'], | ||||
| 			'title'   => $arr['summary'], | ||||
| @@ -424,8 +439,7 @@ function event_store_item($arr,$event) { | ||||
| 			intval($arr['uid']) | ||||
| 		); | ||||
|  | ||||
|  | ||||
| 		$s = q("delete from term where oid = %d and otype = %d", | ||||
| 		q("delete from term where oid = %d and otype = %d", | ||||
| 			intval($r[0]['id']), | ||||
| 			intval(TERM_OBJ_POST) | ||||
| 		); | ||||
| @@ -446,18 +460,16 @@ function event_store_item($arr,$event) { | ||||
|  | ||||
| 		$item_id = $r[0]['id']; | ||||
| 		call_hooks('event_updated', $event['id']); | ||||
|  | ||||
| 		return $item_id; | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
|  | ||||
| 		$z = q("select * from channel where channel_id = %d limit 1", | ||||
| 			intval($arr['uid']) | ||||
| 		); | ||||
|  | ||||
|  | ||||
| 		$private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0); | ||||
|  | ||||
|  | ||||
| 		if($item) { | ||||
| 			$item_arr['id'] = $item['id']; | ||||
| 		} | ||||
| @@ -469,8 +481,7 @@ function event_store_item($arr,$event) { | ||||
| 				$item_flags |= ITEM_WALL; | ||||
| 				$item_flags |= ITEM_ORIGIN; | ||||
| 			} | ||||
| 			$item_arr['item_flags']    = $item_flags; | ||||
|  | ||||
| 			$item_arr['item_flags'] = $item_flags; | ||||
| 		} | ||||
|  | ||||
| 		if(! $arr['mid']) | ||||
| @@ -482,7 +493,6 @@ function event_store_item($arr,$event) { | ||||
| 		$item_arr['mid']           = $arr['mid']; | ||||
| 		$item_arr['parent_mid']    = $arr['mid']; | ||||
|  | ||||
|  | ||||
| 		$item_arr['owner_xchan']   = (($wall) ? $z[0]['channel_hash'] : $arr['event_xchan']); | ||||
| 		$item_arr['author_xchan']  = $arr['event_xchan']; | ||||
| 		$item_arr['title']         = $arr['summary']; | ||||
| @@ -493,8 +503,7 @@ function event_store_item($arr,$event) { | ||||
| 		$item_arr['item_private']  = $private; | ||||
| 		$item_arr['verb']          = ACTIVITY_POST; | ||||
|  | ||||
|  | ||||
| 		if(array_key_exists('term',$arr)) | ||||
| 		if(array_key_exists('term', $arr)) | ||||
| 			$item_arr['term'] = $arr['term']; | ||||
|  | ||||
| 		$item_arr['resource_type'] = 'event'; | ||||
| @@ -512,15 +521,13 @@ function event_store_item($arr,$event) { | ||||
| 		else | ||||
| 			$item_arr['plink'] = z_root() . '/display/' . $item_arr['mid']; | ||||
|  | ||||
|  | ||||
| 		$x = q("select * from xchan where xchan_hash = '%s' limit 1", | ||||
| 				dbesc($arr['event_xchan']) | ||||
| 		); | ||||
| 		if($x) { | ||||
|  | ||||
| 			$item_arr['object'] = json_encode(array( | ||||
| 				'type'    => ACTIVITY_OBJ_EVENT, | ||||
| 				'id'      => z_root() . '/event/' . $hash, | ||||
| 				'id'      => z_root() . '/event/' . $event['event_hash'], | ||||
| 				'title'   => $arr['summary'], | ||||
| 				'content' => format_event_bbcode($arr), | ||||
| 				'author'  => array( | ||||
| @@ -539,7 +546,7 @@ function event_store_item($arr,$event) { | ||||
|  | ||||
| 		$item_id = $res['item_id']; | ||||
|  | ||||
| 		call_hooks("event_created", $event['id']); | ||||
| 		call_hooks('event_created', $event['id']); | ||||
|  | ||||
| 		return $item_id; | ||||
| 	} | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/expire.php | ||||
|  */ | ||||
|  | ||||
| require_once('boot.php'); | ||||
| require_once('include/cli_startup.php'); | ||||
| @@ -7,7 +10,6 @@ function expire_run($argv, $argc){ | ||||
|  | ||||
| 	cli_startup(); | ||||
|  | ||||
|  | ||||
| 	// perform final cleanup on previously delete items | ||||
|  | ||||
| 	$r = q("select id from item where (item_restrict & %d) > 0 and (item_restrict & %d) = 0 | ||||
| @@ -16,23 +18,23 @@ function expire_run($argv, $argc){ | ||||
| 		intval(ITEM_PENDING_REMOVE), | ||||
| 		db_utcnow(), db_quoteinterval('10 DAY') | ||||
| 	); | ||||
| 	if($r) { | ||||
| 		foreach($r as $rr) { | ||||
| 			drop_item($rr['id'],false,DROPITEM_PHASE2); | ||||
| 	if ($r) { | ||||
| 		foreach ($r as $rr) { | ||||
| 			drop_item($rr['id'], false, DROPITEM_PHASE2); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// physically remove anything that has been deleted for more than two months | ||||
| 	// FIXME - this is a wretchedly inefficient query | ||||
| 	/** @FIXME - this is a wretchedly inefficient query */ | ||||
|  | ||||
| 	$r = q("delete from item where ( item_restrict & %d ) > 0 and changed < %s - INTERVAL %s", | ||||
| 		intval(ITEM_PENDING_REMOVE), | ||||
| 		db_utcnow(), db_quoteinterval('36 DAY') | ||||
| 	); | ||||
|  | ||||
| 	// make this optional as it could have a performance impact on large sites | ||||
| 	/** @FIXME make this optional as it could have a performance impact on large sites */ | ||||
|  | ||||
| 	if(intval(get_config('system','optimize_items'))) | ||||
| 	if (intval(get_config('system', 'optimize_items'))) | ||||
| 		q("optimize table item"); | ||||
|  | ||||
| 	logger('expire: start', LOGGER_DEBUG); | ||||
| @@ -43,26 +45,25 @@ function expire_run($argv, $argc){ | ||||
|  | ||||
| 	$r = q("SELECT channel_id, channel_address, channel_pageflags, channel_expire_days from channel where true"); | ||||
|  | ||||
| 	if($r) { | ||||
| 		foreach($r as $rr) { | ||||
| 	if ($r) { | ||||
| 		foreach ($r as $rr) { | ||||
|  | ||||
| 			// expire the sys channel separately | ||||
| 			if($rr['channel_pageflags'] & PAGE_SYSTEM) | ||||
| 			if ($rr['channel_pageflags'] & PAGE_SYSTEM) | ||||
| 				continue; | ||||
|  | ||||
| 			// service class default (if non-zero) over-rides the site default | ||||
|  | ||||
| 			$service_class_expire = service_class_fetch($rr['channel_id'],'expire_days'); | ||||
| 			if(intval($service_class_expire)) | ||||
| 			$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days'); | ||||
| 			if (intval($service_class_expire)) | ||||
| 				$channel_expire = $service_class_expire; | ||||
| 			else | ||||
| 				$channel_expire = $site_expire; | ||||
|  | ||||
| 			if(intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) || | ||||
| 			if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) || | ||||
| 				intval($rr['channel_expire_days'] == 0)) { | ||||
| 				$expire_days = $channel_expire; | ||||
| 			} | ||||
| 			else { | ||||
| 			} else { | ||||
| 				$expire_days = $rr['channel_expire_days']; | ||||
| 			} | ||||
|  | ||||
| @@ -72,34 +73,30 @@ function expire_run($argv, $argc){ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	$x = get_sys_channel(); | ||||
| 	if($x) { | ||||
| 	if ($x) { | ||||
|  | ||||
| 		// this should probably just fetch the channel_expire_days from the sys channel, | ||||
| 		// but there's no convenient way to set it. | ||||
|  | ||||
| 		$expire_days = get_config('system','sys_expire_days'); | ||||
| 		if($expire_days === false) | ||||
| 		$expire_days = get_config('system', 'sys_expire_days'); | ||||
| 		if ($expire_days === false) | ||||
| 			$expire_days = 30; | ||||
|  | ||||
| 		if(intval($site_expire) && (intval($site_expire) < intval($expire_days))) { | ||||
| 		if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) { | ||||
| 			$expire_days = $site_expire; | ||||
| 		} | ||||
|  | ||||
| 		logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG); | ||||
|  | ||||
| 		if($expire_days) | ||||
| 			item_expire($x['channel_id'],$expire_days); | ||||
| 		if ($expire_days) | ||||
| 			item_expire($x['channel_id'], $expire_days); | ||||
|  | ||||
| 		logger('Expire: sys: done', LOGGER_DEBUG); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| if (array_search(__file__,get_included_files())===0){ | ||||
|   expire_run($argv,$argc); | ||||
|   killme(); | ||||
| if (array_search(__file__, get_included_files()) === 0){ | ||||
| 	expire_run($argv, $argc); | ||||
| 	killme(); | ||||
| } | ||||
|   | ||||
| @@ -1,26 +1,28 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/identity.php | ||||
|  */ | ||||
|  | ||||
| require_once('include/zot.php'); | ||||
| require_once('include/crypto.php'); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function identity_check_service_class($account_id) | ||||
|  *     Called when creating a new channel. Checks the account's service class and number | ||||
|  * of current channels to determine whether creating a new channel is within the current | ||||
|  * service class constraints. | ||||
|  * @brief Called when creating a new channel. | ||||
|  * | ||||
|  * Checks the account's service class and number of current channels to determine | ||||
|  * whether creating a new channel is within the current service class constraints. | ||||
|  * | ||||
|  * @param int $account_id | ||||
|  *     Account_id used for this request | ||||
|  * | ||||
|  * @returns array | ||||
|  *       'success' => boolean true if creating a new channel is allowed for this account | ||||
|  *       'message' => if success is false, optional error text | ||||
|  * @returns assoziative array with: | ||||
|  *  * \e boolean \b success boolean true if creating a new channel is allowed for this account | ||||
|  *  * \e string \b message (optional) if success is false, optional error text | ||||
|  *  * \e int \b total_identities | ||||
|  */ | ||||
|   | ||||
|  | ||||
| function identity_check_service_class($account_id) { | ||||
| 	$ret = array('success' => false, $message => ''); | ||||
| 	$ret = array('success' => false, 'message' => ''); | ||||
|  | ||||
| 	$r = q("select count(channel_id) as total from channel where channel_account_id = %d and not ( channel_pageflags & %d )>0 ", | ||||
| 		intval($account_id), | ||||
| @@ -34,64 +36,63 @@ function identity_check_service_class($account_id) { | ||||
|  | ||||
| 	$ret['total_identities'] = intval($r[0]['total']); | ||||
|  | ||||
| 	if(! account_service_class_allows($account_id,'total_identities',$r[0]['total'])) { | ||||
| 		$result['message'] .= upgrade_message(); | ||||
| 		return $result; | ||||
| 	if (! account_service_class_allows($account_id, 'total_identities', $r[0]['total'])) { | ||||
| 		$ret['message'] .= upgrade_message(); | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	$ret['success'] = true; | ||||
|  | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function validate_channelname($name) | ||||
|  *     Determine if the channel name is allowed when creating a new channel. | ||||
|  * @brief Determine if the channel name is allowed when creating a new channel. | ||||
|  * | ||||
|  * This action is pluggable. | ||||
|  * We're currently only checking for an empty name or one that exceeds our | ||||
|  * storage limit (255 chars). 255 chars is probably going to create a mess on | ||||
|  * some pages. | ||||
|  * Plugins can set additional policies such as full name requirements, character | ||||
|  * sets, multi-byte length, etc. | ||||
|  * | ||||
|  * @param string $name | ||||
|  * | ||||
|  * @returns nil return if name is valid, or string describing the error state. | ||||
|  * | ||||
|  * We're currently only checking for an empty name or one that exceeds our storage limit (255 chars). | ||||
|  * 255 chars is probably going to create a mess on some pages.  | ||||
|  * Plugins can set additional policies such as full name requirements, character sets, multi-byte | ||||
|  * length, etc.  | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| function validate_channelname($name) { | ||||
|  | ||||
| 	if(! $name) | ||||
| 	if (! $name) | ||||
| 		return t('Empty name'); | ||||
| 	if(strlen($name) > 255) | ||||
|  | ||||
| 	if (strlen($name) > 255) | ||||
| 		return t('Name too long'); | ||||
|  | ||||
| 	$arr = array('name' => $name); | ||||
| 	call_hooks('validate_channelname',$arr); | ||||
| 	if(x($arr,'message')) | ||||
| 	call_hooks('validate_channelname', $arr); | ||||
|  | ||||
| 	if (x($arr, 'message')) | ||||
| 		return $arr['message']; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function create_sys_channel() | ||||
|  *     Create a system channel - which has no account attached | ||||
|  * @brief Create a system channel - which has no account attached. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| function create_sys_channel() { | ||||
| 	if(get_sys_channel()) | ||||
| 	if (get_sys_channel()) | ||||
| 		return; | ||||
|  | ||||
|     // Ensure that there is a host keypair. | ||||
| 	// Ensure that there is a host keypair. | ||||
|  | ||||
|     if((! get_config('system','pubkey')) && (! get_config('system','prvkey'))) { | ||||
| 	if ((! get_config('system', 'pubkey')) && (! get_config('system', 'prvkey'))) { | ||||
| 		require_once('include/crypto.php'); | ||||
|         $hostkey = new_keypair(4096); | ||||
|         set_config('system','pubkey',$hostkey['pubkey']); | ||||
|         set_config('system','prvkey',$hostkey['prvkey']); | ||||
|     } | ||||
| 		$hostkey = new_keypair(4096); | ||||
| 		set_config('system', 'pubkey', $hostkey['pubkey']); | ||||
| 		set_config('system', 'prvkey', $hostkey['prvkey']); | ||||
| 	} | ||||
|  | ||||
| 	create_identity(array( | ||||
| 		'account_id' => 'xxx',  // This will create an identity with an (integer) account_id of 0, but account_id is required | ||||
| @@ -103,63 +104,79 @@ function create_sys_channel() { | ||||
| 	)); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Returns the sys channel. | ||||
|  * | ||||
|  * @return array|boolean | ||||
|  */ | ||||
| function get_sys_channel() { | ||||
| 	$r = q("select * from channel left join xchan on channel_hash = xchan_hash where (channel_pageflags & %d)>0 limit 1", | ||||
| 		intval(PAGE_SYSTEM) | ||||
| 	); | ||||
| 	if($r) | ||||
| 		return $r[0]; | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| function is_sys_channel($channel_id) { | ||||
| 	$r = q("select channel_pageflags from channel where channel_id = %d limit 1", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
| 	if(($r) && ($r[0]['channel_pageflags'] & PAGE_SYSTEM)) | ||||
| 		return true; | ||||
| 	if ($r) | ||||
| 		return $r[0]; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @channel_total() | ||||
|  *   Return the total number of channels on this site. No filtering is performed except to check PAGE_REMOVED | ||||
|  * | ||||
|  * @returns int  | ||||
|  *   on error returns boolean false | ||||
|  * @brief Checks if $channel_id is sys channel. | ||||
|  * | ||||
|  * @param int $channel_id | ||||
|  * @return boolean | ||||
|  */ | ||||
| function is_sys_channel($channel_id) { | ||||
| 	$r = q("select channel_pageflags from channel where channel_id = %d limit 1", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
|  | ||||
| 	if (($r) && ($r[0]['channel_pageflags'] & PAGE_SYSTEM)) | ||||
| 		return true; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Return the total number of channels on this site. | ||||
|  * | ||||
|  * No filtering is performed except to check PAGE_REMOVED. | ||||
|  * | ||||
|  * @returns int|booleean | ||||
|  *   on error returns boolean false | ||||
|  */ | ||||
| function channel_total() { | ||||
| 	$r = q("select channel_id from channel where not ( channel_pageflags & %d )>0", | ||||
| 		intval(PAGE_REMOVED) | ||||
| 	); | ||||
|  | ||||
| 	if(is_array($r)) | ||||
| 	if (is_array($r)) | ||||
| 		return count($r); | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function create_identity($arr) | ||||
|  *     Create a new channel | ||||
|  * Also creates the related xchan, hubloc, profile, and "self" abook records, and an  | ||||
|  * empty "Friends" group/collection for the new channel | ||||
|  * @brief Create a new channel. | ||||
|  * | ||||
|  * @param array $arr | ||||
|  *       'name'       => full name of channel | ||||
|  *       'nickname'   => "email/url-compliant" nickname | ||||
|  *       'account_id' => account_id to attach with this channel | ||||
|  *       [other identity fields as desired] | ||||
|  * Also creates the related xchan, hubloc, profile, and "self" abook records, | ||||
|  * and an empty "Friends" group/collection for the new channel. | ||||
|  * | ||||
|  * @param array $arr assoziative array with: | ||||
|  *  * \e string \b name full name of channel | ||||
|  *  * \e string \b nickname "email/url-compliant" nickname | ||||
|  *  * \e int \b account_id to attach with this channel | ||||
|  *  * [other identity fields as desired] | ||||
|  * | ||||
|  * @returns array | ||||
|  *     'success' => boolean true or false | ||||
|  *     'message' => optional error text if success is false | ||||
|  *     'channel' => if successful the created channel array | ||||
|  */ | ||||
|   | ||||
| function create_identity($arr) { | ||||
|  | ||||
| 	$a = get_app(); | ||||
| @@ -176,7 +193,6 @@ function create_identity($arr) { | ||||
| 	// save this for auto_friending | ||||
| 	$total_identities = $ret['total_identities']; | ||||
|  | ||||
|  | ||||
| 	$nick = mb_strtolower(trim($arr['nickname'])); | ||||
| 	if(! $nick) { | ||||
| 		$ret['message'] = t('Nickname is required.'); | ||||
| @@ -205,7 +221,6 @@ function create_identity($arr) { | ||||
| 	$guid = zot_new_uid($nick); | ||||
| 	$key = new_keypair(4096); | ||||
|  | ||||
|  | ||||
| 	$sig = base64url_encode(rsa_sign($guid,$key['prvkey'])); | ||||
| 	$hash = make_xchan_hash($guid,$sig); | ||||
|  | ||||
| @@ -221,9 +236,6 @@ function create_identity($arr) { | ||||
| 	if(array_key_exists('primary', $arr)) | ||||
| 		$primary = intval($arr['primary']); | ||||
|  | ||||
|  | ||||
| 	$perms_sql = ''; | ||||
|  | ||||
| 	$role_permissions = null; | ||||
| 	$global_perms = get_perms(); | ||||
|  | ||||
| @@ -270,7 +282,6 @@ function create_identity($arr) { | ||||
| 		dbesc($a->timezone) | ||||
| 	); | ||||
|  | ||||
|  | ||||
| 	$r = q("select * from channel where channel_account_id = %d  | ||||
| 		and channel_guid = '%s' limit 1", | ||||
| 		intval($arr['account_id']), | ||||
| @@ -307,7 +318,6 @@ function create_identity($arr) { | ||||
| 	if(! $r) | ||||
| 		logger('create_identity: Unable to store hub location'); | ||||
|  | ||||
|  | ||||
| 	$newuid = $ret['channel']['channel_id']; | ||||
|  | ||||
| 	$r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", | ||||
| @@ -332,7 +342,6 @@ function create_identity($arr) { | ||||
| 	// Not checking return value. | ||||
| 	// It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate | ||||
|  | ||||
|  | ||||
| 	$r = q("INSERT INTO profile ( aid, uid, profile_guid, profile_name, is_default, publish, name, photo, thumb) | ||||
| 		VALUES ( %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s') ", | ||||
| 		intval($ret['channel']['channel_account_id']), | ||||
| @@ -424,31 +433,25 @@ function create_identity($arr) { | ||||
|  | ||||
| 	$ret['success'] = true; | ||||
| 	return $ret; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function set_default_login_identity($account_id, $channel_id, $force = true) | ||||
|  *       Set default channel to be used on login | ||||
|  * @brief Set default channel to be used on login. | ||||
|  * | ||||
|  * @param int $account_id | ||||
|  *       login account | ||||
|  * @param int $channel_id | ||||
|  *       channel id to set as default for this account | ||||
|  * @param boolean force | ||||
|  * @param boolean $force | ||||
|  *       if true, set this default unconditionally | ||||
|  *       if $force is false only do this if there is no existing default | ||||
|  *  | ||||
|  * @returns nil | ||||
|  */ | ||||
|  | ||||
| function set_default_login_identity($account_id,$channel_id,$force = true) { | ||||
| function set_default_login_identity($account_id, $channel_id, $force = true) { | ||||
| 	$r = q("select account_default_channel from account where account_id = %d limit 1", | ||||
| 		intval($account_id) | ||||
| 	); | ||||
| 	if($r) { | ||||
| 		if((intval($r[0]['account_default_channel']) == 0) || ($force)) { | ||||
| 	if ($r) { | ||||
| 		if ((intval($r[0]['account_default_channel']) == 0) || ($force)) { | ||||
| 			$r = q("update account set account_default_channel = %d where account_id = %d", | ||||
| 				intval($channel_id), | ||||
| 				intval($account_id) | ||||
| @@ -458,8 +461,7 @@ function set_default_login_identity($account_id,$channel_id,$force = true) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function identity_basic_export($channel_id,$items = false) | ||||
|  *     Create an array representing the important channel information | ||||
|  * @brief Create an array representing the important channel information | ||||
|  * which would be necessary to create a nomadic identity clone. This includes | ||||
|  * most channel resources and connection information with the exception of content. | ||||
|  * | ||||
| @@ -470,9 +472,7 @@ function set_default_login_identity($account_id,$channel_id,$force = true) { | ||||
|  * | ||||
|  * @returns array | ||||
|  *     See function for details | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| function identity_basic_export($channel_id, $items = false) { | ||||
|  | ||||
| 	/* | ||||
| @@ -536,7 +536,6 @@ function identity_basic_export($channel_id, $items = false) { | ||||
| 	if($r) | ||||
| 		$ret['config'] = $r; | ||||
|  | ||||
|  | ||||
| 	$r = q("select type, data from photo where scale = 4 and profile = 1 and uid = %d limit 1", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
| @@ -563,11 +562,9 @@ function identity_basic_export($channel_id, $items = false) { | ||||
| 	if($r) | ||||
| 		$ret['obj'] = $r; | ||||
|  | ||||
|  | ||||
| 	if(! $items) | ||||
| 		return $ret; | ||||
|  | ||||
|  | ||||
| 	$r = q("select likes.*, item.mid from likes left join item on likes.iid = item.id where likes.channel_id = %d", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
| @@ -575,7 +572,6 @@ function identity_basic_export($channel_id, $items = false) { | ||||
| 	if($r) | ||||
| 		$ret['likes'] = $r; | ||||
|  | ||||
|  | ||||
| 	$r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
| @@ -583,9 +579,9 @@ function identity_basic_export($channel_id, $items = false) { | ||||
| 	if($r) | ||||
| 		$ret['item_id'] = $r; | ||||
|  | ||||
| 	$key = get_config('system','prvkey'); | ||||
| 	//$key = get_config('system','prvkey'); | ||||
|  | ||||
| 	// warning: this may run into memory limits on smaller systems | ||||
| 	/** @warning this may run into memory limits on smaller systems */ | ||||
|  | ||||
| 	$r = q("select * from item where (item_flags & %d)>0 and not (item_restrict & %d)>0 and uid = %d", | ||||
| 		intval(ITEM_WALL), | ||||
| @@ -598,25 +594,17 @@ function identity_basic_export($channel_id, $items = false) { | ||||
| 		$r = fetch_post_tags($r,true); | ||||
| 		foreach($r as $rr) | ||||
| 			$ret['item'][] = encode_item($rr,true); | ||||
|  | ||||
| 	} | ||||
| 	return $ret; | ||||
|  | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Loads a profile into the App structure. | ||||
|  * | ||||
|  * @function : profile_load(&$a, $nickname, $profile) | ||||
|  *     Generate | ||||
|  * @param App $a | ||||
|  * @param string $nickname | ||||
|  * @param string $profile | ||||
|  * | ||||
|  * Summary: Loads a profile into the App structure. | ||||
|  * The function requires a writeable copy of the main App structure, and the nickname | ||||
|  * of a valid channel. | ||||
|  * The function requires a writeable copy of the main App structure, and the | ||||
|  * nickname of a valid channel. | ||||
|  * | ||||
|  * Permissions of the current observer are checked. If a restricted profile is available | ||||
|  * to the current observer, that will be loaded instead of the channel default profile. | ||||
| @@ -625,9 +613,10 @@ function identity_basic_export($channel_id, $items = false) { | ||||
|  * | ||||
|  * The channel default theme is also selected for use, unless over-riden elsewhere. | ||||
|  * | ||||
|  * @param[in,out] App &$a | ||||
|  * @param string $nickname | ||||
|  * @param string $profile | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function profile_load(&$a, $nickname, $profile = '') { | ||||
|  | ||||
| 	logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : '')); | ||||
| @@ -683,7 +672,6 @@ function profile_load(&$a, $nickname, $profile = '') { | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	if(! $p) { | ||||
| 		logger('profile error: ' . $a->query_string, LOGGER_DEBUG); | ||||
| 		notice( t('Requested profile is not available.') . EOL ); | ||||
| @@ -733,6 +721,7 @@ function profile_load(&$a, $nickname, $profile = '') { | ||||
| 	// fetch user tags if this isn't the default profile | ||||
|  | ||||
| 	if(! $p[0]['is_default']) { | ||||
| 		/** @BUG $profile_uid is undefinded for this query, so should not work. */ | ||||
| 		$x = q("select `keywords` from `profile` where uid = %d and `is_default` = 1 limit 1", | ||||
| 				intval($profile_uid) | ||||
| 		); | ||||
| @@ -744,7 +733,6 @@ function profile_load(&$a, $nickname, $profile = '') { | ||||
| 		$keywords = str_replace(array('#',',',' ',',,'),array('',' ',',',','),$p[0]['keywords']); | ||||
| 		if(strlen($keywords) && $can_view_profile) | ||||
| 			$a->page['htmlhead'] .= '<meta name="keywords" content="' . htmlentities($keywords,ENT_COMPAT,'UTF-8') . '" />' . "\r\n" ; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	$a->profile = $p[0]; | ||||
| @@ -756,7 +744,6 @@ function profile_load(&$a, $nickname, $profile = '') { | ||||
| 	if($can_view_profile) { | ||||
| 		$online = get_online_status($nickname); | ||||
| 		$a->profile['online_status'] = $online['result']; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	if(local_channel()) { | ||||
| @@ -764,7 +751,7 @@ function profile_load(&$a, $nickname, $profile = '') { | ||||
| 		$_SESSION['mobile_theme'] = $a->profile['channel_mobile_theme']; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * load/reload current theme info | ||||
| 	 */ | ||||
|  | ||||
| @@ -776,36 +763,34 @@ function profile_load(&$a, $nickname, $profile = '') { | ||||
| //	if (file_exists($theme_info_file)){ | ||||
| //		require_once($theme_info_file); | ||||
| //	} | ||||
|  | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| function profile_create_sidebar(&$a,$connect = true) { | ||||
|  | ||||
| 	$block = (((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) ? true : false); | ||||
|  | ||||
| 	$a->set_widget('profile',profile_sidebar($a->profile, $block, $connect)); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * Function: profile_sidebar | ||||
|  * @param App &$a | ||||
|  * @param boolean $connect | ||||
|  */ | ||||
| function profile_create_sidebar(&$a, $connect = true) { | ||||
|  | ||||
| 	$block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false); | ||||
|  | ||||
| 	$a->set_widget('profile', profile_sidebar($a->profile, $block, $connect)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Formats a profile for display in the sidebar. | ||||
|  * | ||||
|  * Formats a profile for display in the sidebar. | ||||
|  * It is very difficult to templatise the HTML completely | ||||
|  * because of all the conditional logic. | ||||
|  * | ||||
|  * @parameter: array $profile | ||||
|  * @param array $profile | ||||
|  * @param int $block | ||||
|  * @param boolean $show_connect | ||||
|  * | ||||
|  * Returns HTML string stuitable for sidebar inclusion | ||||
|  * @return HTML string suitable for sidebar inclusion | ||||
|  * Exceptions: Returns empty string if passed $profile is wrong type or not populated | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
|  | ||||
| function profile_sidebar($profile, $block = 0, $show_connect = true) { | ||||
|  | ||||
| 	$a = get_app(); | ||||
| @@ -814,14 +799,12 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { | ||||
|  | ||||
| 	$o = ''; | ||||
| 	$location = false; | ||||
| 	$address = false; | ||||
| 	$pdesc = true; | ||||
| 	$reddress = true; | ||||
|  | ||||
| 	if((! is_array($profile)) && (! count($profile))) | ||||
| 		return $o; | ||||
|  | ||||
|  | ||||
| 	head_set_icon($profile['thumb']); | ||||
|  | ||||
| 	$is_owner = (($profile['uid'] == local_channel()) ? true : false); | ||||
| @@ -849,13 +832,11 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { | ||||
|  | ||||
| 	// show edit profile to yourself | ||||
| 	if($is_owner) { | ||||
|  | ||||
| 		$profile['menu'] = array( | ||||
| 			'chg_photo' => t('Change profile photo'), | ||||
| 			'entries' => array(), | ||||
| 		); | ||||
|  | ||||
|  | ||||
| 		$multi_profiles = feature_enabled(local_channel(), 'multi_profiles'); | ||||
| 		if($multi_profiles) { | ||||
| 			$profile['edit'] = array($a->get_baseurl(). '/profiles', t('Profiles'),"", t('Manage/edit profiles')); | ||||
| @@ -867,7 +848,6 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { | ||||
| 		$r = q("SELECT * FROM `profile` WHERE `uid` = %d", | ||||
| 				local_channel()); | ||||
|  | ||||
|  | ||||
| 		if($r) { | ||||
| 			foreach($r as $rr) { | ||||
| 				if(!($multi_profiles || $rr['is_default'])) | ||||
| @@ -899,21 +879,21 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { | ||||
| 	$marital  = ((x($profile,'marital')  == 1) ? t('Status:')   : False); | ||||
| 	$homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False); | ||||
| 	$profile['online']   = (($profile['online_status'] === 'online') ? t('Online Now') : False); | ||||
| logger('online: ' . $profile['online']); | ||||
| 	logger('online: ' . $profile['online']); | ||||
|  | ||||
| 	if(! perm_is_allowed($profile['uid'],((is_array($observer)) ? $observer['xchan_hash'] : ''),'view_profile')) { | ||||
| 		$block = true; | ||||
| 	} | ||||
|  | ||||
| 	if(($profile['hidewall'] && (! local_channel()) && (! remote_channel())) || $block ) { | ||||
| 		$location = $reddress = $pdesc = $gender = $marital = $homepage = $online = False; | ||||
| 		$location = $reddress = $pdesc = $gender = $marital = $homepage = False; | ||||
| 	} | ||||
|  | ||||
| 	$firstname = ((strpos($profile['channel_name'],' ')) | ||||
| 		? trim(substr($profile['channel_name'],0,strpos($profile['channel_name'],' '))) : $profile['channel_name']); | ||||
| 	$lastname = (($firstname === $profile['channel_name']) ? '' : trim(substr($profile['channel_name'],strlen($firstname)))); | ||||
|  | ||||
|     $diaspora = array( | ||||
| 	$diaspora = array( | ||||
| 		'podloc'     => z_root(), | ||||
| 		'searchable' => (($block) ? 'false' : 'true'), | ||||
| 		'nickname'   => $profile['channel_address'], | ||||
| @@ -970,9 +950,9 @@ logger('online: ' . $profile['online']); | ||||
| } | ||||
|  | ||||
|  | ||||
| // FIXME or remove | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @FIXME or remove | ||||
|  */ | ||||
| 	function get_birthdays() { | ||||
|  | ||||
| 		$a = get_app(); | ||||
| @@ -1030,7 +1010,6 @@ logger('online: ' . $profile['online']); | ||||
| 					$rr['date'] = day_translate(datetime_convert('UTC', $a->timezone, $rr['start'], $rr['adjust'] ? $bd_format : $bd_short)) . (($today) ?  ' ' . t('[today]') : ''); | ||||
| 					$rr['startime'] = Null; | ||||
| 					$rr['today'] = $today; | ||||
| 	 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -1044,14 +1023,13 @@ logger('online: ' . $profile['online']); | ||||
| 			'$events' => $r, | ||||
| 			'$lbr' => '{',  // raw brackets mess up if/endif macro processing | ||||
| 			'$rbr' => '}' | ||||
|  | ||||
| 		)); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| // FIXME | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @FIXME | ||||
|  */ | ||||
| 	function get_events() { | ||||
|  | ||||
| 		require_once('include/bbcode.php'); | ||||
| @@ -1085,7 +1063,6 @@ logger('online: ' . $profile['online']); | ||||
| 			} | ||||
| 			$classtoday = (($istoday) ? 'event-today' : ''); | ||||
|  | ||||
|  | ||||
| 			foreach($r as &$rr) { | ||||
| 				if($rr['adjust']) | ||||
| 					$md = datetime_convert('UTC',$a->timezone,$rr['start'],'Y/m'); | ||||
| @@ -1175,19 +1152,19 @@ function advanced_profile(&$a) { | ||||
| 					: day_translate(datetime_convert('UTC','UTC','2001-' . substr($a->profile['dob'],5) . ' 00:00 +00:00',$short_bd_format))); | ||||
| 			} | ||||
| 			$profile['birthday'] = array( t('Birthday:'), $val); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		if($age = age($a->profile['dob'],$a->profile['timezone'],''))  $profile['age'] = array( t('Age:'), $age ); | ||||
| 		if($age = age($a->profile['dob'],$a->profile['timezone'],'')) | ||||
| 			$profile['age'] = array( t('Age:'), $age ); | ||||
|  | ||||
| 		if($a->profile['marital']) | ||||
| 			$profile['marital'] = array( t('Status:'), $a->profile['marital']); | ||||
|  | ||||
| 		if($a->profile['marital']) $profile['marital'] = array( t('Status:'), $a->profile['marital']); | ||||
|  | ||||
|  | ||||
| 		if($a->profile['with']) $profile['marital']['with'] = bbcode($a->profile['with']); | ||||
| 		if($a->profile['with']) | ||||
| 			$profile['marital']['with'] = bbcode($a->profile['with']); | ||||
|  | ||||
| 		if(strlen($a->profile['howlong']) && $a->profile['howlong'] !== NULL_DATE) { | ||||
| 				$profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s')); | ||||
| 			$profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s')); | ||||
| 		} | ||||
|  | ||||
| 		if($a->profile['sexual']) $profile['sexual'] = array( t('Sexual Preference:'), $a->profile['sexual'] ); | ||||
| @@ -1243,48 +1220,49 @@ function advanced_profile(&$a) { | ||||
|  | ||||
| //		logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA);  | ||||
|  | ||||
|         return replace_macros($tpl, array( | ||||
|             '$title' => t('Profile'), | ||||
| 		return replace_macros($tpl, array( | ||||
| 			'$title' => t('Profile'), | ||||
| 			'$canlike' => (($profile['canlike'])? true : false), | ||||
| 			'$likethis' => t('Like this thing'), | ||||
|             '$profile' => $profile, | ||||
| 			'$profile' => $profile, | ||||
| 			'$things' => $things | ||||
|         )); | ||||
|     } | ||||
| 		)); | ||||
| 	} | ||||
|  | ||||
| 	return ''; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| function get_my_url() { | ||||
| 	if(x($_SESSION,'zrl_override')) | ||||
| 	if(x($_SESSION, 'zrl_override')) | ||||
| 		return $_SESSION['zrl_override']; | ||||
| 	if(x($_SESSION,'my_url')) | ||||
| 	if(x($_SESSION, 'my_url')) | ||||
| 		return $_SESSION['my_url']; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| function get_my_address() { | ||||
| 	if(x($_SESSION,'zid_override')) | ||||
| 	if(x($_SESSION, 'zid_override')) | ||||
| 		return $_SESSION['zid_override']; | ||||
| 	if(x($_SESSION,'my_address')) | ||||
| 	if(x($_SESSION, 'my_address')) | ||||
| 		return $_SESSION['my_address']; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function zid_init(&$a) | ||||
|  *   If somebody arrives at our site using a zid, add their xchan to our DB if we don't have it already. | ||||
|  *   And if they aren't already authenticated here, attempt reverse magic auth. | ||||
|  * @brief | ||||
|  * | ||||
|  * If somebody arrives at our site using a zid, add their xchan to our DB if we don't have it already. | ||||
|  * And if they aren't already authenticated here, attempt reverse magic auth. | ||||
|  * | ||||
|  * @param App &$a | ||||
|  * | ||||
|  * @hooks 'zid_init' | ||||
|  *      string 'zid' - their zid | ||||
|  *      string 'url' - the destination url | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| function zid_init(&$a) { | ||||
| 	$tmp_str = get_my_address(); | ||||
| 	if(validate_email($tmp_str)) { | ||||
| @@ -1312,8 +1290,8 @@ function zid_init(&$a) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function zid($s,$address = '') | ||||
|  *   Adds a zid parameter to a url | ||||
|  * @brief Adds a zid parameter to a url. | ||||
|  * | ||||
|  * @param string $s | ||||
|  *   The url to accept the zid | ||||
|  * @param boolean $address | ||||
| @@ -1325,31 +1303,33 @@ function zid_init(&$a) { | ||||
|  *      string zid - urlencoded zid | ||||
|  *      string result - the return string we calculated, change it if you want to return something else | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function zid($s,$address = '') { | ||||
| 	if(! strlen($s) || strpos($s,'zid=')) | ||||
| 	if (! strlen($s) || strpos($s,'zid=')) | ||||
| 		return $s; | ||||
|  | ||||
| 	$has_params = ((strpos($s,'?')) ? true : false); | ||||
| 	$num_slashes = substr_count($s,'/'); | ||||
| 	if(! $has_params) | ||||
| 		$has_params = ((strpos($s,'&')) ? true : false); | ||||
| 	$num_slashes = substr_count($s, '/'); | ||||
| 	if (! $has_params) | ||||
| 		$has_params = ((strpos($s, '&')) ? true : false); | ||||
|  | ||||
| 	$achar = strpos($s,'?') ? '&' : '?'; | ||||
|  | ||||
| 	$mine = get_my_url(); | ||||
| 	$myaddr = (($address) ? $address : get_my_address()); | ||||
|  | ||||
| 	// FIXME checking against our own channel url is no longer reliable. We may have a lot | ||||
| 	// of urls attached to out channel. Should probably match against our site, since we | ||||
| 	// will not need to remote authenticate on our own site anyway. | ||||
| 	/** @FIXME checking against our own channel url is no longer reliable. We may have a lot | ||||
| 	 * of urls attached to out channel. Should probably match against our site, since we | ||||
| 	 * will not need to remote authenticate on our own site anyway. | ||||
| 	 */ | ||||
|  | ||||
| 	if($mine && $myaddr && (! link_compare($mine,$s))) | ||||
| 	if ($mine && $myaddr && (! link_compare($mine,$s))) | ||||
| 		$zurl = $s . (($num_slashes >= 3) ? '' : '/') . $achar . 'zid=' . urlencode($myaddr); | ||||
| 	else | ||||
| 		$zurl = $s; | ||||
|  | ||||
| 	$arr = array('url' => $s, 'zid' => urlencode($myaddr), 'result' => $zurl); | ||||
| 	call_hooks('zid', $arr); | ||||
|  | ||||
| 	return $arr['result']; | ||||
| } | ||||
|  | ||||
| @@ -1370,54 +1350,44 @@ function get_theme_uid() { | ||||
| 		if($x) | ||||
| 			return $x['channel_id']; | ||||
| 	} | ||||
|  | ||||
| 	return $uid; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @function get_default_profile_photo($size = 175) | ||||
| * 	Retrieves the path of the default_profile_photo for this system | ||||
| * 	with the specified size. | ||||
| * @param int $size | ||||
| * 	one of (175, 80, 48) | ||||
| * @returns string | ||||
| * @brief Retrieves the path of the default_profile_photo for this system | ||||
| * with the specified size. | ||||
| * | ||||
| * @param int $size | ||||
| *  one of (175, 80, 48) | ||||
| * @returns string | ||||
| */ | ||||
|  | ||||
| function get_default_profile_photo($size = 175) { | ||||
| 		$scheme = get_config('system','default_profile_photo'); | ||||
| 		if(! $scheme) | ||||
| 			$scheme = 'rainbow_man'; | ||||
| 		return 'images/default_profile_photos/' . $scheme . '/' . $size . '.png'; | ||||
| 	$scheme = get_config('system','default_profile_photo'); | ||||
| 	if(! $scheme) | ||||
| 		$scheme = 'rainbow_man'; | ||||
|  | ||||
| 	return 'images/default_profile_photos/' . $scheme . '/' . $size . '.png'; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Test whether a given identity is NOT a member of the Red Matrix. | ||||
|  * | ||||
|  * @function is_foreigner($s) | ||||
|  *    Test whether a given identity is NOT a member of the Red Matrix | ||||
|  * @param string $s; | ||||
|  *    xchan_hash of the identity in question | ||||
|  * | ||||
|  * @returns boolean true or false | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| function is_foreigner($s) { | ||||
| 	return((strpbrk($s,'.:@')) ? true : false); | ||||
| 	return((strpbrk($s, '.:@')) ? true : false); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Test whether a given identity is a member of the Red Matrix. | ||||
|  * | ||||
|  * @function is_member($s) | ||||
|  *    Test whether a given identity is a member of the Red Matrix | ||||
|  * @param string $s; | ||||
|  *    xchan_hash of the identity in question | ||||
|  * | ||||
|  * @returns boolean true or false | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| function is_member($s) { | ||||
| 	return((is_foreigner($s)) ? false : true); | ||||
| } | ||||
| @@ -1464,8 +1434,8 @@ function remote_online_status($webbie) { | ||||
| 		if($j) | ||||
| 			$result = (($j['result']) ? $j['result'] : false); | ||||
| 	} | ||||
| 	return $result; | ||||
|  | ||||
| 	return $result; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1477,17 +1447,20 @@ function get_channel_by_nick($nick) { | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @return string | ||||
|  */ | ||||
| function identity_selector() { | ||||
| 	if(local_channel()) { | ||||
| 	if (local_channel()) { | ||||
| 		$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and (channel_pageflags & %d) = 0 order by channel_name ", | ||||
| 			intval(get_account_id()), | ||||
| 			intval(PAGE_REMOVED) | ||||
| 		); | ||||
| 		if(count($r) > 1) { | ||||
| 			$selected_channel = null; | ||||
| 			$account = get_app()->get_account(); | ||||
| 			$o = replace_macros(get_markup_template('channel_id_select.tpl'),array( | ||||
| 		if (count($r) > 1) { | ||||
| 			//$account = get_app()->get_account(); | ||||
| 			$o = replace_macros(get_markup_template('channel_id_select.tpl'), array( | ||||
| 				'$channels' => $r, | ||||
| 				'$selected' => local_channel() | ||||
| 			)); | ||||
| @@ -1507,6 +1480,7 @@ function is_public_profile() { | ||||
| 	$channel = get_app()->get_channel(); | ||||
| 	if($channel && $channel['channel_r_profile'] == PERMS_PUBLIC) | ||||
| 		return true; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| @@ -1522,7 +1496,6 @@ function get_profile_fields_basic($filter = 0) { | ||||
| 			$x[$f] = 1; | ||||
|  | ||||
| 	return $x; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1536,6 +1509,7 @@ function get_profile_fields_advanced($filter = 0) { | ||||
| 	if($basic) | ||||
| 		foreach($basic as $f => $v) | ||||
| 			$x[$f] = $v; | ||||
|  | ||||
| 	if($profile_fields_advanced) | ||||
| 		foreach($profile_fields_advanced as $f) | ||||
| 			$x[$f] = 1; | ||||
| @@ -1544,28 +1518,26 @@ function get_profile_fields_advanced($filter = 0) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function notifications_off($channel_id) | ||||
|  *    Clear notifyflags for a channel - most likely during bulk import of content or other activity that is likely | ||||
|  *    to generate huge amounts of undesired notifications. | ||||
|  * @brief Clear notifyflags for a channel. | ||||
|  * | ||||
|  * Most likely during bulk import of content or other activity that is likely | ||||
|  * to generate huge amounts of undesired notifications. | ||||
|  * | ||||
|  * @param int $channel_id | ||||
|  *    The channel to disable notifications for | ||||
|  * @returns int | ||||
|  *    Current notification flag value. Send this to notifications_on() to restore the channel settings when finished | ||||
|  *    with the activity requiring notifications_off();  | ||||
|  */ | ||||
|  | ||||
|  | ||||
|  | ||||
| function notifications_off($channel_id) { | ||||
| 	$r = q("select channel_notifyflags from channel where channel_id = %d limit 1", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
| 	$x = q("update channel set channel_notifyflags = 0 where channel_id = %d", | ||||
| 	q("update channel set channel_notifyflags = 0 where channel_id = %d", | ||||
| 		intval($channel_id) | ||||
| 	); | ||||
|  | ||||
| 	return intval($r[0]['channel_notifyflags']); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1586,5 +1558,6 @@ function get_channel_default_perms($uid) { | ||||
| 	); | ||||
| 	if($r) | ||||
| 		return $r[0]['abook_my_perms']; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,8 +1,8 @@ | ||||
| <?php | ||||
| /** | ||||
|  * @file | ||||
|  * @file include/language.php | ||||
|  * | ||||
|  * @brief translation support | ||||
|  * @brief Translation support. | ||||
|  * | ||||
|  * This file contains functions to work with translations and other | ||||
|  * language related tasks. | ||||
| @@ -26,7 +26,7 @@ function get_browser_language() { | ||||
| 	$langs = array(); | ||||
| 	$lang_parse = array(); | ||||
|  | ||||
| 	if (x($_SERVER,'HTTP_ACCEPT_LANGUAGE')) { | ||||
| 	if (x($_SERVER, 'HTTP_ACCEPT_LANGUAGE')) { | ||||
| 		// break up string into pieces (languages and q factors) | ||||
| 		preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',  | ||||
| 			$_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse); | ||||
| @@ -110,9 +110,12 @@ function pop_lang() { | ||||
| 	$a->language = $a->langsave; | ||||
| } | ||||
|  | ||||
|  | ||||
| // load string translation table for alternate language | ||||
|  | ||||
| /** | ||||
|  * @brief Load string translation table for alternate language. | ||||
|  * | ||||
|  * @param string $lang language code in 2-letter ISO 639-1 (en, de, fr) format | ||||
|  * @param boolean $install (optional) default false | ||||
|  */ | ||||
| function load_translation_table($lang, $install = false) { | ||||
| 	global $a; | ||||
|  | ||||
| @@ -139,14 +142,13 @@ function load_translation_table($lang, $install = false) { | ||||
| 	if(file_exists("view/local-$lang/strings.php")) { | ||||
| 		include("view/local-$lang/strings.php"); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief translate string if translation exists. | ||||
|  * @brief Translate string if translation exists. | ||||
|  * | ||||
|  * @param string $s string that should get translated | ||||
|  * @param string $ctx optional context to appear in po file | ||||
|  * @param string $ctx (optional) context to appear in po file | ||||
|  * @return translated string if exists, otherwise return $s | ||||
|  * | ||||
|  */ | ||||
| @@ -154,37 +156,53 @@ function t($s, $ctx = '') { | ||||
| 	global $a; | ||||
|  | ||||
| 	$cs = $ctx ? '__ctx:' . $ctx . '__ ' . $s : $s; | ||||
| 	if(x($a->strings, $cs)) { | ||||
| 	if (x($a->strings, $cs)) { | ||||
| 		$t = $a->strings[$cs]; | ||||
|  | ||||
| 		return is_array($t) ? $t[0] : $t; | ||||
| 	} | ||||
|  | ||||
| 	return $s; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param string $singular | ||||
|  * @param string $plural | ||||
|  * @param int $count | ||||
|  * @param string $ctx | ||||
|  * @return string | ||||
|  */ | ||||
| function tt($singular, $plural, $count, $ctx = ''){ | ||||
| 	$a = get_app(); | ||||
|  | ||||
| 	$cs = $ctx?"__ctx:".$ctx."__ ".$singular:$singular; | ||||
| 	if(x($a->strings,$cs)) { | ||||
| 	$cs = $ctx ? "__ctx:" . $ctx . "__ " . $singular : $singular; | ||||
| 	if (x($a->strings,$cs)) { | ||||
| 		$t = $a->strings[$cs]; | ||||
| 		$f = 'string_plural_select_' . str_replace('-', '_', $a->language); | ||||
| 		if(! function_exists($f)) | ||||
| 		if (! function_exists($f)) | ||||
| 			$f = 'string_plural_select_default'; | ||||
|  | ||||
| 		$k = $f($count); | ||||
|  | ||||
| 		return is_array($t) ? $t[$k] : $t; | ||||
| 	} | ||||
|  | ||||
| 	if ($count != 1){ | ||||
| 	if ($count != 1) { | ||||
| 		return $plural; | ||||
| 	} else { | ||||
| 		return $singular; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // provide a fallback which will not collide with  | ||||
| // a function defined in any language file  | ||||
|  | ||||
| /** | ||||
|  * @brief Provide a fallback which will not collide with a function defined in | ||||
|  * any language file. | ||||
|  * | ||||
|  * @param int $n | ||||
|  * @return boolean | ||||
|  */ | ||||
| function string_plural_select_default($n) { | ||||
| 	return ($n != 1); | ||||
| } | ||||
| @@ -200,25 +218,25 @@ function string_plural_select_default($n) { | ||||
|  * returned through config['system']['language_detect_min_confidence']. | ||||
|  * | ||||
|  * @see http://pear.php.net/package/Text_LanguageDetect | ||||
|  * @param s A string to examine | ||||
|  * @param string $s A string to examine | ||||
|  * @return Language code in 2-letter ISO 639-1 (en, de, fr) format | ||||
|  */ | ||||
| function detect_language($s) { | ||||
| 	require_once('Text/LanguageDetect.php'); | ||||
|  | ||||
| 	$min_length = get_config('system', 'language_detect_min_length'); | ||||
| 	if($min_length === false) | ||||
| 	if ($min_length === false) | ||||
| 		$min_length = LANGUAGE_DETECT_MIN_LENGTH; | ||||
|  | ||||
| 	$min_confidence = get_config('system', 'language_detect_min_confidence'); | ||||
| 	if($min_confidence === false) | ||||
| 	if ($min_confidence === false) | ||||
| 		$min_confidence = LANGUAGE_DETECT_MIN_CONFIDENCE; | ||||
|  | ||||
| 	// embedded apps have long base64 strings which will trip up the detector. | ||||
| 	$naked_body = preg_replace('/\[app\](.*?)\[\/app\]/','',$s); | ||||
| 	// strip off bbcode | ||||
| 	$naked_body = preg_replace('/\[(.+?)\]/', '', $naked_body); | ||||
| 	if(mb_strlen($naked_body) < intval($min_length)) { | ||||
| 	if (mb_strlen($naked_body) < intval($min_length)) { | ||||
| 		logger('string length less than ' . intval($min_length), LOGGER_DATA); | ||||
| 		return ''; | ||||
| 	} | ||||
| @@ -233,11 +251,11 @@ function detect_language($s) { | ||||
| 		logger('detect language exception: ' . $e->getMessage(), LOGGER_DATA); | ||||
| 	} | ||||
|  | ||||
| 	if((! $lng) || (! (x($lng,'language')))) { | ||||
| 	if ((! $lng) || (! (x($lng,'language')))) { | ||||
| 		return ''; | ||||
| 	} | ||||
|  | ||||
| 	if($lng['confidence'] < (float) $min_confidence) { | ||||
| 	if ($lng['confidence'] < (float) $min_confidence) { | ||||
| 		logger('detect language: confidence less than ' . (float) $min_confidence, LOGGER_DATA); | ||||
| 		return ''; | ||||
| 	} | ||||
| @@ -251,38 +269,37 @@ function detect_language($s) { | ||||
|  * By default we use the localized language name. You can switch the result | ||||
|  * to any language with the optional 2nd parameter $l. | ||||
|  * | ||||
|  * $s and $l should be in 2-letter ISO 639-1 format | ||||
|  * $s and $l should be in 2-letter ISO 639-1 format. | ||||
|  * | ||||
|  * If nothing could be looked up it returns $s. | ||||
|  * | ||||
|  * @param $s Language code to look up | ||||
|  * @param $l (optional) In which language to return the name | ||||
|  * @param string $s Language code to look up | ||||
|  * @param string $l (optional) In which language to return the name | ||||
|  * @return string with the language name, or $s if unrecognized | ||||
|  * | ||||
|  * @todo include CommerceGuys\Intl through composer like SabreDAV. | ||||
|  */ | ||||
| require_once(__DIR__ . '/../library/intl/vendor/autoload.php'); | ||||
| use CommerceGuys\Intl\Language\LanguageRepository; | ||||
| function get_language_name($s, $l = null) { | ||||
| 	// get() expects the second part to be in upper case | ||||
| 	if(strpos($s,'-') !== false) $s = substr($s,0,2) . strtoupper(substr($s,2)); | ||||
| 	if($l !== null && strpos($l,'-') !== false) $l = substr($l,0,2) . strtoupper(substr($l,2)); | ||||
| 	if (strpos($s, '-') !== false) $s = substr($s, 0, 2) . strtoupper(substr($s, 2)); | ||||
| 	if ($l !== null && strpos($l, '-') !== false) $l = substr($l, 0, 2) . strtoupper(substr($l, 2)); | ||||
|  | ||||
| 	$languageRepository = new LanguageRepository; | ||||
|  | ||||
| 	// Sometimes intl doesn't like the second part at all ... | ||||
| 	try { | ||||
| 		$language = $languageRepository->get($s, $l); | ||||
| 	} | ||||
| 	catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) { | ||||
| 		$s = substr($s,0,2); | ||||
| 		if($l !== null) $l = substr($s,0,2); | ||||
| 	} catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) { | ||||
| 		$s = substr($s, 0, 2); | ||||
| 		if($l !== null) $l = substr($s, 0, 2); | ||||
| 		try { | ||||
| 			$language = $languageRepository->get($s, $l); | ||||
| 		} | ||||
| 		catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) { | ||||
| 		} catch (CommerceGuys\Intl\Exception\UnknownLanguageException $e) { | ||||
| 			return $s; // Give up | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return $language->getName(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,33 +1,39 @@ | ||||
| <?php /** @file */ | ||||
|  | ||||
|  | ||||
| <?php | ||||
| /** | ||||
|  * @file include/network.php | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @brief Returns path to CA file. | ||||
|  * | ||||
|  * @return string | ||||
|  */ | ||||
| function get_capath() { | ||||
| 	return appdirpath() . '/library/cacert.pem'; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function z_fetch_url | ||||
|  * @brief fetches an URL. | ||||
|  * | ||||
|  * @param string $url | ||||
|  *    URL to fetch | ||||
|  * @param boolean $binary = false | ||||
|  * @param boolean $binary default false | ||||
|  *    TRUE if asked to return binary results (file download) | ||||
|  * @param int $redirects = 0 | ||||
|  * @param int $redirects default 0 | ||||
|  *    internal use, recursion counter | ||||
|  * @param array $opts (optional parameters) | ||||
|  *    'accept_content' => supply Accept: header with 'accept_content' as the value | ||||
|  *    'timeout' => int seconds, default system config value or 60 seconds | ||||
|  *    'http_auth' => username:password | ||||
|  *    'novalidate' => do not validate SSL certs, default is to validate using our CA list | ||||
|  *    'nobody' => only return the header | ||||
|  * @param array $opts (optional parameters) assoziative array with: | ||||
|  *  * \b accept_content => supply Accept: header with 'accept_content' as the value | ||||
|  *  * \b timeout => int seconds, default system config value or 60 seconds | ||||
|  *  * \b http_auth => username:password | ||||
|  *  * \b novalidate => do not validate SSL certs, default is to validate using our CA list | ||||
|  *  * \b nobody => only return the header | ||||
|  * | ||||
|  * @returns array | ||||
|  *    'return_code' => HTTP return code or 0 if timeout or failure | ||||
|  *    'success' => boolean true (if HTTP 2xx result) or false | ||||
|  *    'header' => HTTP headers | ||||
|  *    'body' => fetched content | ||||
|  * @return array an assoziative array with: | ||||
|  *  * \e int \b return_code => HTTP return code or 0 if timeout or failure | ||||
|  *  * \e boolean \b success => boolean true (if HTTP 2xx result) or false | ||||
|  *  * \e string \b header => HTTP headers | ||||
|  *  * \e string \b body => fetched content | ||||
|  */ | ||||
|  | ||||
| function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { | ||||
|  | ||||
| 	$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => ""); | ||||
| @@ -136,7 +142,8 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function z_post_url | ||||
|  * @brief | ||||
|  * | ||||
|  * @param string $url | ||||
|  *    URL to post | ||||
|  * @param mixed $params | ||||
| @@ -151,15 +158,13 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { | ||||
|  *    'timeout' => int seconds, default system config value or 60 seconds | ||||
|  *    'http_auth' => username:password | ||||
|  *    'novalidate' => do not validate SSL certs, default is to validate using our CA list | ||||
|  *     | ||||
|  * @returns array | ||||
|  *    'return_code' => HTTP return code or 0 if timeout or failure | ||||
|  *    'success' => boolean true (if HTTP 2xx result) or false | ||||
|  *    'header' => HTTP headers | ||||
|  *    'body' => fetched content | ||||
|  * @return array an assoziative array with: | ||||
|  *  * \e int \b return_code => HTTP return code or 0 if timeout or failure | ||||
|  *  * \e boolean \b success => boolean true (if HTTP 2xx result) or false | ||||
|  *  * \e string \b header => HTTP headers | ||||
|  *  * \e string \b body => content | ||||
|  *  * \e string \b debug => from curl_info() | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function z_post_url($url,$params, $redirects = 0, $opts = array()) { | ||||
|  | ||||
| 	$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => ""); | ||||
| @@ -257,24 +262,35 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { | ||||
| 		logger('z_post_url: debug: ' . print_r($curl_info,true), LOGGER_DATA); | ||||
| 	} | ||||
|  | ||||
| 	$ret['body'] = substr($s,strlen($header)); | ||||
| 	$ret['body'] = substr($s, strlen($header)); | ||||
| 	$ret['header'] = $header; | ||||
|  | ||||
| 	if(x($opts,'debug')) { | ||||
| 		$ret['debug'] = $curl_info; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	curl_close($ch); | ||||
| 	return($ret); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Like z_post_url() but with an application/json HTTP header. | ||||
|  * | ||||
|  * Add a "Content-Type: application/json" HTTP-header to $opts and call z_post_url(). | ||||
|  * | ||||
|  * @see z_post_url() | ||||
|  * | ||||
|  * @param string $url | ||||
|  * @param array $params | ||||
|  * @param number $redirects default 0 | ||||
|  * @param array $opts (optional) curl options | ||||
|  * @return z_post_url() | ||||
|  */ | ||||
| function z_post_url_json($url, $params, $redirects = 0, $opts = array()) { | ||||
|  | ||||
| function z_post_url_json($url,$params,$redirects = 0, $opts = array()) { | ||||
| 	$opts = array_merge($opts, array('headers' => array('Content-Type: application/json'))); | ||||
|  | ||||
| 	$opts = array_merge($opts,array('headers' => array('Content-Type: application/json'))); | ||||
| 	return z_post_url($url,json_encode($params),$redirects,$opts); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -305,22 +321,19 @@ function xml_status($st, $message = '') { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @function http_status_exit | ||||
|  * @brief Send HTTP status header and exit. | ||||
|  * | ||||
|  * Send HTTP status header and exit | ||||
|  * @param int $val | ||||
|  *    integer HTTP status result value | ||||
|  * @param string $msg | ||||
|  *    optional message | ||||
|  * @returns (does not return, process is terminated) | ||||
|  */ | ||||
| function http_status_exit($val, $msg = '') { | ||||
|  | ||||
| function http_status_exit($val,$msg = '') { | ||||
|  | ||||
| 	$err = ''; | ||||
| 	if($val >= 400) | ||||
| 	if ($val >= 400) | ||||
| 		$msg = (($msg) ? $msg : 'Error'); | ||||
| 	if($val >= 200 && $val < 300) | ||||
| 	if ($val >= 200 && $val < 300) | ||||
| 		$msg = (($msg) ? $msg : 'OK'); | ||||
|  | ||||
| 	logger('http_status_exit ' . $val . ' ' . $msg);	 | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * @file incldue/permissions.php | ||||
|  * @file include/permissions.php | ||||
|  * | ||||
|  * This file conntains functions to check and work with permissions. | ||||
|  */ | ||||
| @@ -445,21 +445,21 @@ function site_default_perms() { | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function get_role_perms($role) | ||||
|  * @param string $role | ||||
|  * @brief Return an array of all permissions for this role. | ||||
|  * | ||||
|  *   Given a string for the channel role ('social','forum', etc) | ||||
|  * Given a string for the channel role ('social','forum', etc) | ||||
|  * return an array of all permission fields pre-filled for this role. | ||||
|  * This includes the channel permission scope indicators (anything beginning with 'channel_') as well as | ||||
|  *    perms_auto:   true or false to create auto-permissions for this channel | ||||
|  *    perms_follow: The permissions to apply when initiating a connection request to another channel | ||||
|  *    perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic) | ||||
|  *    default_collection: true or false to make the default ACL include the channel's default collection  | ||||
|  *    directory_publish: true or false to publish this channel in the directory | ||||
|  *  * perms_auto:   true or false to create auto-permissions for this channel | ||||
|  *  * perms_follow: The permissions to apply when initiating a connection request to another channel | ||||
|  *  * perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic) | ||||
|  *  * default_collection: true or false to make the default ACL include the channel's default collection  | ||||
|  *  * directory_publish: true or false to publish this channel in the directory | ||||
|  * Any attributes may be extended (new roles defined) and modified (specific permissions altered) by plugins | ||||
|  * | ||||
|  * @param string $role | ||||
|  * @return array | ||||
|  */ | ||||
|  | ||||
| function get_role_perms($role) { | ||||
|  | ||||
| 	$ret = array(); | ||||
| @@ -800,9 +800,8 @@ function get_role_perms($role) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Returns a list or roles, grouped by type | ||||
|  * @brief Returns a list or roles, grouped by type. | ||||
|  * | ||||
|  * @param string $current The current role | ||||
|  * @return string Returns an array of roles, grouped by type | ||||
|  */ | ||||
| function get_roles() { | ||||
| @@ -811,7 +810,8 @@ function get_roles() { | ||||
| 		t('Community Forum') => array('forum' => t('Mostly Public'), 'forum_restricted' => t('Restricted'), 'forum_private' => t('Private')), | ||||
| 		t('Feed Republish') => array('feed' => t('Mostly Public'), 'feed_restricted' => t('Restricted')), | ||||
| 		t('Special Purpose') => array('soapbox' => t('Celebrity/Soapbox'), 'repository' => t('Group Repository')), | ||||
| 		t('Other') => array('custom' => t('Custom/Expert Mode'))); | ||||
| 		t('Other') => array('custom' => t('Custom/Expert Mode')) | ||||
| 	); | ||||
|  | ||||
| 	return $roles; | ||||
| } | ||||
|   | ||||
| @@ -1,10 +1,21 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file include/photos.php | ||||
|  * @brief Functions related to photo handling. | ||||
|  */ | ||||
|  | ||||
| require_once('include/permissions.php'); | ||||
| require_once('include/items.php'); | ||||
| require_once('include/photo/photo_driver.php'); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param array $channel | ||||
|  * @param array $observer | ||||
|  * @param array $args | ||||
|  * @return array | ||||
|  */ | ||||
| function photo_upload($channel, $observer, $args) { | ||||
|  | ||||
| 	$ret = array('success' => false); | ||||
| @@ -18,12 +29,12 @@ function photo_upload($channel, $observer, $args) { | ||||
|  | ||||
| 	call_hooks('photo_upload_begin', $args); | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Determine the album to use | ||||
| 	 */ | ||||
|  | ||||
| 	$album       = $args['album']; | ||||
| 	$newalbum    = $args['newalbum']; | ||||
| 	$album    = $args['album']; | ||||
| 	$newalbum = $args['newalbum']; | ||||
|  | ||||
| 	logger('photo_upload: album= ' . $album . ' newalbum= ' . $newalbum , LOGGER_DEBUG); | ||||
|  | ||||
| @@ -44,8 +55,7 @@ function photo_upload($channel, $observer, $args) { | ||||
| 	$str_group_deny    = perms2str(((is_array($args['group_deny']))    ? $args['group_deny']    : explode(',',$args['group_deny']))); | ||||
| 	$str_contact_deny  = perms2str(((is_array($args['contact_deny']))  ? $args['contact_deny']  : explode(',',$args['contact_deny']))); | ||||
|  | ||||
|  | ||||
| 	if($args['data']) { | ||||
| 	if ($args['data']) { | ||||
|  | ||||
| 		// allow an import from a binary string representing the image. | ||||
| 		// This bypasses the upload step and max size limit checking | ||||
| @@ -56,23 +66,21 @@ function photo_upload($channel, $observer, $args) { | ||||
| 		// this is going to be deleted if it exists | ||||
| 		$src = '/tmp/deletemenow'; | ||||
| 		$type = $args['type']; | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); | ||||
|  | ||||
| 		call_hooks('photo_upload_file',$f); | ||||
|  | ||||
| 		if(x($f,'src') && x($f,'filesize')) { | ||||
| 		if (x($f,'src') && x($f,'filesize')) { | ||||
| 			$src      = $f['src']; | ||||
| 			$filename = $f['filename']; | ||||
| 			$filesize = $f['filesize']; | ||||
| 			$type     = $f['type']; | ||||
| 		} | ||||
| 		else { | ||||
| 			$src        = $_FILES['userfile']['tmp_name']; | ||||
| 			$filename   = basename($_FILES['userfile']['name']); | ||||
| 			$filesize   = intval($_FILES['userfile']['size']); | ||||
| 			$type       = $_FILES['userfile']['type']; | ||||
| 		} else { | ||||
| 			$src      = $_FILES['userfile']['tmp_name']; | ||||
| 			$filename = basename($_FILES['userfile']['name']); | ||||
| 			$filesize = intval($_FILES['userfile']['size']); | ||||
| 			$type     = $_FILES['userfile']['type']; | ||||
| 		} | ||||
|  | ||||
| 		if (! $type)  | ||||
| @@ -82,14 +90,14 @@ function photo_upload($channel, $observer, $args) { | ||||
|  | ||||
| 		$maximagesize = get_config('system','maximagesize'); | ||||
|  | ||||
| 		if(($maximagesize) && ($filesize > $maximagesize)) { | ||||
| 		if (($maximagesize) && ($filesize > $maximagesize)) { | ||||
| 			$ret['message'] =  sprintf ( t('Image exceeds website size limit of %lu bytes'), $maximagesize); | ||||
| 			@unlink($src); | ||||
| 			call_hooks('photo_upload_end',$ret); | ||||
| 			return $ret; | ||||
| 		} | ||||
|  | ||||
| 		if(! $filesize) { | ||||
| 		if (! $filesize) { | ||||
| 			$ret['message'] = t('Image file is empty.'); | ||||
| 			@unlink($src); | ||||
| 			call_hooks('photo_post_end',$ret); | ||||
| @@ -101,14 +109,13 @@ function photo_upload($channel, $observer, $args) { | ||||
| 		$imagedata = @file_get_contents($src); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	$r = q("select sum(size) as total from photo where aid = %d and scale = 0 ", | ||||
| 		intval($account_id) | ||||
| 	); | ||||
|  | ||||
| 	$limit = service_class_fetch($channel_id,'photo_upload_limit'); | ||||
|  | ||||
| 	if(($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { | ||||
| 	if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { | ||||
| 		$ret['message'] = upgrade_message(); | ||||
| 		@unlink($src); | ||||
| 		call_hooks('photo_post_end',$ret); | ||||
| @@ -117,7 +124,7 @@ function photo_upload($channel, $observer, $args) { | ||||
|  | ||||
| 	$ph = photo_factory($imagedata, $type); | ||||
|  | ||||
| 	if(! $ph->is_valid()) { | ||||
| 	if (! $ph->is_valid()) { | ||||
| 		$ret['message'] = t('Unable to process image'); | ||||
| 		logger('photo_upload: unable to process image'); | ||||
| 		@unlink($src); | ||||
| @@ -127,13 +134,12 @@ function photo_upload($channel, $observer, $args) { | ||||
|  | ||||
| 	$exif = $ph->orient($src); | ||||
|  | ||||
|  | ||||
| 	@unlink($src); | ||||
|  | ||||
| 	$max_length = get_config('system','max_image_length'); | ||||
| 	if(! $max_length) | ||||
| 	if (! $max_length) | ||||
| 		$max_length = MAX_IMAGE_LENGTH; | ||||
| 	if($max_length > 0) | ||||
| 	if ($max_length > 0) | ||||
| 		$ph->scaleImage($max_length); | ||||
|  | ||||
| 	$width  = $ph->getWidth(); | ||||
| @@ -144,7 +150,7 @@ function photo_upload($channel, $observer, $args) { | ||||
| 	$photo_hash = (($args['resource_id']) ? $args['resource_id'] : photo_new_resource()); | ||||
|  | ||||
| 	$visitor = ''; | ||||
| 	if($channel['channel_hash'] !== $observer['xchan_hash']) | ||||
| 	if ($channel['channel_hash'] !== $observer['xchan_hash']) | ||||
| 		$visitor = $observer['xchan_hash']; | ||||
|  | ||||
| 	$errors = false; | ||||
| @@ -163,7 +169,6 @@ function photo_upload($channel, $observer, $args) { | ||||
| 	if($args['description']) | ||||
| 		$p['description'] = $args['description']; | ||||
|  | ||||
|  | ||||
| 	$r1 = $ph->save($p); | ||||
| 	if(! $r1) | ||||
| 		$errors = true; | ||||
| @@ -214,8 +219,6 @@ function photo_upload($channel, $observer, $args) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	$item_flags = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP; | ||||
| 	$item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN); | ||||
| 	$title = ''; | ||||
| @@ -263,10 +266,9 @@ function photo_upload($channel, $observer, $args) { | ||||
| 			$tag = '[zmg]'; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	$arr['body']          = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'  | ||||
| 				. $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]' | ||||
| 				. '[/zrl]'; | ||||
| 	$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'  | ||||
| 			. $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]' | ||||
| 			. '[/zrl]'; | ||||
|  | ||||
| 	$result = item_store($arr); | ||||
| 	$item_id = $result['item_id']; | ||||
| @@ -304,7 +306,7 @@ function photos_albums_list($channel, $observer) { | ||||
| 	if(! perm_is_allowed($channel_id, $observer_xchan, 'view_photos')) | ||||
| 		return false; | ||||
|  | ||||
| 	// FIXME - create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status | ||||
| 	/** @FIXME create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status */ | ||||
|  | ||||
| 	$sql_extra = permissions_sql($channel_id); | ||||
|  | ||||
| @@ -327,7 +329,8 @@ function photos_albums_list($channel, $observer) { | ||||
| 				'total' => $album['total'],  | ||||
| 				'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album['album']),  | ||||
| 				'urlencode' => urlencode($album['album']), | ||||
| 				'bin2hex' => bin2hex($album['album'])); | ||||
| 				'bin2hex' => bin2hex($album['album']) | ||||
| 			); | ||||
| 			$ret['albums'][] = $entry; | ||||
| 		} | ||||
| 	} | ||||
| @@ -360,11 +363,19 @@ function photos_album_widget($channelx,$observer,$albums = null) { | ||||
| 				? t('Upload New Photos') : '') | ||||
| 		)); | ||||
| 	} | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|  | ||||
|  | ||||
| function photos_list_photos($channel,$observer,$album = '') { | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param array $channel | ||||
|  * @param array $observer | ||||
|  * @param string $album default empty | ||||
|  * @return boolean|array | ||||
|  */ | ||||
| function photos_list_photos($channel, $observer, $album = '') { | ||||
|  | ||||
| 	$channel_id     = $channel['channel_id']; | ||||
| 	$observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); | ||||
| @@ -416,6 +427,7 @@ function photos_album_exists($channel_id, $album) { | ||||
|  * @brief Renames a photo album in a channel. | ||||
|  * | ||||
|  * @todo Do we need to check if new album name already exists? | ||||
|  * | ||||
|  * @param int $channel_id id of the channel | ||||
|  * @param string $oldname The name of the album to rename | ||||
|  * @param string $newname The new name of the album | ||||
| @@ -429,25 +441,31 @@ function photos_album_rename($channel_id, $oldname, $newname) { | ||||
| 	); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param int $channel_id | ||||
|  * @param string $album | ||||
|  * @param string $remote_xchan | ||||
|  * @return string|boolean | ||||
|  */ | ||||
| function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { | ||||
|  | ||||
| function photos_album_get_db_idstr($channel_id,$album,$remote_xchan = '') { | ||||
|  | ||||
| 	if($remote_xchan) { | ||||
| 	if ($remote_xchan) { | ||||
| 		$r = q("SELECT distinct resource_id as from photo where xchan = '%s' and uid = %d and album = '%s' ", | ||||
| 			dbesc($remote_xchan), | ||||
| 			intval($channel_id), | ||||
| 			dbesc($album) | ||||
| 		); | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$r = q("SELECT distinct resource_id  from photo where uid = %d and album = '%s' ", | ||||
| 			intval($channel_id), | ||||
| 			dbesc($album) | ||||
| 		); | ||||
| 	} | ||||
| 	if($r) { | ||||
| 	if ($r) { | ||||
| 		$arr = array(); | ||||
| 		foreach($r as $rr) { | ||||
| 		foreach ($r as $rr) { | ||||
| 			$arr[] = "'" . dbesc($rr['resource_id']) . "'" ; | ||||
| 		} | ||||
| 		$str = implode(',',$arr); | ||||
| @@ -457,6 +475,15 @@ function photos_album_get_db_idstr($channel_id,$album,$remote_xchan = '') { | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Creates a new photo item. | ||||
|  * | ||||
|  * @param array $channel | ||||
|  * @param string $creator_hash | ||||
|  * @param array $photo | ||||
|  * @param boolean $visible default false | ||||
|  * @return int item_id | ||||
|  */ | ||||
| function photos_create_item($channel, $creator_hash, $photo, $visible = false) { | ||||
|  | ||||
| 	// Create item container | ||||
| @@ -506,7 +533,6 @@ function getGps($exifCoord, $hemi) { | ||||
|     $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; | ||||
|  | ||||
|     return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600))); | ||||
|  | ||||
| } | ||||
|  | ||||
| function gps2Num($coordPart) { | ||||
| @@ -521,4 +547,3 @@ function gps2Num($coordPart) { | ||||
|  | ||||
|     return floatval($parts[0]) / floatval($parts[1]); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -7,13 +7,12 @@ | ||||
|  | ||||
| require_once("include/smarty.php"); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief unloads an addon. | ||||
|  * | ||||
|  * @param string $plugin name of the addon | ||||
|  * @return void | ||||
|  */ | ||||
|  | ||||
| function unload_plugin($plugin){ | ||||
| 	logger("Addons: unloading " . $plugin, LOGGER_DEBUG); | ||||
|  | ||||
| @@ -28,9 +27,8 @@ function unload_plugin($plugin){ | ||||
|  * @brief uninstalls an addon. | ||||
|  * | ||||
|  * @param string $plugin name of the addon | ||||
|  * @return bool | ||||
|  * @return boolean | ||||
|  */ | ||||
|  | ||||
| function uninstall_plugin($plugin) { | ||||
| 	unload_plugin($plugin); | ||||
|  | ||||
| @@ -70,7 +68,7 @@ function install_plugin($plugin) { | ||||
|  | ||||
| 	$plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0); | ||||
|  | ||||
| 	$r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ", | ||||
| 	q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ", | ||||
| 		dbesc($plugin), | ||||
| 		intval($t), | ||||
| 		$plugin_admin | ||||
| @@ -196,6 +194,7 @@ function register_hook($hook, $file, $function, $priority = 0) { | ||||
| 		dbesc($function), | ||||
| 		dbesc($priority) | ||||
| 	); | ||||
|  | ||||
| 	return $r; | ||||
| } | ||||
|  | ||||
| @@ -206,7 +205,7 @@ function register_hook($hook, $file, $function, $priority = 0) { | ||||
|  * @param string $hook the name of the hook | ||||
|  * @param string $file the name of the file that hooks into | ||||
|  * @param string $function the name of the function that the hook called | ||||
|  * @return mixed | ||||
|  * @return array | ||||
|  */ | ||||
| function unregister_hook($hook, $file, $function) { | ||||
| 	$r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `function` = '%s'", | ||||
| @@ -214,6 +213,7 @@ function unregister_hook($hook, $file, $function) { | ||||
| 		dbesc($file), | ||||
| 		dbesc($function) | ||||
| 	); | ||||
|  | ||||
| 	return $r; | ||||
| } | ||||
|  | ||||
| @@ -243,8 +243,7 @@ function load_hooks() { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @function insert_hook($hook,$fn) | ||||
|  * @brief Inserts a hook into a page request. | ||||
|  * | ||||
|  * Insert a short-lived hook into the running page request.  | ||||
|  * Hooks are normally persistent so that they can be called  | ||||
| @@ -255,9 +254,9 @@ function load_hooks() { | ||||
|  * which will not persist beyond the life of this page request | ||||
|  * or the current process.  | ||||
|  * | ||||
|  * @param string $hook; | ||||
|  * @param string $hook | ||||
|  *     name of hook to attach callback | ||||
|  * @param string $fn; | ||||
|  * @param string $fn | ||||
|  *     function name of callback handler | ||||
|  */  | ||||
| function insert_hook($hook, $fn) { | ||||
| @@ -305,9 +304,10 @@ function call_hooks($name, &$data = null) { | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief parse plugin comment in search of plugin infos. | ||||
|  * @brief Parse plugin comment in search of plugin infos. | ||||
|  * | ||||
|  * like | ||||
|  * \code | ||||
|  *   * Name: Plugin | ||||
|  *   * Description: A plugin which plugs in | ||||
|  *   * Version: 1.2.3 | ||||
| @@ -315,7 +315,7 @@ function call_hooks($name, &$data = null) { | ||||
|  *   * Author: Jane <email> | ||||
|  *   * Compat: Red [(version)], Friendica [(version)] | ||||
|  *   * | ||||
|  * | ||||
|  *\endcode | ||||
|  * @param string $plugin the name of the plugin | ||||
|  * @return array with the plugin information | ||||
|  */ | ||||
| @@ -363,9 +363,10 @@ function get_plugin_info($plugin){ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief parse theme comment in search of theme infos. | ||||
|  * @brief Parse theme comment in search of theme infos. | ||||
|  * | ||||
|  * like | ||||
|  * \code | ||||
|  *   * Name: My Theme | ||||
|  *   * Description: My Cool Theme | ||||
|  *   * Version: 1.2.3 | ||||
| @@ -373,7 +374,7 @@ function get_plugin_info($plugin){ | ||||
|  *   * Maintainer: Jane <profile url> | ||||
|  *   * Compat: Friendica [(version)], Red [(version)] | ||||
|  *   * | ||||
|  * | ||||
|  * \endcode | ||||
|  * @param string $theme the name of the theme | ||||
|  * @return array | ||||
|  */ | ||||
| @@ -456,13 +457,11 @@ function get_theme_screenshot($theme) { | ||||
| 	return($a->get_baseurl() . '/images/blank.png'); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief add CSS to <head> | ||||
|  * @brief add CSS to \<head\> | ||||
|  * | ||||
|  * @param string $src | ||||
|  * @param string $media change media attribute (default to 'screen') | ||||
|  * @return void | ||||
|  */ | ||||
| function head_add_css($src, $media = 'screen') { | ||||
| 	get_app()->css_sources[] = array($src, $media); | ||||
| @@ -471,21 +470,23 @@ function head_add_css($src, $media = 'screen') { | ||||
| function head_remove_css($src, $media = 'screen') { | ||||
| 	$a = get_app(); | ||||
| 	$index = array_search(array($src, $media), $a->css_sources); | ||||
| 	if($index !== false) | ||||
| 	if ($index !== false) | ||||
| 		unset($a->css_sources[$index]); | ||||
| } | ||||
|  | ||||
| function head_get_css() { | ||||
| 	$str = ''; | ||||
| 	$sources = get_app()->css_sources; | ||||
| 	if(count($sources))  | ||||
| 		foreach($sources as $source) | ||||
| 	if (count($sources)) { | ||||
| 		foreach ($sources as $source) | ||||
| 			$str .= format_css_if_exists($source); | ||||
| 	} | ||||
|  | ||||
| 	return $str; | ||||
| } | ||||
|  | ||||
| function format_css_if_exists($source) { | ||||
| 	if(strpos($source[0], '/') !== false) | ||||
| 	if (strpos($source[0], '/') !== false) | ||||
| 		$path = $source[0]; | ||||
| 	else | ||||
| 		$path = theme_include($source[0]); | ||||
| @@ -592,6 +593,7 @@ function theme_include($file, $root = '') { | ||||
| 		if(file_exists($p)) | ||||
| 			return $p; | ||||
| 	} | ||||
|  | ||||
| 	return ''; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,305 +1,307 @@ | ||||
| <?php | ||||
| 	require_once 'include/ITemplateEngine.php'; | ||||
| require_once 'include/ITemplateEngine.php'; | ||||
|  | ||||
| 	define ("KEY_NOT_EXISTS", '^R_key_not_Exists^'); | ||||
| define ("KEY_NOT_EXISTS", '^R_key_not_Exists^'); | ||||
|  | ||||
| 	class Template implements ITemplateEngine { | ||||
| 		static $name ="internal"; | ||||
| class Template implements ITemplateEngine { | ||||
| 	static $name ="internal"; | ||||
|  | ||||
| 		var $r; | ||||
| 		var $search; | ||||
| 		var $replace; | ||||
| 		var $stack = array(); | ||||
| 		var $nodes = array(); | ||||
| 		var $done = false; | ||||
| 		var $d = false; | ||||
| 		var $lang = null; | ||||
| 		var $debug=false; | ||||
| 	var $r; | ||||
| 	var $search; | ||||
| 	var $replace; | ||||
| 	var $stack = array(); | ||||
| 	var $nodes = array(); | ||||
| 	var $done = false; | ||||
| 	var $d = false; | ||||
| 	var $lang = null; | ||||
| 	var $debug=false; | ||||
|  | ||||
| 		private function _preg_error(){ | ||||
| 			 | ||||
| 			switch(preg_last_error()){ | ||||
| 			    case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break; | ||||
| 			    case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break; | ||||
| 			    case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break; | ||||
| 			    case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break; | ||||
| 	private function _preg_error() { | ||||
| 		switch(preg_last_error()) { | ||||
| 			case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break; | ||||
| 			case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break; | ||||
| 			case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break; | ||||
| 			case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break; | ||||
| // This is only valid for php > 5.3, not certain how to code around it for unit tests | ||||
| //			    case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; | ||||
| 			    default: | ||||
| 					//die("Unknown preg error."); | ||||
| 					return; | ||||
| 			} | ||||
| 			echo "<hr><pre>"; | ||||
| 			debug_print_backtrace(); | ||||
| 			die(); | ||||
| 		} | ||||
| 		 | ||||
| 		 | ||||
| 		private function _push_stack(){ | ||||
| 			$this->stack[] = array($this->r, $this->nodes); | ||||
| 		} | ||||
| 		private function _pop_stack(){ | ||||
| 			list($this->r, $this->nodes) = array_pop($this->stack); | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
| 		private function _get_var($name, $retNoKey=false){ | ||||
| 			$keys = array_map('trim',explode(".",$name)); | ||||
| 			if ($retNoKey && !array_key_exists($keys[0], $this->r)) return KEY_NOT_EXISTS; | ||||
| 			$val = $this->r; | ||||
| 			foreach($keys as $k) { | ||||
| 				$val = (isset($val[$k]) ? $val[$k] : null); | ||||
| 			} | ||||
| 			return template_escape($val); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * IF node | ||||
| 		 *  | ||||
| 		 * {{ if <$var> }}...[{{ else }} ...] {{ endif }} | ||||
| 		 * {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }} | ||||
| 		 * {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }} | ||||
| 		 */ | ||||
| 		private function _replcb_if($args){ | ||||
| 			if (strpos($args[2],"==")>0){ | ||||
| 				list($a,$b) = array_map("trim",explode("==",$args[2])); | ||||
| 				$a = $this->_get_var($a); | ||||
| 				if ($b[0]=="$") $b =  $this->_get_var($b); | ||||
| 				$val = ($a == $b); | ||||
| 			} else if (strpos($args[2],"!=")>0){ | ||||
| 				list($a,$b) = array_map("trim", explode("!=",$args[2])); | ||||
| 				$a = $this->_get_var($a); | ||||
| 				if ($b[0]=="$") $b =  $this->_get_var($b); | ||||
| 				$val = ($a != $b); | ||||
| 			} else { | ||||
| 				$val = $this->_get_var($args[2]); | ||||
| 			} | ||||
| 			$x = preg_split("|{{ *else *}}|", $args[3]); | ||||
| 			return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : "")); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * FOR node | ||||
| 		 *  | ||||
| 		 * {{ for <$var> as $name }}...{{ endfor }} | ||||
| 		 * {{ for <$var> as $key=>$name }}...{{ endfor }} | ||||
| 		 */ | ||||
| 		private function _replcb_for($args){ | ||||
| 			$m = array_map('trim', explode(" as ", $args[2])); | ||||
| 			$x = explode("=>",$m[1]); | ||||
| 			if (count($x) == 1) { | ||||
| 				$varname = $x[0]; | ||||
| 				$keyname = ""; | ||||
| 			} else { | ||||
| 				list($keyname, $varname) = $x; | ||||
| 			} | ||||
| 			if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ; | ||||
| 			//$vals = $this->r[$m[0]]; | ||||
| 			$vals = $this->_get_var($m[0]); | ||||
| 			$ret=""; | ||||
| 			if (!is_array($vals)) return $ret;  | ||||
| 			foreach ($vals as $k=>$v){ | ||||
| 				$this->_push_stack(); | ||||
| 				$r = $this->r; | ||||
| 				$r[$varname] = $v; | ||||
| 				if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k); | ||||
| 				$ret .=  $this->replace($args[3], $r); | ||||
| 				$this->_pop_stack(); | ||||
| 			} | ||||
| 			return $ret; | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * INC node | ||||
| 		 *  | ||||
| 		 * {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }} | ||||
| 		 */ | ||||
| 		private function _replcb_inc($args){ | ||||
| 			if (strpos($args[2],"with")) { | ||||
| 				list($tplfile, $newctx) = array_map('trim', explode("with",$args[2])); | ||||
| 			} else { | ||||
| 				$tplfile = trim($args[2]); | ||||
| 				$newctx = null; | ||||
| 			} | ||||
| 			 | ||||
| 			if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile); | ||||
| 			 | ||||
| 			$this->_push_stack(); | ||||
| 			$r = $this->r; | ||||
| 			if (!is_null($newctx)) { | ||||
| 				list($a,$b) = array_map('trim', explode("=",$newctx)); | ||||
| 				$r[$a] = $this->_get_var($b);  | ||||
| 			} | ||||
| 			$this->nodes = Array(); | ||||
| 			$tpl = get_markup_template($tplfile); | ||||
| 			$ret = $this->replace($tpl, $r); | ||||
| 			$this->_pop_stack(); | ||||
| 			return $ret; | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * DEBUG node | ||||
| 		 *  | ||||
| 		 * {{ debug $var [$var [$var [...]]] }}{{ enddebug }} | ||||
| 		 *  | ||||
| 		 * replace node with <pre>var_dump($var, $var, ...);</pre> | ||||
| 		 */ | ||||
| 		private function _replcb_debug($args){ | ||||
| 			$vars = array_map('trim', explode(" ",$args[2])); | ||||
| 			$vars[] = $args[1]; | ||||
|  | ||||
| 			$ret = "<pre>"; | ||||
| 			foreach ($vars as $var){ | ||||
| 				$ret .= htmlspecialchars(var_export( $this->_get_var($var), true )); | ||||
| 				$ret .= "\n"; | ||||
| 			} | ||||
| 			$ret .= "</pre>"; | ||||
| 			return $ret; | ||||
| 		} | ||||
|  | ||||
| 		private function _replcb_node($m) { | ||||
| 			$node = $this->nodes[$m[1]]; | ||||
| 			if (method_exists($this, "_replcb_".$node[1])){ | ||||
| 				$s = call_user_func(array($this, "_replcb_".$node[1]),  $node); | ||||
| 			} else { | ||||
| 				$s = ""; | ||||
| 			} | ||||
| 			$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); | ||||
| 			return $s; | ||||
| 		} | ||||
| 						 | ||||
| 		private function _replcb($m){ | ||||
| 			//var_dump(array_map('htmlspecialchars', $m)); | ||||
| 			$this->done = false;	 | ||||
| 			$this->nodes[] = (array) $m; | ||||
| 			return "||". (count($this->nodes)-1) ."||"; | ||||
| 		} | ||||
| 		 | ||||
| 		private function _build_nodes($s){ | ||||
| 			$this->done = false; | ||||
| 			while (!$this->done){ | ||||
| 				$this->done=true; | ||||
| 				$s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s); | ||||
| 				if ($s==Null) $this->_preg_error(); | ||||
| 			} | ||||
| 			//({{ *else *}}[^{]*)? | ||||
| 			krsort($this->nodes); | ||||
| 			return $s; | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		private function var_replace($s){ | ||||
| 			$m = array(); | ||||
| 			/** regexp: | ||||
| 			 * \$ 						literal $ | ||||
| 			 * (\[)?					optional open square bracket | ||||
| 			 * ([a-zA-Z0-9-_]+\.?)+		var name, followed by optional | ||||
| 			 * 							dot, repeated at least 1 time | ||||
| 			 * (?(1)\])					if there was opened square bracket | ||||
| 			 * 							(subgrup 1), match close bracket | ||||
| 			 */ | ||||
| 			if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)){ | ||||
| 					foreach($m[0] as $var){ | ||||
|  | ||||
|               $exp = str_replace(array("[", "]"), array("", ""), $var); | ||||
|                 $exptks = explode("|", $exp); | ||||
|  | ||||
|                 $varn = $exptks[0]; | ||||
|                 unset($exptks[0]); | ||||
|                 $val = $this->_get_var($varn, true); | ||||
|                 if ($val != KEY_NOT_EXISTS) { | ||||
|                     /* run filters */ | ||||
|                     /* | ||||
|                      * Filter are in form of: | ||||
|                      * filtername:arg:arg:arg | ||||
|                      * | ||||
|                      * "filtername" is function name | ||||
|                      * "arg"s are optional, var value is appended to the end | ||||
|                      *          if one "arg"==='x' , is replaced with var value | ||||
|                      * | ||||
|                      * examples: | ||||
|                      * $item.body|htmlspecialchars              // escape html chars | ||||
|                      * $item.body|htmlspecialchars|strtoupper   // escape html and uppercase result | ||||
|                      * $item.created|date:%Y %M %j              // format date (created is a timestamp) | ||||
|                      * $item.body|str_replace:cat:dog           // replace all "cat" with "dog" | ||||
|                      * $item.body|str_replace:cat:dog:x:1       // replace one "cat" with "dog" | ||||
|  | ||||
|                      */ | ||||
|                     foreach ($exptks as $filterstr) { | ||||
|                         $filter = explode(":", $filterstr); | ||||
|                         $filtername = $filter[0]; | ||||
|                         unset($filter[0]); | ||||
|                         $valkey = array_search("x", $filter); | ||||
|                         if ($valkey === false) { | ||||
|                             $filter[] = $val; | ||||
|                         } else { | ||||
|                             $filter[$valkey] = $val; | ||||
|                         } | ||||
|                         if (function_exists($filtername)) { | ||||
|                             $val = call_user_func_array($filtername, $filter); | ||||
|                         } | ||||
|                     } | ||||
|                     $s = str_replace($var, $val, $s); | ||||
|  | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			return $s; | ||||
| 		} | ||||
| 		 | ||||
| 		private function replace($s,$r) { | ||||
| 			$this->replace_macros($s, $r); | ||||
| 		} | ||||
| 		 | ||||
| 		// TemplateEngine interface | ||||
| 		public function replace_macros($s, $r) { | ||||
| 			$this->r = $r; | ||||
| 			 | ||||
| 			$s = $this->_build_nodes($s); | ||||
|  | ||||
| 			$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); | ||||
| 			if ($s==Null) $this->_preg_error(); | ||||
| 			 | ||||
| 			// remove comments block | ||||
| 			$s = preg_replace('/{#[^#]*#}/', "" , $s); | ||||
| 			 | ||||
| 			$t2 = dba_timer(); | ||||
|  | ||||
| 			// replace strings recursively (limit to 10 loops) | ||||
| 			$os = ""; $count=0; | ||||
| 			while(($os !== $s) && $count<10){ | ||||
| 				$os=$s; $count++; | ||||
| 				$s = $this->var_replace($s); | ||||
| 			} | ||||
| 			return $s; | ||||
| 		} | ||||
|  | ||||
| 		public function get_markup_template($file, $root='') { | ||||
| 			$template_file = theme_include($file, $root); | ||||
| 			if ($template_file) { | ||||
| 				$content = file_get_contents($template_file); | ||||
| 			} | ||||
| 			return $content;		 | ||||
| //			case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; | ||||
| 			default: | ||||
| 				//die("Unknown preg error."); | ||||
| 				return; | ||||
| 		} | ||||
| 		echo "<hr><pre>"; | ||||
| 		debug_print_backtrace(); | ||||
| 		die(); | ||||
| 	} | ||||
|  | ||||
| 	private function _push_stack() { | ||||
| 		$this->stack[] = array($this->r, $this->nodes); | ||||
| 	} | ||||
|  | ||||
| 	private function _pop_stack(){ | ||||
| 		list($this->r, $this->nodes) = array_pop($this->stack); | ||||
| 	} | ||||
|  | ||||
| 	private function _get_var($name, $retNoKey=false) { | ||||
| 		$keys = array_map('trim',explode(".",$name)); | ||||
| 		if ($retNoKey && !array_key_exists($keys[0], $this->r)) | ||||
| 			return KEY_NOT_EXISTS; | ||||
|  | ||||
| 		$val = $this->r; | ||||
| 		foreach($keys as $k) { | ||||
| 			$val = (isset($val[$k]) ? $val[$k] : null); | ||||
| 		} | ||||
|  | ||||
| 		return template_escape($val); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * IF node | ||||
| 	 * \code | ||||
| 	 * {{ if <$var> }}...[{{ else }} ...] {{ endif }} | ||||
| 	 * {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }} | ||||
| 	 * {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }} | ||||
| 	 * \endcode | ||||
| 	 */ | ||||
| 	private function _replcb_if($args) { | ||||
| 		if (strpos($args[2],"==")>0){ | ||||
| 			list($a,$b) = array_map("trim",explode("==",$args[2])); | ||||
| 			$a = $this->_get_var($a); | ||||
| 			if ($b[0]=="$") $b =  $this->_get_var($b); | ||||
| 			$val = ($a == $b); | ||||
| 		} else if (strpos($args[2],"!=")>0){ | ||||
| 			list($a,$b) = array_map("trim", explode("!=",$args[2])); | ||||
| 			$a = $this->_get_var($a); | ||||
| 			if ($b[0]=="$") $b =  $this->_get_var($b); | ||||
| 			$val = ($a != $b); | ||||
| 		} else { | ||||
| 			$val = $this->_get_var($args[2]); | ||||
| 		} | ||||
| 		$x = preg_split("|{{ *else *}}|", $args[3]); | ||||
|  | ||||
| 		return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : "")); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * FOR node | ||||
| 	 * \code | ||||
| 	 * {{ for <$var> as $name }}...{{ endfor }} | ||||
| 	 * {{ for <$var> as $key=>$name }}...{{ endfor }} | ||||
| 	 * \endcode | ||||
| 	 */ | ||||
| 	private function _replcb_for($args) { | ||||
| 		$m = array_map('trim', explode(" as ", $args[2])); | ||||
| 		$x = explode("=>",$m[1]); | ||||
| 		if (count($x) == 1) { | ||||
| 			$varname = $x[0]; | ||||
| 			$keyname = ""; | ||||
| 		} else { | ||||
| 			list($keyname, $varname) = $x; | ||||
| 		} | ||||
| 		if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ; | ||||
| 		//$vals = $this->r[$m[0]]; | ||||
| 		$vals = $this->_get_var($m[0]); | ||||
| 		$ret=""; | ||||
| 		if (!is_array($vals)) return $ret; | ||||
|  | ||||
| 		foreach ($vals as $k=>$v){ | ||||
| 			$this->_push_stack(); | ||||
| 			$r = $this->r; | ||||
| 			$r[$varname] = $v; | ||||
| 			if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k); | ||||
| 			$ret .=  $this->replace($args[3], $r); | ||||
| 			$this->_pop_stack(); | ||||
| 		} | ||||
|  | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * INC node | ||||
| 	 * \code | ||||
| 	 * {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }} | ||||
| 	 * \endcode | ||||
| 	 */ | ||||
| 	private function _replcb_inc($args) { | ||||
| 		if (strpos($args[2],"with")) { | ||||
| 			list($tplfile, $newctx) = array_map('trim', explode("with",$args[2])); | ||||
| 		} else { | ||||
| 			$tplfile = trim($args[2]); | ||||
| 			$newctx = null; | ||||
| 		} | ||||
|  | ||||
| 		if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile); | ||||
|  | ||||
| 		$this->_push_stack(); | ||||
| 		$r = $this->r; | ||||
| 		if (!is_null($newctx)) { | ||||
| 			list($a,$b) = array_map('trim', explode("=",$newctx)); | ||||
| 			$r[$a] = $this->_get_var($b);  | ||||
| 		} | ||||
| 		$this->nodes = Array(); | ||||
| 		$tpl = get_markup_template($tplfile); | ||||
| 		$ret = $this->replace($tpl, $r); | ||||
| 		$this->_pop_stack(); | ||||
|  | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * DEBUG node | ||||
| 	 * \code | ||||
| 	 * {{ debug $var [$var [$var [...]]] }}{{ enddebug }} | ||||
| 	 * \endcode | ||||
| 	 * replace node with <pre>var_dump($var, $var, ...);</pre> | ||||
| 	 */ | ||||
| 	private function _replcb_debug($args) { | ||||
| 		$vars = array_map('trim', explode(" ",$args[2])); | ||||
| 		$vars[] = $args[1]; | ||||
|  | ||||
| 		$ret = "<pre>"; | ||||
| 		foreach ($vars as $var){ | ||||
| 			$ret .= htmlspecialchars(var_export( $this->_get_var($var), true )); | ||||
| 			$ret .= "\n"; | ||||
| 		} | ||||
| 		$ret .= "</pre>"; | ||||
|  | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	private function _replcb_node($m) { | ||||
| 		$node = $this->nodes[$m[1]]; | ||||
| 		if (method_exists($this, "_replcb_".$node[1])){ | ||||
| 			$s = call_user_func(array($this, "_replcb_".$node[1]),  $node); | ||||
| 		} else { | ||||
| 			$s = ""; | ||||
| 		} | ||||
| 		$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); | ||||
|  | ||||
| 		return $s; | ||||
| 	} | ||||
|  | ||||
| 	private function _replcb($m) { | ||||
| 		//var_dump(array_map('htmlspecialchars', $m)); | ||||
| 		$this->done = false; | ||||
| 		$this->nodes[] = (array) $m; | ||||
|  | ||||
| 		return "||". (count($this->nodes)-1) ."||"; | ||||
| 	} | ||||
|  | ||||
| 	private function _build_nodes($s) { | ||||
| 		$this->done = false; | ||||
| 		while (!$this->done) { | ||||
| 			$this->done=true; | ||||
| 			$s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s); | ||||
| 			if ($s==Null) $this->_preg_error(); | ||||
| 		} | ||||
| 		//({{ *else *}}[^{]*)? | ||||
| 		krsort($this->nodes); | ||||
|  | ||||
| 		return $s; | ||||
| 	} | ||||
|  | ||||
| 	private function var_replace($s) { | ||||
| 		$m = array(); | ||||
| 		/** regexp: | ||||
| 		 * \$ 						literal $ | ||||
| 		 * (\[)?					optional open square bracket | ||||
| 		 * ([a-zA-Z0-9-_]+\.?)+		var name, followed by optional | ||||
| 		 * 							dot, repeated at least 1 time | ||||
| 		 * (?(1)\])					if there was opened square bracket | ||||
| 		 * 							(subgrup 1), match close bracket | ||||
| 		 */ | ||||
| 		if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)) { | ||||
| 			foreach ($m[0] as $var) { | ||||
| 				$exp = str_replace(array("[", "]"), array("", ""), $var); | ||||
| 				$exptks = explode("|", $exp); | ||||
|  | ||||
| 				$varn = $exptks[0]; | ||||
| 				unset($exptks[0]); | ||||
| 				$val = $this->_get_var($varn, true); | ||||
| 				if ($val != KEY_NOT_EXISTS) { | ||||
| 					/* run filters */ | ||||
| 					/* | ||||
| 					 * Filter are in form of: | ||||
| 					 * filtername:arg:arg:arg | ||||
| 					 * | ||||
| 					 * "filtername" is function name | ||||
| 					 * "arg"s are optional, var value is appended to the end | ||||
| 					 *          if one "arg"==='x' , is replaced with var value | ||||
| 					 * | ||||
| 					 * examples: | ||||
| 					 * $item.body|htmlspecialchars              // escape html chars | ||||
| 					 * $item.body|htmlspecialchars|strtoupper   // escape html and uppercase result | ||||
| 					 * $item.created|date:%Y %M %j              // format date (created is a timestamp) | ||||
| 					 * $item.body|str_replace:cat:dog           // replace all "cat" with "dog" | ||||
| 					 * $item.body|str_replace:cat:dog:x:1       // replace one "cat" with "dog" | ||||
| 					 */ | ||||
| 					foreach ($exptks as $filterstr) { | ||||
| 						$filter = explode(":", $filterstr); | ||||
| 						$filtername = $filter[0]; | ||||
| 						unset($filter[0]); | ||||
| 						$valkey = array_search("x", $filter); | ||||
| 						if ($valkey === false) { | ||||
| 							$filter[] = $val; | ||||
| 						} else { | ||||
| 							$filter[$valkey] = $val; | ||||
| 						} | ||||
| 						if (function_exists($filtername)) { | ||||
| 							$val = call_user_func_array($filtername, $filter); | ||||
| 						} | ||||
| 					} | ||||
| 					$s = str_replace($var, $val, $s); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return $s; | ||||
| 	} | ||||
|  | ||||
| 	private function replace($s, $r) { | ||||
| 		$this->replace_macros($s, $r); | ||||
| 	} | ||||
|  | ||||
| 	// TemplateEngine interface | ||||
| 	public function replace_macros($s, $r) { | ||||
| 		$this->r = $r; | ||||
|  | ||||
| 		$s = $this->_build_nodes($s); | ||||
|  | ||||
| 		$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); | ||||
| 		if ($s == Null) | ||||
| 			$this->_preg_error(); | ||||
|  | ||||
| 		// remove comments block | ||||
| 		$s = preg_replace('/{#[^#]*#}/', "" , $s); | ||||
|  | ||||
| 		//$t2 = dba_timer(); | ||||
|  | ||||
| 		// replace strings recursively (limit to 10 loops) | ||||
| 		$os = ""; | ||||
| 		$count=0; | ||||
| 		while (($os !== $s) && $count<10) { | ||||
| 			$os=$s; | ||||
| 			$count++; | ||||
| 			$s = $this->var_replace($s); | ||||
| 		} | ||||
|  | ||||
| 		return $s; | ||||
| 	} | ||||
|  | ||||
| 	public function get_markup_template($file, $root='') { | ||||
| 		$template_file = theme_include($file, $root); | ||||
| 		if ($template_file) { | ||||
| 			$content = file_get_contents($template_file); | ||||
| 		} | ||||
|  | ||||
| 		return $content; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| function template_escape($s) { | ||||
|  | ||||
| 	return str_replace(array('$','{{'),array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),$s); | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| function template_unescape($s) { | ||||
|  | ||||
| 	return str_replace(array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),array('$','{{'),$s); | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										319
									
								
								include/text.php
									
									
									
									
									
								
							
							
						
						
									
										319
									
								
								include/text.php
									
									
									
									
									
								
							| @@ -1,18 +1,26 @@ | ||||
| <?php /** @file */ | ||||
|  | ||||
| <?php | ||||
| /** | ||||
|  * @file include/text.php | ||||
|  */ | ||||
|  | ||||
| require_once("include/template_processor.php"); | ||||
| require_once("include/smarty.php"); | ||||
|  | ||||
| // random string, there are 86 characters max in text mode, 128 for hex | ||||
| // output is urlsafe | ||||
|  | ||||
| define('RANDOM_STRING_HEX',  0x00 ); | ||||
| define('RANDOM_STRING_TEXT', 0x01 ); | ||||
|  | ||||
| /** | ||||
|  * This is our template processor | ||||
|  * @brief This is our template processor. | ||||
|  * | ||||
|  * @param string|FriendicaSmarty $s the string requiring macro substitution, | ||||
|  *									or an instance of FriendicaSmarty | ||||
|  *   or an instance of FriendicaSmarty | ||||
|  * @param array $r key value pairs (search => replace) | ||||
|  * @return string substituted string | ||||
|  */ | ||||
| function replace_macros($s,$r) { | ||||
| function replace_macros($s, $r) { | ||||
| 	$a = get_app(); | ||||
|  | ||||
| 	$arr = array('template' => $s, 'params' => $r); | ||||
| @@ -24,23 +32,23 @@ function replace_macros($s,$r) { | ||||
| 	return $output; | ||||
| } | ||||
|  | ||||
|  | ||||
| // random string, there are 86 characters max in text mode, 128 for hex | ||||
| // output is urlsafe | ||||
|  | ||||
| define('RANDOM_STRING_HEX',  0x00 ); | ||||
| define('RANDOM_STRING_TEXT', 0x01 ); | ||||
|  | ||||
|  | ||||
| function random_string($size = 64,$type = RANDOM_STRING_HEX) { | ||||
| /** | ||||
|  * @brief Generates a random string. | ||||
|  * | ||||
|  * @param number $size | ||||
|  * @param int $type | ||||
|  * @return string | ||||
|  */ | ||||
| function random_string($size = 64, $type = RANDOM_STRING_HEX) { | ||||
| 	// generate a bit of entropy and run it through the whirlpool | ||||
| 	$s = hash('whirlpool', (string) rand() . uniqid(rand(),true) . (string) rand(),(($type == RANDOM_STRING_TEXT) ? true : false)); | ||||
| 	$s = (($type == RANDOM_STRING_TEXT) ? str_replace("\n","",base64url_encode($s,true)) : $s); | ||||
| 	return(substr($s,0,$size)); | ||||
|  | ||||
| 	return(substr($s, 0, $size)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * This is our primary input filter. | ||||
|  * @brief This is our primary input filter. | ||||
|  * | ||||
|  * The high bit hack only involved some old IE browser, forget which (IE5/Mac?) | ||||
|  * that had an XSS attack vector due to stripping the high-bit on an 8-bit character | ||||
| @@ -56,8 +64,6 @@ function random_string($size = 64,$type = RANDOM_STRING_HEX) { | ||||
|  * @param string $string Input string | ||||
|  * @return string Filtered string | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function notags($string) { | ||||
|  | ||||
| 	return(str_replace(array("<",">"), array('[',']'), $string)); | ||||
| @@ -105,7 +111,6 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { | ||||
| 		return purify_html($s); | ||||
|  | ||||
| 	return escape_tags($s); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -114,39 +119,38 @@ function purify_html($s) { | ||||
| 	require_once('library/HTMLPurifier.auto.php'); | ||||
| 	require_once('include/html2bbcode.php'); | ||||
|  | ||||
| // FIXME this function has html output, not bbcode - so safely purify these | ||||
| //	$s = html2bb_video($s); | ||||
| //	$s = oembed_html2bbcode($s); | ||||
| /** | ||||
|  * @FIXME this function has html output, not bbcode - so safely purify these | ||||
|  * $s = html2bb_video($s); | ||||
|  * $s = oembed_html2bbcode($s); | ||||
|  */ | ||||
|  | ||||
| 	$config = HTMLPurifier_Config::createDefault(); | ||||
| 	$config->set('Cache.DefinitionImpl', null); | ||||
| 	$config->set('Attr.EnableID', true); | ||||
|  | ||||
| 	$purifier = new HTMLPurifier($config); | ||||
|  | ||||
| 	return $purifier->purify($s); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| // generate a string that's random, but usually pronounceable.  | ||||
| // used to generate initial passwords | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * generate a string that's random, but usually pronounceable.  | ||||
|  * used to generate initial passwords | ||||
|  * @brief generate a string that's random, but usually pronounceable. | ||||
|  * | ||||
|  * Used to generate initial passwords. | ||||
|  * | ||||
|  * @param int $len | ||||
|  * @return string | ||||
|  */ | ||||
| function autoname($len) { | ||||
|  | ||||
| 	if($len <= 0) | ||||
| 	if ($len <= 0) | ||||
| 		return ''; | ||||
|  | ||||
| 	$vowels = array('a','a','ai','au','e','e','e','ee','ea','i','ie','o','ou','u');  | ||||
| 	if(mt_rand(0,5) == 4) | ||||
| 	if (mt_rand(0, 5) == 4) | ||||
| 		$vowels[] = 'y'; | ||||
|  | ||||
| 	$cons = array( | ||||
| @@ -178,8 +182,8 @@ function autoname($len) { | ||||
| 	$noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr', | ||||
| 				'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh'); | ||||
|  | ||||
| 	$start = mt_rand(0,2); | ||||
| 	if($start == 0) | ||||
| 	$start = mt_rand(0, 2); | ||||
| 	if ($start == 0) | ||||
| 		$table = $vowels; | ||||
| 	else | ||||
| 		$table = $cons; | ||||
| @@ -190,33 +194,30 @@ function autoname($len) { | ||||
| 		$r = mt_rand(0,count($table) - 1); | ||||
| 		$word .= $table[$r]; | ||||
|  | ||||
| 		if($table == $vowels) | ||||
| 			$table = array_merge($cons,$midcons); | ||||
| 		if ($table == $vowels) | ||||
| 			$table = array_merge($cons, $midcons); | ||||
| 		else | ||||
| 			$table = $vowels; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	$word = substr($word,0,$len); | ||||
|  | ||||
| 	foreach($noend as $noe) { | ||||
| 		if((strlen($word) > 2) && (substr($word,-2) == $noe)) { | ||||
| 	foreach ($noend as $noe) { | ||||
| 		if ((strlen($word) > 2) && (substr($word,-2) == $noe)) { | ||||
| 			$word = substr($word,0,-1); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if(substr($word,-1) == 'q') | ||||
| 		$word = substr($word,0,-1); | ||||
| 	if (substr($word, -1) == 'q') | ||||
| 		$word = substr($word, 0, -1); | ||||
|  | ||||
| 	return $word; | ||||
| } | ||||
|  | ||||
|  | ||||
| // escape text ($str) for XML transport | ||||
| // returns escaped text. | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * escape text ($str) for XML transport | ||||
|  * @brief escape text ($str) for XML transport | ||||
|  * | ||||
|  * @param string $str | ||||
|  * @return string Escaped text. | ||||
|  */ | ||||
| @@ -228,7 +229,6 @@ function xmlify($str) { | ||||
| 		$char = mb_substr($str,$x,1); | ||||
|  | ||||
| 		switch( $char ) { | ||||
|  | ||||
| 			case "\r" : | ||||
| 				break; | ||||
| 			case "&" : | ||||
| @@ -255,6 +255,7 @@ function xmlify($str) { | ||||
| 		} | ||||
| 	} | ||||
| 	$buffer = trim($buffer); | ||||
|  | ||||
| 	return($buffer); | ||||
| } | ||||
|  | ||||
| @@ -268,10 +269,12 @@ function unxmlify($s) { | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
| // convenience wrapper, reverse the operation "bin2hex" | ||||
|  | ||||
| // This is a built-in function in php >= 5.4 | ||||
|  | ||||
| /** | ||||
|  * Convenience wrapper, reverse the operation "bin2hex" | ||||
|  * This is a built-in function in php >= 5.4 | ||||
|  * | ||||
|  * @FIXME We already have php >= 5.4 requirements, so can we remove this? | ||||
|  */ | ||||
| if(! function_exists('hex2bin')) { | ||||
| function hex2bin($s) { | ||||
| 	if(! (is_string($s) && strlen($s))) | ||||
| @@ -381,14 +384,16 @@ function alt_pager(&$a, $i, $more = '', $less = '') { | ||||
|  | ||||
| } | ||||
|  | ||||
| // Turn user/group ACLs stored as angle bracketed text into arrays | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Turn user/group ACLs stored as angle bracketed text into arrays. | ||||
|  * | ||||
|  * turn string array of angle-bracketed elements into string array | ||||
|  * e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e); | ||||
|  * | ||||
|  * @param string $s | ||||
|  * @return array | ||||
|  */ | ||||
| function expand_acl($s) { | ||||
|  | ||||
| 	// turn string array of angle-bracketed elements into string array | ||||
| 	// e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e); | ||||
|  | ||||
| 	$ret = array(); | ||||
|  | ||||
| 	if(strlen($s)) { | ||||
| @@ -399,34 +404,41 @@ function expand_acl($s) { | ||||
| 				$ret[] = $aa; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
| // Used to wrap ACL elements in angle brackets for storage  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Used to wrap ACL elements in angle brackets for storage. | ||||
|  * | ||||
|  * @param[in,out] array &$item | ||||
|  */ | ||||
| function sanitise_acl(&$item) { | ||||
| 	if(strlen($item)) | ||||
| 	if (strlen($item)) | ||||
| 		$item = '<' . notags(trim($item)) . '>'; | ||||
| 	else | ||||
| 		unset($item); | ||||
| } | ||||
|  | ||||
|  | ||||
| // Convert an ACL array to a storable string | ||||
|  | ||||
| /** | ||||
|  * @brief Convert an ACL array to a storable string. | ||||
|  * | ||||
|  * @param array $p | ||||
|  * @return array | ||||
|  */ | ||||
| function perms2str($p) { | ||||
| 	$ret = ''; | ||||
|  | ||||
| 	if(is_array($p)) | ||||
| 	if (is_array($p)) | ||||
| 		$tmp = $p; | ||||
| 	else | ||||
| 		$tmp = explode(',',$p); | ||||
| 		$tmp = explode(',', $p); | ||||
|  | ||||
| 	if(is_array($tmp)) { | ||||
| 		array_walk($tmp,'sanitise_acl'); | ||||
| 		$ret = implode('',$tmp); | ||||
| 	if (is_array($tmp)) { | ||||
| 		array_walk($tmp, 'sanitise_acl'); | ||||
| 		$ret = implode('', $tmp); | ||||
| 	} | ||||
|  | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
| @@ -858,51 +870,48 @@ function valid_email($x){ | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Replace naked text hyperlink with HTML formatted hyperlink. | ||||
|  * | ||||
|  * Function: linkify | ||||
|  * | ||||
|  * Replace naked text hyperlink with HTML formatted hyperlink | ||||
|  * | ||||
|  * @param string $s | ||||
|  * @param boolean $me (optional) default false | ||||
|  * @return string | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function linkify($s,$me = false) { | ||||
| function linkify($s, $me = false) { | ||||
| 	$s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+\,\@]*)/", (($me) ? ' <a href="$1" rel="me" >$1</a>' : ' <a href="$1" >$1</a>'), $s); | ||||
| 	$s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$s); | ||||
|  | ||||
| 	return($s); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function sslify($s) | ||||
|  *    Replace media element using http url with https to a local redirector if using https locally | ||||
|  * @param string $s | ||||
|  * @brief Replace media element using http url with https to a local redirector | ||||
|  *  if using https locally. | ||||
|  * | ||||
|  * Looks for HTML tags containing src elements that are http when we're viewing an https page | ||||
|  * Typically this throws an insecure content violation in the browser. So we redirect them | ||||
|  * to a local redirector which uses https and which redirects to the selected content | ||||
|  * | ||||
|  * @param string $s | ||||
|  * @returns string | ||||
|  */ | ||||
| function sslify($s) { | ||||
| 	if(strpos(z_root(),'https:') === false) | ||||
| 	if (strpos(z_root(),'https:') === false) | ||||
| 		return $s; | ||||
|  | ||||
| 	$matches = null; | ||||
| 	$cnt = preg_match_all("/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/",$s,$matches,PREG_SET_ORDER); | ||||
| 	if($cnt) { | ||||
| 		foreach($matches as $match) { | ||||
| 			$filename = basename( parse_url($match[2],PHP_URL_PATH) ); | ||||
| 	if ($cnt) { | ||||
| 		foreach ($matches as $match) { | ||||
| 			$filename = basename( parse_url($match[2], PHP_URL_PATH) ); | ||||
| 			$s = str_replace($match[2],z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($match[2]),$s); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return $s; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| function get_poke_verbs() { | ||||
| 	// index is present tense verb | ||||
| 	// value is array containing past tense verb, translation of present, translation of past | ||||
| @@ -1033,18 +1042,11 @@ function list_smilies() { | ||||
|  | ||||
| 	$params = array('texts' => $texts, 'icons' => $icons); | ||||
| 	call_hooks('smilie', $params); | ||||
|  | ||||
| 	return $params; | ||||
| } | ||||
| /** | ||||
|  *  | ||||
|  * Function: smilies | ||||
|  * | ||||
|  * Description: | ||||
|  * Replaces text emoticons with graphical images | ||||
|  * | ||||
|  * @Parameter: string $s | ||||
|  * | ||||
|  * Returns string | ||||
|  * @brief Replaces text emoticons with graphical images. | ||||
|  * | ||||
|  * It is expected that this function will be called using HTML text. | ||||
|  * We will escape text between HTML pre and code blocks, and HTML attributes | ||||
| @@ -1052,28 +1054,30 @@ function list_smilies() { | ||||
|  * | ||||
|  * At a higher level, the bbcode [nosmile] tag can be used to prevent this  | ||||
|  * function from being executed by the prepare_text() routine when preparing | ||||
|  * bbcode source for HTML display | ||||
|  * bbcode source for HTML display. | ||||
|  * | ||||
|  * @param string $s | ||||
|  * @param boolean $sample (optional) default false | ||||
|  * @return string | ||||
|  */ | ||||
| function smilies($s, $sample = false) { | ||||
|  | ||||
| 	if(intval(get_config('system','no_smilies'))  | ||||
| 		|| (local_channel() && intval(get_pconfig(local_channel(),'system','no_smilies')))) | ||||
| 	if(intval(get_config('system', 'no_smilies'))  | ||||
| 		|| (local_channel() && intval(get_pconfig(local_channel(), 'system', 'no_smilies')))) | ||||
| 		return $s; | ||||
|  | ||||
| 	$s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism','smile_shield',$s); | ||||
| 	$s = preg_replace_callback('/<[a-z]+ .*?>/ism','smile_shield',$s); | ||||
| 	$s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism', 'smile_shield', $s); | ||||
| 	$s = preg_replace_callback('/<[a-z]+ .*?>/ism', 'smile_shield', $s); | ||||
|  | ||||
| 	$params = list_smilies(); | ||||
| 	$params['string'] = $s; | ||||
|  | ||||
| 	if($sample) { | ||||
| 	if ($sample) { | ||||
| 		$s = '<div class="smiley-sample">'; | ||||
| 		for($x = 0; $x < count($params['texts']); $x ++) { | ||||
| 		for ($x = 0; $x < count($params['texts']); $x ++) { | ||||
| 			$s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>'; | ||||
| 		} | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$params['string'] = preg_replace_callback('/<(3+)/','preg_heart',$params['string']); | ||||
| 		$s = str_replace($params['texts'],$params['icons'],$params['string']); | ||||
| 	} | ||||
| @@ -1083,6 +1087,12 @@ function smilies($s, $sample = false) { | ||||
| 	return $s; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief | ||||
|  * | ||||
|  * @param array $m | ||||
|  * @return string | ||||
|  */ | ||||
| function smile_shield($m) { | ||||
| 	return '<!--base64:' . base64url_encode($m[0]) . '-->'; | ||||
| } | ||||
| @@ -1091,16 +1101,22 @@ function smile_unshield($m) { | ||||
| 	return base64url_decode($m[1]);  | ||||
| } | ||||
|  | ||||
| // expand <3333 to the correct number of hearts | ||||
|  | ||||
| /** | ||||
|  * @brief Expand <3333 to the correct number of hearts. | ||||
|  * | ||||
|  * @param array $x | ||||
|  */ | ||||
| function preg_heart($x) { | ||||
| 	$a = get_app(); | ||||
| 	if(strlen($x[1]) == 1) | ||||
| 	if (strlen($x[1]) == 1) | ||||
| 		return $x[0]; | ||||
|  | ||||
| 	$t = ''; | ||||
| 	for($cnt = 0; $cnt < strlen($x[1]); $cnt ++) | ||||
| 		$t .= '<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-heart.gif" alt="<3" />'; | ||||
|  | ||||
| 	$r =  str_replace($x[0],$t,$x[0]); | ||||
|  | ||||
| 	return $r; | ||||
| } | ||||
|  | ||||
| @@ -1118,27 +1134,33 @@ function day_translate($s) { | ||||
| 	return $ret; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief normalises a string. | ||||
|  * | ||||
|  * @param string $url | ||||
|  * @return string | ||||
|  */ | ||||
| function normalise_link($url) { | ||||
| 	$ret = str_replace(array('https:','//www.'), array('http:','//'), $url); | ||||
| 	return(rtrim($ret,'/')); | ||||
| 	$ret = str_replace(array('https:', '//www.'), array('http:', '//'), $url); | ||||
|  | ||||
| 	return(rtrim($ret, '/')); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Compare two URLs to see if they are the same. | ||||
|  * | ||||
|  * Compare two URLs to see if they are the same, but ignore | ||||
|  * slight but hopefully insignificant differences such as if one  | ||||
|  * is https and the other isn't, or if one is www.something and  | ||||
|  * the other isn't - and also ignore case differences. | ||||
|  * But ignore slight but hopefully insignificant differences such as if one | ||||
|  * is https and the other isn't, or if one is www.something and the other | ||||
|  * isn't - and also ignore case differences. | ||||
|  * | ||||
|  * Return true if the URLs match, otherwise false. | ||||
|  * @see normalis_link() | ||||
|  * | ||||
|  * @param string $a | ||||
|  * @param string $b | ||||
|  * @return true if the URLs match, otherwise false | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function link_compare($a,$b) { | ||||
| 	if(strcasecmp(normalise_link($a),normalise_link($b)) === 0) | ||||
| function link_compare($a, $b) { | ||||
| 	if (strcasecmp(normalise_link($a), normalise_link($b)) === 0) | ||||
| 		return true; | ||||
|  | ||||
| 	return false; | ||||
| @@ -1167,8 +1189,10 @@ function theme_attachments(&$item) { | ||||
| 			$icon = ''; | ||||
| 			$icontype = substr($r['type'],0,strpos($r['type'],'/')); | ||||
|  | ||||
| 			// FIXME This should probably be a giant "if" statement in the template so that we don't have icon names | ||||
| 			// embedded in php code | ||||
| 			/** | ||||
| 			 * @FIXME This should probably be a giant "if" statement in the | ||||
| 			 * template so that we don't have icon names embedded in php code. | ||||
| 			 */ | ||||
|  | ||||
| 			switch($icontype) { | ||||
| 				case 'video': | ||||
| @@ -1394,11 +1418,14 @@ function prepare_body(&$item,$attach = false) { | ||||
| 	return $prep_arr['html']; | ||||
| } | ||||
|  | ||||
|  | ||||
| // Given a text string, convert from bbcode to html and add smilie icons. | ||||
|  | ||||
|  | ||||
| function prepare_text($text,$content_type = 'text/bbcode') { | ||||
| /** | ||||
|  * @brief Given a text string, convert from bbcode to html and add smilie icons. | ||||
|  * | ||||
|  * @param string $text | ||||
|  * @param sting $content_type | ||||
|  * @return string | ||||
|  */ | ||||
| function prepare_text($text, $content_type = 'text/bbcode') { | ||||
|  | ||||
| 	switch($content_type) { | ||||
| 		case 'text/plain': | ||||
| @@ -1456,14 +1483,16 @@ function prepare_text($text,$content_type = 'text/bbcode') { | ||||
|  * immediate display. | ||||
|  * | ||||
|  * Issues: Currently the order of HTML parameters in the text is somewhat rigid and inflexible. | ||||
|  *    We assume it looks like <a class="zrl" href="xxxxxxxxxx"> and will not work if zrl and href appear in a different order.  | ||||
|  *    We assume it looks like \<a class="zrl" href="xxxxxxxxxx"\> and will not work if zrl and href appear in a different order. | ||||
|  * | ||||
|  * @param array $match | ||||
|  * @return string | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function zidify_callback($match) { | ||||
| 	$is_zid = ((feature_enabled(local_channel(),'sendzid')) || (strpos($match[1],'zrl')) ? true : false); | ||||
| 	$replace = '<a' . $match[1] . ' href="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"';			 | ||||
| 	$x = str_replace($match[0],$replace,$match[0]); | ||||
|  | ||||
| 	return $x; | ||||
| } | ||||
|  | ||||
| @@ -1472,6 +1501,7 @@ function zidify_img_callback($match) { | ||||
| 	$replace = '<img' . $match[1] . ' src="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"'; | ||||
|  | ||||
| 	$x = str_replace($match[0],$replace,$match[0]); | ||||
|  | ||||
| 	return $x; | ||||
| } | ||||
|  | ||||
| @@ -1479,16 +1509,17 @@ function zidify_img_callback($match) { | ||||
| function zidify_links($s) { | ||||
| 	$s = preg_replace_callback('/\<a(.*?)href\=\"(.*?)\"/ism','zidify_callback',$s); | ||||
| 	$s = preg_replace_callback('/\<img(.*?)src\=\"(.*?)\"/ism','zidify_img_callback',$s); | ||||
|  | ||||
| 	return $s; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * return atom link elements for all of our hubs | ||||
|  * @brief Return atom link elements for all of our hubs. | ||||
|  * | ||||
|  * @return string | ||||
|  */ | ||||
|  | ||||
| function feed_hublinks() { | ||||
| 	$hub = get_config('system','huburl'); | ||||
| 	$hub = get_config('system', 'huburl'); | ||||
|  | ||||
| 	$hubxml = ''; | ||||
| 	if(strlen($hub)) { | ||||
| @@ -1498,6 +1529,7 @@ function feed_hublinks() { | ||||
| 				$h = trim($h); | ||||
| 				if(! strlen($h)) | ||||
| 					continue; | ||||
|  | ||||
| 				$hubxml .= '<link rel="hub" href="' . xmlify($h) . '" />' . "\n" ; | ||||
| 			} | ||||
| 		} | ||||
| @@ -2094,15 +2126,16 @@ function extra_query_args() { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * This function removes the tag $tag from the text $body and replaces it with  | ||||
|  * the appropiate link.  | ||||
|  *  | ||||
|  * @param unknown_type $body the text to replace the tag in | ||||
|  * @param unknown_type $access_tag  - used to return tag ACL exclusions e.g. @!foo | ||||
|  * @param unknown_type $str_tags string to add the tag to | ||||
|  * @param unknown_type $profile_uid | ||||
|  * @param unknown_type $tag the tag to replace | ||||
|  * @brief This function removes the tag $tag from the text $body and replaces it | ||||
|  * with the appropiate link. | ||||
|  * | ||||
|  * @param App $a | ||||
|  * @param[in,out] string &$body the text to replace the tag in | ||||
|  * @param[in,out] string &$access_tag used to return tag ACL exclusions e.g. @!foo | ||||
|  * @param[in,out] string &$str_tags string to add the tag to | ||||
|  * @param int $profile_uid | ||||
|  * @param string $tag the tag to replace | ||||
|  * @param boolean $diaspora default false | ||||
|  * @return boolean true if replaced, false if not replaced | ||||
|  */ | ||||
| function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $diaspora = false) { | ||||
|   | ||||
							
								
								
									
										689
									
								
								include/zot.php
									
									
									
									
									
								
							
							
						
						
									
										689
									
								
								include/zot.php
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -73,7 +73,7 @@ function admin_post(&$a){ | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param App $$a | ||||
|  * @param App &$a | ||||
|  * @return string | ||||
|  */ | ||||
| function admin_content(&$a) { | ||||
| @@ -84,7 +84,7 @@ function admin_content(&$a) { | ||||
| 		return login(false); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Side bar links | ||||
| 	 */ | ||||
|  | ||||
| @@ -125,7 +125,7 @@ function admin_content(&$a) { | ||||
| 	)); | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Page content | ||||
| 	 */ | ||||
| 	$o = ''; | ||||
| @@ -183,7 +183,7 @@ function admin_content(&$a) { | ||||
| /** | ||||
|  * @brief Returns content for Admin Summary Page. | ||||
|  * | ||||
|  * @param App $$a | ||||
|  * @param App &$a | ||||
|  * @return string HTML from parsed admin_summary.tpl | ||||
|  */ | ||||
| function admin_page_summary(&$a) { | ||||
| @@ -252,8 +252,9 @@ function admin_page_summary(&$a) { | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Admin Site Page | ||||
|  *  @param App $a | ||||
|  * @brief POST handler for Admin Site Page. | ||||
|  * | ||||
|  * @param App &$a | ||||
|  */ | ||||
| function admin_page_site_post(&$a){ | ||||
| 	if (!x($_POST, 'page_site')){ | ||||
| @@ -277,15 +278,15 @@ function admin_page_site_post(&$a){ | ||||
|  | ||||
| 	$register_text		=	((x($_POST,'register_text'))	? notags(trim($_POST['register_text']))		: ''); | ||||
|  | ||||
| 	$allowed_sites        =	((x($_POST,'allowed_sites'))	? notags(trim($_POST['allowed_sites']))		: ''); | ||||
| 	$allowed_email        =	((x($_POST,'allowed_email'))	? notags(trim($_POST['allowed_email']))		: ''); | ||||
| 	$not_allowed_email    =	((x($_POST,'not_allowed_email'))	? notags(trim($_POST['not_allowed_email']))		: ''); | ||||
| 	$block_public		  =	((x($_POST,'block_public'))		? True	: False); | ||||
| 	$force_publish		  =	((x($_POST,'publish_all'))		? True	: False); | ||||
| 	$disable_discover_tab =	((x($_POST,'disable_discover_tab'))		? True	:	False); | ||||
| 	$no_login_on_homepage =	((x($_POST,'no_login_on_homepage'))		? True	:	False); | ||||
| 	$global_directory	  = ((x($_POST,'directory_submit_url'))	? notags(trim($_POST['directory_submit_url']))	: ''); | ||||
| 	$no_community_page	  = !((x($_POST,'no_community_page'))	? True	:	False); | ||||
| 	$allowed_sites        = ((x($_POST,'allowed_sites'))	? notags(trim($_POST['allowed_sites']))		: ''); | ||||
| 	$allowed_email        = ((x($_POST,'allowed_email'))	? notags(trim($_POST['allowed_email']))		: ''); | ||||
| 	$not_allowed_email    = ((x($_POST,'not_allowed_email'))	? notags(trim($_POST['not_allowed_email']))		: ''); | ||||
| 	$block_public         = ((x($_POST,'block_public'))		? True	: False); | ||||
| 	$force_publish        = ((x($_POST,'publish_all'))		? True	: False); | ||||
| 	$disable_discover_tab = ((x($_POST,'disable_discover_tab'))		? True	:	False); | ||||
| 	$no_login_on_homepage = ((x($_POST,'no_login_on_homepage'))		? True	:	False); | ||||
| 	$global_directory     = ((x($_POST,'directory_submit_url'))	? notags(trim($_POST['directory_submit_url']))	: ''); | ||||
| 	$no_community_page    = !((x($_POST,'no_community_page'))	? True	:	False); | ||||
| 	$default_expire_days  = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0); | ||||
|  | ||||
| 	$verifyssl         = ((x($_POST,'verifyssl'))        ? True : False); | ||||
| @@ -307,7 +308,7 @@ function admin_page_site_post(&$a){ | ||||
| 	set_config('system', 'sitename', $sitename); | ||||
| 	set_config('system', 'no_login_on_homepage', $no_login_on_homepage); | ||||
| 	set_config('system', 'verify_email', $verify_email); | ||||
| 	set_config('system','default_expire_days', $default_expire_days); | ||||
| 	set_config('system', 'default_expire_days', $default_expire_days); | ||||
|  | ||||
| 	if ($banner == '') { | ||||
| 		del_config('system', 'banner'); | ||||
| @@ -360,6 +361,8 @@ function admin_page_site_post(&$a){ | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Admin page site. | ||||
|  * | ||||
|  * @param  App $a | ||||
|  * @return string | ||||
|  */ | ||||
| @@ -480,8 +483,8 @@ function admin_page_site(&$a) { | ||||
| 		'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (matrix/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')), | ||||
| 		'$form_security_token' => get_form_security_token("admin_site"), | ||||
| 	)); | ||||
|  | ||||
| } | ||||
|  | ||||
| function admin_page_hubloc_post(&$a){ | ||||
| 	check_form_security_token_redirectOnErr('/admin/hubloc', 'admin_hubloc'); | ||||
| 	require_once('include/zot.php'); | ||||
| @@ -617,7 +620,6 @@ function admin_page_queue($a) { | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	$r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq  | ||||
| 		where outq_delivered = 0 group by outq_posturl order by total desc"); | ||||
|  | ||||
| @@ -626,7 +628,6 @@ function admin_page_queue($a) { | ||||
| 		$r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d'); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	$o = replace_macros(get_markup_template('admin_queue.tpl'), array( | ||||
| 		'$banner' => t('Queue Statistics'), | ||||
| 		'$numentries' => t('Total Entries'), | ||||
| @@ -763,13 +764,11 @@ function admin_page_users(&$a){ | ||||
| 	} | ||||
|  | ||||
|  | ||||
| //	WEe'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet. | ||||
| //	We'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet. | ||||
| //	That's where we need to be doing last post/channel flags/etc, not here. | ||||
|  | ||||
|  | ||||
| 	$serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : ''); | ||||
|  | ||||
|  | ||||
| 	$order = " order by account_email asc "; | ||||
| 	if($_REQUEST['order'] === 'expires') | ||||
| 		$order = " order by account_expires desc "; | ||||
| @@ -803,7 +802,6 @@ function admin_page_users(&$a){ | ||||
| //	} | ||||
| //	$users = array_map("_setup_users", $users); | ||||
|  | ||||
|  | ||||
| 	$t = get_markup_template('admin_users.tpl'); | ||||
| 	$o = replace_macros($t, array( | ||||
| 		// strings // | ||||
| @@ -841,9 +839,9 @@ function admin_page_users(&$a){ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Channels admin page | ||||
|  * @brief Channels admin page. | ||||
|  * | ||||
|  * @param App $a | ||||
|  * @param App &$a | ||||
|  */ | ||||
| function admin_page_channels_post(&$a) { | ||||
| 	$channels = ( x($_POST, 'channel') ? $_POST['channel'] : Array() ); | ||||
| @@ -872,7 +870,9 @@ function admin_page_channels_post(&$a) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param App $a | ||||
|  * @brief | ||||
|  * | ||||
|  * @param App &$a | ||||
|  * @return string | ||||
|  */ | ||||
| function admin_page_channels(&$a){ | ||||
| @@ -975,7 +975,7 @@ function admin_page_channels(&$a){ | ||||
|  */ | ||||
| function admin_page_plugins(&$a){ | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Single plugin | ||||
| 	 */ | ||||
| 	if ($a->argc == 3){ | ||||
| @@ -1055,7 +1055,7 @@ function admin_page_plugins(&$a){ | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * List plugins | ||||
| 	 */ | ||||
| 	$plugins = array(); | ||||
| @@ -1087,7 +1087,7 @@ function admin_page_plugins(&$a){ | ||||
|  * @param string $th | ||||
|  * @param int $result | ||||
|  */ | ||||
| function toggle_theme(&$themes,$th,&$result) { | ||||
| function toggle_theme(&$themes, $th, &$result) { | ||||
| 	for($x = 0; $x < count($themes); $x ++) { | ||||
| 		if($themes[$x]['name'] === $th) { | ||||
| 			if($themes[$x]['allowed']) { | ||||
| @@ -1142,9 +1142,9 @@ function rebuild_theme_table($themes) { | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Themes admin page | ||||
|  * @brief Themes admin page. | ||||
|  * | ||||
|  * @param App $a | ||||
|  * @param App &$a | ||||
|  * @return string | ||||
|  */ | ||||
| function admin_page_themes(&$a){ | ||||
| @@ -1174,7 +1174,7 @@ function admin_page_themes(&$a){ | ||||
| 		return ''; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Single theme | ||||
| 	 */ | ||||
|  | ||||
| @@ -1253,8 +1253,7 @@ function admin_page_themes(&$a){ | ||||
| 		)); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * List themes | ||||
| 	 */ | ||||
|  | ||||
| @@ -1281,9 +1280,9 @@ function admin_page_themes(&$a){ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Logs admin page | ||||
|  * @brief POST handler for logs admin page. | ||||
|  * | ||||
|  * @param App $a | ||||
|  * @param App &$a | ||||
|  */ | ||||
| function admin_page_logs_post(&$a) { | ||||
| 	if (x($_POST, 'page_logs')) { | ||||
| @@ -1303,6 +1302,8 @@ function admin_page_logs_post(&$a) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief Logs admin page. | ||||
|  * | ||||
|  * @param App $a | ||||
|  * @return string | ||||
|  */ | ||||
| @@ -1435,5 +1436,4 @@ function admin_page_profs(&$a) { | ||||
| 			'$submit' => t('Save') | ||||
| 		)); | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										201
									
								
								mod/id.php
									
									
									
									
									
								
							
							
						
						
									
										201
									
								
								mod/id.php
									
									
									
									
									
								
							| @@ -1,45 +1,51 @@ | ||||
| <?php | ||||
| /** | ||||
|  * @file mod/id.php | ||||
|  * @brief OpenID implementation | ||||
|  */ | ||||
|  | ||||
| 	require 'library/openid/provider/provider.php'; | ||||
| require 'library/openid/provider/provider.php'; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	$attrMap = array( | ||||
|         'namePerson/first'       => t('First Name'), | ||||
|         'namePerson/last'        => t('Last Name'), | ||||
|         'namePerson/friendly'    => t('Nickname'), | ||||
| 		'namePerson'             => t('Full Name'), | ||||
| 		'contact/internet/email' => t('Email'), | ||||
| 		'contact/email'          => t('Email'), | ||||
| 		'media/image/aspect11'   => t('Profile Photo'), | ||||
| 		'media/image'            => t('Profile Photo'), | ||||
| 		'media/image/default'    => t('Profile Photo'), | ||||
| 		'media/image/16x16'      => t('Profile Photo 16px'), | ||||
| 		'media/image/32x32'      => t('Profile Photo 32px'), | ||||
| 		'media/image/48x48'      => t('Profile Photo 48px'), | ||||
| 		'media/image/64x64'      => t('Profile Photo 64px'), | ||||
| 		'media/image/80x80'      => t('Profile Photo 80px'), | ||||
| 		'media/image/128x128'    => t('Profile Photo 128px'), | ||||
| 		'timezone'               => t('Timezone'), | ||||
| 		'contact/web/default'    => t('Homepage URL'), | ||||
| 		'language/pref'          => t('Language'), | ||||
| 		'birthDate/birthYear'    => t('Birth Year'), | ||||
| 		'birthDate/birthMonth'   => t('Birth Month'), | ||||
| 		'birthDate/birthday'     => t('Birth Day'), | ||||
| 		'birthDate'              => t('Birthdate'), | ||||
| 		'gender'                 => t('Gender'), | ||||
| 	); | ||||
|  | ||||
| $attrMap = array( | ||||
| 	'namePerson/first'       => t('First Name'), | ||||
| 	'namePerson/last'        => t('Last Name'), | ||||
| 	'namePerson/friendly'    => t('Nickname'), | ||||
| 	'namePerson'             => t('Full Name'), | ||||
| 	'contact/internet/email' => t('Email'), | ||||
| 	'contact/email'          => t('Email'), | ||||
| 	'media/image/aspect11'   => t('Profile Photo'), | ||||
| 	'media/image'            => t('Profile Photo'), | ||||
| 	'media/image/default'    => t('Profile Photo'), | ||||
| 	'media/image/16x16'      => t('Profile Photo 16px'), | ||||
| 	'media/image/32x32'      => t('Profile Photo 32px'), | ||||
| 	'media/image/48x48'      => t('Profile Photo 48px'), | ||||
| 	'media/image/64x64'      => t('Profile Photo 64px'), | ||||
| 	'media/image/80x80'      => t('Profile Photo 80px'), | ||||
| 	'media/image/128x128'    => t('Profile Photo 128px'), | ||||
| 	'timezone'               => t('Timezone'), | ||||
| 	'contact/web/default'    => t('Homepage URL'), | ||||
| 	'language/pref'          => t('Language'), | ||||
| 	'birthDate/birthYear'    => t('Birth Year'), | ||||
| 	'birthDate/birthMonth'   => t('Birth Month'), | ||||
| 	'birthDate/birthday'     => t('Birth Day'), | ||||
| 	'birthDate'              => t('Birthdate'), | ||||
| 	'gender'                 => t('Gender'), | ||||
| ); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Entrypoint for the OpenID implementation. | ||||
|  * | ||||
|  * @param App &$a | ||||
|  */ | ||||
| function id_init(&$a) { | ||||
|  | ||||
| 	logger('id: ' . print_r($_REQUEST,true)); | ||||
| 	logger('id: ' . print_r($_REQUEST, true)); | ||||
|  | ||||
|  | ||||
| 	if(argc() > 1) | ||||
| 	if(argc() > 1) { | ||||
| 		$which = argv(1); | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$a->error = 404; | ||||
| 		return; | ||||
| 	} | ||||
| @@ -48,41 +54,45 @@ function id_init(&$a) { | ||||
| 	$channel = $a->get_channel(); | ||||
| 	profile_load($a,$which,$profile); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	$op = new MysqlProvider; | ||||
| 	$op->server(); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| function getUserData($handle=null) { | ||||
| 	if(! local_channel()) { | ||||
| /** | ||||
|  * @brief Returns user data needed for OpenID. | ||||
|  * | ||||
|  * If no $handle is provided we will use local_channel() by default. | ||||
|  * | ||||
|  * @param string $handle (default null) | ||||
|  * @return boolean|array | ||||
|  */ | ||||
| function getUserData($handle = null) { | ||||
| 	if (! local_channel()) { | ||||
| 		notice( t('Permission denied.') . EOL); | ||||
| 		get_app()->page['content'] =  login(); | ||||
|  | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| //	logger('handle: ' . $handle); | ||||
|  | ||||
| 	if($handle) { | ||||
| 	if ($handle) { | ||||
| 		$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1", | ||||
| 			dbesc($handle) | ||||
| 		); | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d", | ||||
| 			intval(local_channel()) | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| 	if(! r) | ||||
| 	if (! r) | ||||
| 		return false; | ||||
|  | ||||
| 	$x = q("select * from account where account_id = %d limit 1",  | ||||
| 		intval($r[0]['channel_account_id']) | ||||
| 	); | ||||
| 	if($x) | ||||
| 	if ($x) | ||||
| 		$r[0]['email'] = $x[0]['account_email']; | ||||
|  | ||||
| 	$p = q("select * from profile where is_default = 1 and uid = %d limit 1", | ||||
| @@ -90,9 +100,9 @@ function getUserData($handle=null) { | ||||
| 	); | ||||
|  | ||||
| 	$gender = ''; | ||||
| 	if($p[0]['gender'] == t('Male')) | ||||
| 	if ($p[0]['gender'] == t('Male')) | ||||
| 		$gender = 'M'; | ||||
| 	if($p[0]['gender'] == t('Female')) | ||||
| 	if ($p[0]['gender'] == t('Female')) | ||||
| 		$gender = 'F'; | ||||
|  | ||||
| 	$r[0]['firstName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],0,strpos($r[0]['channel_name'],' ')) : $r[0]['channel_name']); | ||||
| @@ -144,20 +154,20 @@ function getUserData($handle=null) { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class MysqlProvider extends LightOpenIDProvider | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief MySQL provider for OpenID implementation. | ||||
|  * | ||||
|  */ | ||||
| class MysqlProvider extends LightOpenIDProvider { | ||||
|  | ||||
| 	// See http://openid.net/specs/openid-attribute-properties-list-1_0-01.html | ||||
| 	// This list contains a few variations of these attributes to maintain  | ||||
| 	// compatibility with legacy clients | ||||
|  | ||||
|     private $attrFieldMap = array( | ||||
|         'namePerson/first'       => 'firstName', | ||||
|         'namePerson/last'        => 'lastName', | ||||
|         'namePerson/friendly'    => 'channel_address', | ||||
| 	private $attrFieldMap = array( | ||||
| 		'namePerson/first'       => 'firstName', | ||||
| 		'namePerson/last'        => 'lastName', | ||||
| 		'namePerson/friendly'    => 'channel_address', | ||||
| 		'namePerson'             => 'namePerson', | ||||
| 		'contact/internet/email' => 'email', | ||||
| 		'contact/email'          => 'email', | ||||
| @@ -178,11 +188,9 @@ class MysqlProvider extends LightOpenIDProvider | ||||
| 		'birthDate/birthday'     => 'birthday', | ||||
| 		'birthDate'              => 'birthdate', | ||||
| 		'gender'                 => 'gender', | ||||
|         ); | ||||
| 	); | ||||
|  | ||||
|    | ||||
|     function setup($identity, $realm, $assoc_handle, $attributes) | ||||
|     { | ||||
| 	function setup($identity, $realm, $assoc_handle, $attributes) { | ||||
| 		global $attrMap; | ||||
|  | ||||
| //		logger('identity: ' . $identity); | ||||
| @@ -190,10 +198,10 @@ class MysqlProvider extends LightOpenIDProvider | ||||
| //		logger('assoc_handle: ' . $assoc_handle); | ||||
| //		logger('attributes: ' . print_r($attributes,true)); | ||||
|  | ||||
|         $data = getUserData($assoc_handle); | ||||
| 		$data = getUserData($assoc_handle); | ||||
|  | ||||
|  | ||||
| // FIXME this needs to be a template with localised strings | ||||
| /** @FIXME this needs to be a template with localised strings */ | ||||
|  | ||||
|         $o .= '<form action="" method="post">' | ||||
|            . '<input type="hidden" name="openid.assoc_handle" value="' . $assoc_handle . '">' | ||||
| @@ -228,27 +236,23 @@ class MysqlProvider extends LightOpenIDProvider | ||||
|            . '</form>'; | ||||
|  | ||||
| 		get_app()->page['content'] .= $o; | ||||
| 	} | ||||
|  | ||||
|     } | ||||
|      | ||||
|     function checkid($realm, &$attributes) | ||||
|     { | ||||
| 	function checkid($realm, &$attributes) { | ||||
|  | ||||
| 		logger('checkid: ' . $realm); | ||||
|  | ||||
| 		logger('checkid attrs: ' . print_r($attributes,true)); | ||||
|  | ||||
| 		if(isset($_POST['cancel'])) { | ||||
| 			$this->cancel(); | ||||
| 		} | ||||
|  | ||||
|         if(isset($_POST['cancel'])) { | ||||
|             $this->cancel(); | ||||
|         } | ||||
| 		$data = getUserData(); | ||||
| 		if(! $data) { | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
|         $data = getUserData(); | ||||
|         if(! $data) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
| 		$q = get_pconfig(local_channel(),'openid',$realm); | ||||
| 		$q = get_pconfig(local_channel(), 'openid', $realm); | ||||
|  | ||||
| 		$attrs = array(); | ||||
| 		if($q) { | ||||
| @@ -266,56 +270,41 @@ class MysqlProvider extends LightOpenIDProvider | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if(isset($_POST['always'])) { | ||||
| 		if(isset($_POST['always'])) { | ||||
| 			set_pconfig(local_channel(),'openid',$realm,array_keys($attributes)); | ||||
|         } | ||||
| 		} | ||||
|  | ||||
| 		return z_root() . '/id/' . $data['channel_address']; | ||||
|     } | ||||
| 	} | ||||
|  | ||||
|     function assoc_handle() | ||||
|     { | ||||
| 	logger('assoc_handle'); | ||||
| 	function assoc_handle() { | ||||
| 		logger('assoc_handle'); | ||||
| 		$channel = get_app()->get_channel(); | ||||
|  | ||||
| 		return z_root() . '/channel/' . $channel['channel_address'];  | ||||
| 	} | ||||
|  | ||||
|     } | ||||
|      | ||||
|     function setAssoc($handle, $data) | ||||
|     { | ||||
| 	function setAssoc($handle, $data) { | ||||
| 		logger('setAssoc'); | ||||
| 		$channel = channelx_by_nick(basename($handle)); | ||||
| 		if($channel) | ||||
| 			set_pconfig($channel['channel_id'],'openid','associate',$data); | ||||
|     } | ||||
| 	} | ||||
|  | ||||
|     function getAssoc($handle) | ||||
|     { | ||||
| 	function getAssoc($handle) { | ||||
| 		logger('getAssoc: ' . $handle); | ||||
|  | ||||
| 		$channel = channelx_by_nick(basename($handle)); | ||||
| 		if($channel) | ||||
| 			return get_pconfig($channel['channel_id'],'openid','associate'); | ||||
| 		return false; | ||||
|     } | ||||
| 			return get_pconfig($channel['channel_id'], 'openid', 'associate'); | ||||
|  | ||||
|     function delAssoc($handle) | ||||
|     { | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	function delAssoc($handle) { | ||||
| 		logger('delAssoc'); | ||||
| 		$channel = channelx_by_nick(basename($handle)); | ||||
| 		if($channel) | ||||
| 			return del_pconfig($channel['channel_id'],'openid','associate'); | ||||
|     } | ||||
|      | ||||
| 			return del_pconfig($channel['channel_id'], 'openid', 'associate'); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,14 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| // FIXME - this has never been properly ported from Friendica | ||||
| // It takes keywords from your profile and queries the directory server for  | ||||
| // matching keywords from other profiles. | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Controller for /match. | ||||
|  * | ||||
|  * It takes keywords from your profile and queries the directory server for | ||||
|  * matching keywords from other profiles. | ||||
|  * | ||||
|  * @FIXME this has never been properly ported from Friendica. | ||||
|  * | ||||
|  * @param App &$a | ||||
|  * @return void|string | ||||
|  */ | ||||
| function match_content(&$a) { | ||||
|  | ||||
| 	$o = ''; | ||||
| 	if(! local_channel()) | ||||
| 	if (! local_channel()) | ||||
| 		return; | ||||
|  | ||||
| 	$_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd; | ||||
| @@ -18,20 +24,20 @@ function match_content(&$a) { | ||||
| 	$r = q("SELECT `keywords` FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1", | ||||
| 		intval(local_channel()) | ||||
| 	); | ||||
| 	if(! count($r)) | ||||
| 		return;  | ||||
| 	if(! $r[0]['keywords']) { | ||||
| 		notice( t('No keywords to match. Please add keywords to your default profile.') . EOL); | ||||
| 	if (! count($r)) | ||||
| 		return; | ||||
|  | ||||
| 	if (! $r[0]['keywords']) { | ||||
| 		notice( t('No keywords to match. Please add keywords to your default profile.') . EOL); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	$params = array(); | ||||
| 	$tags = trim($r[0]['keywords']); | ||||
|  | ||||
| 	if($tags) { | ||||
| 	if ($tags) { | ||||
| 		$params['s'] = $tags; | ||||
| 		if($a->pager['page'] != 1) | ||||
| 		if ($a->pager['page'] != 1) | ||||
| 			$params['p'] = $a->pager['page']; | ||||
|  | ||||
| //		if(strlen(get_config('system','directory_submit_url'))) | ||||
| @@ -41,18 +47,14 @@ function match_content(&$a) { | ||||
|  | ||||
| 		$j = json_decode($x); | ||||
|  | ||||
| 		if($j->total) { | ||||
| 		if ($j->total) { | ||||
| 			$a->set_pager_total($j->total); | ||||
| 			$a->set_pager_itemspage($j->items_page); | ||||
| 		} | ||||
|  | ||||
| 		if(count($j->results)) { | ||||
|  | ||||
|  | ||||
| 			 | ||||
| 		if (count($j->results)) { | ||||
| 			$tpl = get_markup_template('match.tpl'); | ||||
| 			foreach($j->results as $jj) { | ||||
| 				 | ||||
| 			foreach ($j->results as $jj) { | ||||
| 				$connlnk = $a->get_baseurl() . '/follow/?url=' . $jj->url; | ||||
| 				$o .= replace_macros($tpl,array( | ||||
| 					'$url' => zid($jj->url), | ||||
| @@ -64,14 +66,13 @@ function match_content(&$a) { | ||||
| 					'$tags' => $jj->tags | ||||
| 				)); | ||||
| 			} | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			info( t('No matches') . EOL); | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	$o .= cleardiv(); | ||||
| 	$o .= paginate($a); | ||||
|  | ||||
| 	return $o; | ||||
| } | ||||
|   | ||||
							
								
								
									
										497
									
								
								mod/post.php
									
									
									
									
									
								
							
							
						
						
									
										497
									
								
								mod/post.php
									
									
									
									
									
								
							| @@ -1,20 +1,21 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Zot endpoint | ||||
|  * @file mod/post.php | ||||
|  * | ||||
|  * @brief Zot endpoint. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| require_once('include/zot.php'); | ||||
|  | ||||
|  | ||||
| function post_init(&$a) { | ||||
|  | ||||
| 	// Most access to this endpoint is via the post method. | ||||
| 	// Here we will pick out the magic auth params which arrive | ||||
| 	// as a get request, and the only communications to arrive this way. | ||||
|  | ||||
| /** | ||||
|  * @brief HTTP POST entry point for Zot. | ||||
|  * | ||||
|  * Most access to this endpoint is via the post method. | ||||
|  * Here we will pick out the magic auth params which arrive as a get request, | ||||
|  * and the only communications to arrive this way. | ||||
|  * | ||||
|  * Magic Auth | ||||
|  * ========== | ||||
|  * | ||||
| @@ -24,13 +25,12 @@ function post_init(&$a) { | ||||
|  * The endpoint is typically  https://$remotesite/post - or whatever was specified as the callback url in prior communications | ||||
|  * (we will bootstrap an address and fetch a zot info packet if possible where no prior communications exist) | ||||
|  * | ||||
|  * Four GET parameters are supplied: | ||||
|  * | ||||
|  ** auth => the urlencoded webbie (channel@host.domain) of the channel requesting access | ||||
|  ** dest => the desired destination URL (urlencoded) | ||||
|  ** sec  => a random string which is also stored on $mysite for use during the verification phase.  | ||||
|  ** version => the zot revision | ||||
|  ** delegate => optional urlencoded webbie of a local channel to invoke delegation rights for | ||||
|  * Five GET parameters are supplied: | ||||
|  * * auth => the urlencoded webbie (channel@host.domain) of the channel requesting access | ||||
|  * * dest => the desired destination URL (urlencoded) | ||||
|  * * sec  => a random string which is also stored on $mysite for use during the verification phase.  | ||||
|  * * version => the zot revision | ||||
|  * * delegate => optional urlencoded webbie of a local channel to invoke delegation rights for | ||||
|  * | ||||
|  * When this packet is received, an "auth-check" zot message is sent to $mysite. | ||||
|  * (e.g. if $_GET['auth'] is foobar@podunk.edu, a zot packet is sent to the podunk.edu zot endpoint, which is typically /post) | ||||
| @@ -40,38 +40,40 @@ function post_init(&$a) { | ||||
|  * The sender of this packet is an arbitrary/random site channel. The recipients will be a single recipient corresponding | ||||
|  * to the guid and guid_sig we have associated with the requesting auth identity | ||||
|  * | ||||
|  * | ||||
|  *    { | ||||
|  *      "type":"auth_check", | ||||
|  *      "sender":{ | ||||
|  *        "guid":"kgVFf_...", | ||||
|  *        "guid_sig":"PT9-TApz...", | ||||
|  *        "url":"http:\/\/podunk.edu", | ||||
|  *        "url_sig":"T8Bp7j..." | ||||
|  *      }, | ||||
|  *      "recipients":{ | ||||
|  *        { | ||||
|  *        "guid":"ZHSqb...", | ||||
|  *        "guid_sig":"JsAAXi..." | ||||
|  *        } | ||||
|  *      } | ||||
|  *      "callback":"\/post", | ||||
|  *      "version":1, | ||||
|  *      "secret":"1eaa661", | ||||
|  *      "secret_sig":"eKV968b1..." | ||||
|  *    } | ||||
|  * | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  *   "type":"auth_check", | ||||
|  *   "sender":{ | ||||
|  *     "guid":"kgVFf_...", | ||||
|  *     "guid_sig":"PT9-TApz...", | ||||
|  *     "url":"http:\/\/podunk.edu", | ||||
|  *     "url_sig":"T8Bp7j..." | ||||
|  *   }, | ||||
|  *   "recipients":{ | ||||
|  *     { | ||||
|  *       "guid":"ZHSqb...", | ||||
|  *       "guid_sig":"JsAAXi..." | ||||
|  *     } | ||||
|  *   } | ||||
|  *   "callback":"\/post", | ||||
|  *   "version":1, | ||||
|  *   "secret":"1eaa661", | ||||
|  *   "secret_sig":"eKV968b1..." | ||||
|  * } | ||||
|  * \endcode | ||||
|  * | ||||
|  * auth_check messages MUST use encapsulated encryption. This message is sent to the origination site, which checks the 'secret' to see  | ||||
|  * if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the  | ||||
|  * destination channel's private key and base64url encoded. If everything checks out, a json packet is returned: | ||||
|  * | ||||
|  *    {  | ||||
|  *      "success":1,  | ||||
|  *      "confirm":"q0Ysovd1u..." | ||||
|  *      "service_class":(optional) | ||||
|  *      "level":(optional) | ||||
|  *    } | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  *   "success":1, | ||||
|  *   "confirm":"q0Ysovd1u...", | ||||
|  *   "service_class":(optional) | ||||
|  *   "level":(optional) | ||||
|  * } | ||||
|  * \endcode | ||||
|  * | ||||
|  * 'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the | ||||
|  * base64url encoded whirlpool hash of the requestor's guid and guid_sig; signed with the source channel private key.  | ||||
| @@ -80,11 +82,11 @@ function post_init(&$a) { | ||||
|  * Service_class can be used by cooperating sites to provide different access rights based on account rights and subscription plans. It is  | ||||
|  * a string whose contents are not defined by protocol. Example: "basic" or "gold". | ||||
|  * | ||||
|  * | ||||
|  * | ||||
|  * @param[in,out] App &$a | ||||
|  */ | ||||
| function post_init(&$a) { | ||||
|  | ||||
| 	if(array_key_exists('auth',$_REQUEST)) { | ||||
| 	if (array_key_exists('auth', $_REQUEST)) { | ||||
|  | ||||
| 		$ret = array('success' => false, 'message' => ''); | ||||
|  | ||||
| @@ -95,7 +97,7 @@ function post_init(&$a) { | ||||
| 		$version  = $_REQUEST['version']; | ||||
| 		$delegate = $_REQUEST['delegate']; | ||||
|  | ||||
| 		$test    = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0); | ||||
| 		$test     = ((x($_REQUEST, 'test')) ? intval($_REQUEST['test']) : 0); | ||||
|  | ||||
| 		// They are authenticating ultimately to the site and not to a particular channel. | ||||
| 		// Any channel will do, providing it's currently active. We just need to have an  | ||||
| @@ -105,10 +107,10 @@ function post_init(&$a) { | ||||
| 			intval(PAGE_REMOVED) | ||||
| 		); | ||||
|  | ||||
| 		if(! $c) { | ||||
| 		if (! $c) { | ||||
| 			// nobody here | ||||
| 			logger('mod_zot: auth: unable to find a response channel'); | ||||
| 			if($test) { | ||||
| 			if ($test) { | ||||
| 				$ret['message'] .= 'no local channels found.' . EOL; | ||||
| 				json_return_and_die($ret); | ||||
| 			} | ||||
| @@ -121,12 +123,12 @@ function post_init(&$a) { | ||||
| 			dbesc($address) | ||||
| 		); | ||||
|  | ||||
| 		if(! $x) { | ||||
| 		if (! $x) { | ||||
| 			// finger them if they can't be found.  | ||||
| 			$ret = zot_finger($address,null); | ||||
| 			if($ret['success']) { | ||||
| 				$j = json_decode($ret['body'],true); | ||||
| 				if($j) | ||||
| 			$ret = zot_finger($address, null); | ||||
| 			if ($ret['success']) { | ||||
| 				$j = json_decode($ret['body'], true); | ||||
| 				if ($j) | ||||
| 					import_xchan($j); | ||||
| 				$x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' order by hubloc_id desc limit 1", | ||||
| 					dbesc($address) | ||||
| @@ -166,32 +168,31 @@ function post_init(&$a) { | ||||
|  | ||||
| 		$j = array(); | ||||
|  | ||||
| 		if(! $already_authed) { | ||||
| 		if (! $already_authed) { | ||||
|  | ||||
| 			// Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the site private key | ||||
| 			// The actual channel sending the packet ($c[0]) is not important, but this provides a generic zot packet with a sender | ||||
| 			// which can be verified | ||||
|   | ||||
| 			$p = zot_build_packet($c[0],$type = 'auth_check', array(array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig'])), $x[0]['hubloc_sitekey'], $sec); | ||||
| 			if($test) { | ||||
| 			if ($test) { | ||||
| 				$ret['message'] .= 'auth check packet created using sitekey ' . $x[0]['hubloc_sitekey'] . EOL; | ||||
| 				$ret['message'] .= 'packet contents: ' . $p . EOL; | ||||
| 			} | ||||
|  | ||||
| 			$result = zot_zot($x[0]['hubloc_callback'],$p); | ||||
|  | ||||
|  | ||||
| 			if(! $result['success']) { | ||||
| 			if (! $result['success']) { | ||||
| 				logger('mod_zot: auth_check callback failed.'); | ||||
| 				if($test) { | ||||
| 				if ($test) { | ||||
| 					$ret['message'] .= 'auth check request to your site returned .' . print_r($result, true) . EOL; | ||||
| 					json_return_and_die($ret); | ||||
| 				} | ||||
|  | ||||
| 				goaway($desturl); | ||||
| 			} | ||||
| 			$j = json_decode($result['body'],true); | ||||
| 			if(! $j) { | ||||
| 			$j = json_decode($result['body'], true); | ||||
| 			if (! $j) { | ||||
| 				logger('mod_zot: auth_check json data malformed.'); | ||||
| 				if($test) { | ||||
| 					$ret['message'] .= 'json malformed: ' . $result['body'] . EOL; | ||||
| @@ -200,27 +201,27 @@ function post_init(&$a) { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if($test) { | ||||
| 		if ($test) { | ||||
| 			$ret['message'] .= 'auth check request returned .' . print_r($j, true) . EOL; | ||||
| 		} | ||||
|  | ||||
| 		if($already_authed || $j['success']) { | ||||
| 			if($j['success']) { | ||||
| 		if ($already_authed || $j['success']) { | ||||
| 			if ($j['success']) { | ||||
| 				// legit response, but we do need to check that this wasn't answered by a man-in-middle | ||||
| 				if(! rsa_verify($sec . $x[0]['xchan_hash'],base64url_decode($j['confirm']),$x[0]['xchan_pubkey'])) { | ||||
| 				if (! rsa_verify($sec . $x[0]['xchan_hash'],base64url_decode($j['confirm']),$x[0]['xchan_pubkey'])) { | ||||
| 					logger('mod_zot: auth: final confirmation failed.'); | ||||
| 					if($test) { | ||||
| 					if ($test) { | ||||
| 						$ret['message'] .= 'final confirmation failed. ' . $sec . print_r($j,true) . print_r($x[0],true); | ||||
| 						json_return_and_die($ret); | ||||
| 					} | ||||
|  | ||||
| 					goaway($desturl); | ||||
| 				} | ||||
| 				if(array_key_exists('service_class',$j)) | ||||
| 				if (array_key_exists('service_class',$j)) | ||||
| 					$remote_service_class = $j['service_class']; | ||||
| 				if(array_key_exists('level',$j)) | ||||
| 				if (array_key_exists('level',$j)) | ||||
| 					$remote_level = $j['level']; | ||||
| 				if(array_key_exists('DNT',$j)) | ||||
| 				if (array_key_exists('DNT',$j)) | ||||
| 					$DNT = $j['DNT']; | ||||
| 			} | ||||
| 			// everything is good... maybe | ||||
| @@ -229,35 +230,33 @@ function post_init(&$a) { | ||||
| 				// tell them to logout if they're logged in locally as anything but the target remote account | ||||
| 				// in which case just shut up because they don't need to be doing this at all. | ||||
|  | ||||
| 				if($a->channel['channel_hash'] != $x[0]['xchan_hash']) { | ||||
| 				if ($a->channel['channel_hash'] != $x[0]['xchan_hash']) { | ||||
| 					logger('mod_zot: auth: already authenticated locally as somebody else.'); | ||||
| 					notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry.') . EOL); | ||||
| 					if($test) { | ||||
| 					if ($test) { | ||||
| 						$ret['message'] .= 'already logged in locally with a conflicting identity.' . EOL; | ||||
| 						json_return_and_die($ret); | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
| 				goaway($desturl); | ||||
| 			} | ||||
|  | ||||
|  | ||||
| 			// log them in | ||||
|  | ||||
| 			if($test) { | ||||
| 			if ($test) { | ||||
| 				$ret['success'] = true; | ||||
| 				$ret['message'] .= 'Authentication Success!' . EOL; | ||||
| 				json_return_and_die($ret); | ||||
| 			} | ||||
|  | ||||
| 			$delegation_success = false; | ||||
| 			if($delegate) { | ||||
| 			if ($delegate) { | ||||
| 				$r = q("select * from channel left join xchan on channel_hash = xchan_hash where xchan_addr = '%s' limit 1", | ||||
| 					dbesc($delegate) | ||||
| 				); | ||||
| 				if($r && intval($r[0]['channel_id'])) { | ||||
| 				if ($r && intval($r[0]['channel_id'])) { | ||||
| 					$allowed = perm_is_allowed($r[0]['channel_id'],$x[0]['xchan_hash'],'delegate'); | ||||
| 					if($allowed) { | ||||
| 					if ($allowed) { | ||||
| 						$_SESSION['delegate_channel'] = $r[0]['channel_id']; | ||||
| 						$_SESSION['delegate'] = $x[0]['xchan_hash']; | ||||
| 						$_SESSION['account_id'] = intval($r[0]['channel_account_id']); | ||||
| @@ -268,11 +267,8 @@ function post_init(&$a) { | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 			$_SESSION['authenticated'] = 1; | ||||
| 			if(! $delegation_success) { | ||||
| 			if (! $delegation_success) { | ||||
| 				$_SESSION['visitor_id'] = $x[0]['xchan_hash']; | ||||
| 				$_SESSION['my_url'] = $x[0]['xchan_url']; | ||||
| 				$_SESSION['my_address'] = $address; | ||||
| @@ -289,18 +285,15 @@ function post_init(&$a) { | ||||
| 			$a->set_groups(init_groups_visitor($_SESSION['visitor_id'])); | ||||
| 			info(sprintf( t('Welcome %s. Remote authentication successful.'),$x[0]['xchan_name'])); | ||||
| 			logger('mod_zot: auth success from ' . $x[0]['xchan_addr']);  | ||||
| 			 q("update hubloc set hubloc_status =  (hubloc_status | %d ) where hubloc_id = %d ", | ||||
|                                 intval(HUBLOC_WORKS), | ||||
|                                 intval($x[0]['hubloc_id']) | ||||
|                         ); | ||||
|  | ||||
|  | ||||
| 			q("update hubloc set hubloc_status =  (hubloc_status | %d ) where hubloc_id = %d ", | ||||
| 					intval(HUBLOC_WORKS), | ||||
| 					intval($x[0]['hubloc_id']) | ||||
| 			); | ||||
| 		} else { | ||||
| 			if($test) { | ||||
| 			if ($test) { | ||||
| 				$ret['message'] .= 'auth failure. ' . print_r($_REQUEST,true) . print_r($j,true) . EOL; | ||||
| 				json_return_and_die($ret); | ||||
| 			} | ||||
|  | ||||
| 			logger('mod_zot: magic-auth failure - not authenticated: ' . $x[0]['xchan_addr']); | ||||
| 			q("update hubloc set hubloc_status =  (hubloc_status | %d ) where hubloc_id = %d ", | ||||
| 				intval(HUBLOC_RECEIVE_ERROR), | ||||
| @@ -308,11 +301,14 @@ function post_init(&$a) { | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		// FIXME - we really want to save the return_url in the session before we visit rmagic. | ||||
| 		// This does however prevent a recursion if you visit rmagic directly, as it would otherwise send you back here again.  | ||||
| 		// But z_root() probably isn't where you really want to go.  | ||||
| 		/** | ||||
| 		 * @FIXME we really want to save the return_url in the session before we | ||||
| 		 * visit rmagic. This does however prevent a recursion if you visit | ||||
| 		 * rmagic directly, as it would otherwise send you back here again. | ||||
| 		 * But z_root() probably isn't where you really want to go. | ||||
| 		 */ | ||||
|  | ||||
| 		if($test) { | ||||
| 		if ($test) { | ||||
| 			$ret['message'] .= 'auth failure fallthrough ' . print_r($_REQUEST,true) . print_r($j,true) . EOL; | ||||
| 			json_return_and_die($ret); | ||||
| 		} | ||||
| @@ -322,40 +318,39 @@ function post_init(&$a) { | ||||
|  | ||||
| 		goaway($desturl); | ||||
| 	} | ||||
| 	return; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @function post_post(&$a) | ||||
|  *     zot communications and messaging | ||||
|  * @brief zot communications and messaging. | ||||
|  * | ||||
|  *     Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet. | ||||
|  *     This packet is optionally encrypted, which we will discover if the json has an 'iv' element. | ||||
|  *     $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data); | ||||
|  *     $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded. | ||||
|  *     Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate. | ||||
|  * Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet. | ||||
|  * This packet is optionally encrypted, which we will discover if the json has an 'iv' element. | ||||
|  * $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data); | ||||
|  * $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded. | ||||
|  * Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate. | ||||
|  * | ||||
|  *     Once decrypted, one will find the normal json_encoded zot message packet.  | ||||
|  * Once decrypted, one will find the normal json_encoded zot message packet. | ||||
|  *  | ||||
|  * Defined packet types are: notify, purge, refresh, force_refresh, auth_check, ping, and pickup  | ||||
|  * | ||||
|  * Standard packet: (used by notify, purge, refresh, force_refresh, and auth_check) | ||||
|  * | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  *  "type": "notify", | ||||
|  *  "sender":{ | ||||
|  *       "guid":"kgVFf_1...", | ||||
|  *       "guid_sig":"PT9-TApzp...", | ||||
|  *       "url":"http:\/\/podunk.edu", | ||||
|  *       "url_sig":"T8Bp7j5...", | ||||
|  *    }, | ||||
|  *  "recipients": { optional recipient array }, | ||||
|  *  "callback":"\/post", | ||||
|  *  "version":1, | ||||
|  *  "secret":"1eaa...", | ||||
|  *  "secret_sig": "df89025470fac8..." | ||||
|  *   "type": "notify", | ||||
|  *   "sender":{ | ||||
|  *     "guid":"kgVFf_1...", | ||||
|  *     "guid_sig":"PT9-TApzp...", | ||||
|  *     "url":"http:\/\/podunk.edu", | ||||
|  *     "url_sig":"T8Bp7j5...", | ||||
|  *   }, | ||||
|  *   "recipients": { optional recipient array }, | ||||
|  *   "callback":"\/post", | ||||
|  *   "version":1, | ||||
|  *   "secret":"1eaa...", | ||||
|  *   "secret_sig": "df89025470fac8..." | ||||
|  * } | ||||
|  * \endcode | ||||
|  * | ||||
|  * Signature fields are all signed with the sender channel private key and base64url encoded. | ||||
|  * Recipients are arrays of guid and guid_sig, which were previously signed with the recipients private  | ||||
| @@ -364,107 +359,115 @@ function post_init(&$a) { | ||||
|  * | ||||
|  * "pickup" packet: | ||||
|  * The pickup packet is sent in response to a notify packet from another site | ||||
|  *  | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  *  "type":"pickup", | ||||
|  *  "url":"http:\/\/example.com", | ||||
|  *  "callback":"http:\/\/example.com\/post", | ||||
|  *  "callback_sig":"teE1_fLI...", | ||||
|  *  "secret":"1eaa...", | ||||
|  *  "secret_sig":"O7nB4_..." | ||||
|  *   "type":"pickup", | ||||
|  *   "url":"http:\/\/example.com", | ||||
|  *   "callback":"http:\/\/example.com\/post", | ||||
|  *   "callback_sig":"teE1_fLI...", | ||||
|  *   "secret":"1eaa...", | ||||
|  *   "secret_sig":"O7nB4_..." | ||||
|  * } | ||||
|  * \endcode | ||||
|  * | ||||
|  * In the pickup packet, the sig fields correspond to the respective data element signed with this site's system  | ||||
|  * private key and then base64url encoded. | ||||
|  * In the pickup packet, the sig fields correspond to the respective data | ||||
|  * element signed with this site's system private key and then base64url encoded. | ||||
|  * The "secret" is the same as the original secret from the notify packet.  | ||||
|  * | ||||
|  * If verification is successful, a json structure is returned | ||||
|  * containing a success indicator and an array of type 'pickup'. | ||||
|  * Each pickup element contains the original notify request and a message field whose contents are  | ||||
|  * dependent on the message type | ||||
|  * If verification is successful, a json structure is returned containing a | ||||
|  * success indicator and an array of type 'pickup'. | ||||
|  * Each pickup element contains the original notify request and a message field | ||||
|  * whose contents are dependent on the message type. | ||||
|  * | ||||
|  * This JSON array is AES encapsulated using the site public key of the site that sent the initial zot pickup packet. | ||||
|  * This JSON array is AES encapsulated using the site public key of the site | ||||
|  * that sent the initial zot pickup packet. | ||||
|  * Using the above example, this would be example.com. | ||||
|  * | ||||
|  *  | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  * "success":1, | ||||
|  * "pickup":{ | ||||
|  *   "notify":{ | ||||
|  *     "type":"notify", | ||||
|  *     "sender":{ | ||||
|  *       "guid":"kgVFf_...", | ||||
|  *       "guid_sig":"PT9-TApz...", | ||||
|  *       "url":"http:\/\/z.podunk.edu", | ||||
|  *       "url_sig":"T8Bp7j5D..." | ||||
|  *     }, | ||||
|  *     "callback":"\/post", | ||||
|  *     "version":1, | ||||
|  *     "secret":"1eaa661..." | ||||
|  *   }, | ||||
|  *   "message":{ | ||||
|  *     "type":"activity", | ||||
|  *     "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", | ||||
|  *     "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", | ||||
|  *     "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", | ||||
|  *     "created":"2012-11-20 04:04:16", | ||||
|  *     "edited":"2012-11-20 04:04:16", | ||||
|  *     "title":"", | ||||
|  *     "body":"Hi Nickordo", | ||||
|  *     "app":"", | ||||
|  *     "verb":"post", | ||||
|  *     "object_type":"", | ||||
|  *     "target_type":"", | ||||
|  *     "permalink":"", | ||||
|  *     "location":"", | ||||
|  *     "longlat":"", | ||||
|  *     "owner":{ | ||||
|  *       "name":"Indigo", | ||||
|  *       "address":"indigo@podunk.edu", | ||||
|  *       "url":"http:\/\/podunk.edu", | ||||
|  *       "photo":{ | ||||
|  *         "mimetype":"image\/jpeg", | ||||
|  *         "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" | ||||
|  *   "success":1, | ||||
|  *   "pickup":{ | ||||
|  *     "notify":{ | ||||
|  *       "type":"notify", | ||||
|  *       "sender":{ | ||||
|  *         "guid":"kgVFf_...", | ||||
|  *         "guid_sig":"PT9-TApz...", | ||||
|  *         "url":"http:\/\/z.podunk.edu", | ||||
|  *         "url_sig":"T8Bp7j5D..." | ||||
|  *       }, | ||||
|  *       "guid":"kgVFf_...", | ||||
|  *       "guid_sig":"PT9-TAp...", | ||||
|  *       "callback":"\/post", | ||||
|  *       "version":1, | ||||
|  *       "secret":"1eaa661..." | ||||
|  *     }, | ||||
|  *     "author":{ | ||||
|  *       "name":"Indigo", | ||||
|  *       "address":"indigo@podunk.edu", | ||||
|  *       "url":"http:\/\/podunk.edu", | ||||
|  *       "photo":{ | ||||
|  *         "mimetype":"image\/jpeg", | ||||
|  *         "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" | ||||
|  *     "message":{ | ||||
|  *       "type":"activity", | ||||
|  *       "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", | ||||
|  *       "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", | ||||
|  *       "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", | ||||
|  *       "created":"2012-11-20 04:04:16", | ||||
|  *       "edited":"2012-11-20 04:04:16", | ||||
|  *       "title":"", | ||||
|  *       "body":"Hi Nickordo", | ||||
|  *       "app":"", | ||||
|  *       "verb":"post", | ||||
|  *       "object_type":"", | ||||
|  *       "target_type":"", | ||||
|  *       "permalink":"", | ||||
|  *       "location":"", | ||||
|  *       "longlat":"", | ||||
|  *       "owner":{ | ||||
|  *         "name":"Indigo", | ||||
|  *         "address":"indigo@podunk.edu", | ||||
|  *         "url":"http:\/\/podunk.edu", | ||||
|  *         "photo":{ | ||||
|  *           "mimetype":"image\/jpeg", | ||||
|  *           "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" | ||||
|  *         }, | ||||
|  *         "guid":"kgVFf_...", | ||||
|  *         "guid_sig":"PT9-TAp...", | ||||
|  *       }, | ||||
|  *       "guid":"kgVFf_...", | ||||
|  *       "guid_sig":"PT9-TAp..." | ||||
|  *       "author":{ | ||||
|  *         "name":"Indigo", | ||||
|  *         "address":"indigo@podunk.edu", | ||||
|  *         "url":"http:\/\/podunk.edu", | ||||
|  *         "photo":{ | ||||
|  *           "mimetype":"image\/jpeg", | ||||
|  *           "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" | ||||
|  *         }, | ||||
|  *         "guid":"kgVFf_...", | ||||
|  *         "guid_sig":"PT9-TAp..." | ||||
|  *       } | ||||
|  *     } | ||||
|  *   } | ||||
|  * } | ||||
|  *}  | ||||
|  * \endcode | ||||
|  * | ||||
|  * Currently defined message types are 'activity', 'mail', 'profile', 'location' and 'channel_sync',  | ||||
|  * which each have different content schemas. | ||||
|  * Currently defined message types are 'activity', 'mail', 'profile', 'location' | ||||
|  * and 'channel_sync', which each have different content schemas. | ||||
|  * | ||||
|  * Ping packet: | ||||
|  * A ping packet does not require any parameters except the type. It may or may not be encrypted. | ||||
|  * A ping packet does not require any parameters except the type. It may or may | ||||
|  * not be encrypted. | ||||
|  * | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  *  "type": "ping" | ||||
|  *   "type": "ping" | ||||
|  * } | ||||
|  * \endcode | ||||
|  * | ||||
|  * On receipt of a ping packet a ping response will be returned: | ||||
|  * | ||||
|  * \code{.json} | ||||
|  * { | ||||
|  *   "success" : 1, | ||||
|  *   "site" { | ||||
|  *       "url":"http:\/\/podunk.edu", | ||||
|  *       "url_sig":"T8Bp7j5...", | ||||
|  *       "sitekey": "-----BEGIN PUBLIC KEY----- | ||||
|  *                  MIICIjANBgkqhkiG9w0BAQE..." | ||||
|  *    } | ||||
|  *     "url": "http:\/\/podunk.edu", | ||||
|  *     "url_sig": "T8Bp7j5...", | ||||
|  *     "sitekey": "-----BEGIN PUBLIC KEY----- | ||||
|  *                 MIICIjANBgkqhkiG9w0BAQE..." | ||||
|  *   } | ||||
|  * } | ||||
|  * \endcode | ||||
|  * | ||||
|  * The ping packet can be used to verify that a site has not been re-installed, and to  | ||||
|  * initiate corrective action if it has. The url_sig is signed with the site private key | ||||
| @@ -479,21 +482,19 @@ function post_init(&$a) { | ||||
|  * If you have no records which match this url_sig and key - no corrective action should | ||||
|  * be taken as this packet may have been returned by an imposter.   | ||||
|  * | ||||
|  * @param[in,out] App &$a | ||||
|  */ | ||||
|  | ||||
| 	 | ||||
| function post_post(&$a) { | ||||
|  | ||||
|  | ||||
| 	$encrypted_packet = false; | ||||
| 	$ret = array('success' => false); | ||||
|  | ||||
| 	$data = json_decode($_REQUEST['data'],true); | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	 * Many message packets will arrive encrypted. The existence of an 'iv' element  | ||||
| 	 * tells us we need to unencapsulate the AES-256-CBC content using the site private key | ||||
| 	/* | ||||
| 	 * Many message packets will arrive encrypted. The existence of an 'iv' | ||||
| 	 * element tells us we need to unencapsulate the AES-256-CBC content using | ||||
| 	 * the site private key. | ||||
| 	 */ | ||||
|  | ||||
| 	if($data && array_key_exists('iv',$data)) { | ||||
| @@ -539,12 +540,11 @@ function post_post(&$a) { | ||||
|  | ||||
| 	if($msgtype === 'pickup') { | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * The 'pickup' message arrives with a tracking ID which is associated with a particular outq_hash | ||||
| 		 * First verify that that the returned signatures verify, then check that we have an outbound queue item | ||||
| 		 * with the correct hash. | ||||
| 		 * If everything verifies, find any/all outbound messages in the queue for this hubloc and send them back | ||||
| 		 * | ||||
| 		 */ | ||||
|  | ||||
| 		if((! $data['secret']) || (! $data['secret_sig'])) { | ||||
| @@ -597,7 +597,7 @@ function post_post(&$a) { | ||||
| 			json_return_and_die($ret); | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * If we made it to here, the signatures verify, but we still don't know if the tracking ID is valid. | ||||
| 		 * It wouldn't be an error if the tracking ID isn't found, because we may have sent this particular | ||||
| 		 * queue item with another pickup (after the tracking ID for the other pickup  was verified).  | ||||
| @@ -613,7 +613,7 @@ function post_post(&$a) { | ||||
| 			json_return_and_die($ret); | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * Everything is good if we made it here, so find all messages that are going to this location | ||||
| 		 * and send them all. | ||||
| 		 */ | ||||
| @@ -651,33 +651,31 @@ function post_post(&$a) { | ||||
| 		$encrypted = crypto_encapsulate(json_encode($ret),$sitekey); | ||||
| 		json_return_and_die($encrypted); | ||||
|  | ||||
| 		/** pickup: end */ | ||||
| 		/* pickup: end */ | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * All other message types require us to verify the sender. This is a generic check, so we  | ||||
| 	 * will do it once here and bail if anything goes wrong. | ||||
| 	 */ | ||||
|  | ||||
| 	if(array_key_exists('sender',$data)) { | ||||
| 	if (array_key_exists('sender',$data)) { | ||||
| 		$sender = $data['sender']; | ||||
| 	} | ||||
|  | ||||
| 	/** Check if the sender is already verified here */ | ||||
| 	/* Check if the sender is already verified here */ | ||||
|  | ||||
| 	$hub = zot_gethub($sender); | ||||
|  | ||||
| 	if(! $hub) { | ||||
| 	if (! $hub) { | ||||
|  | ||||
| 		/** Have never seen this guid or this guid coming from this location. Check it and register it. */ | ||||
| 		/* Have never seen this guid or this guid coming from this location. Check it and register it. */ | ||||
|  | ||||
| 		// (!!) this will validate the sender | ||||
| 		$result = zot_register_hub($sender); | ||||
|  | ||||
| 		if((! $result['success']) || (! ($hub = zot_gethub($sender)))) { | ||||
| 		if ((! $result['success']) || (! ($hub = zot_gethub($sender)))) { | ||||
| 			$ret['message'] = 'Hub not available.'; | ||||
| 			logger('mod_zot: no hub'); | ||||
| 			json_return_and_die($ret); | ||||
| @@ -695,12 +693,12 @@ function post_post(&$a) { | ||||
|  | ||||
| 	// a dead hub came back to life - reset any tombstones we might have | ||||
|  | ||||
| 	if($hub['hubloc_status'] & HUBLOC_OFFLINE) { | ||||
| 	if ($hub['hubloc_status'] & HUBLOC_OFFLINE) { | ||||
| 		q("update hubloc set hubloc_status = (hubloc_status & ~%d) where hubloc_id = %d", | ||||
| 			intval(HUBLOC_OFFLINE), | ||||
| 			intval($hub['hubloc_id'])		 | ||||
| 		); | ||||
| 		if($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) { | ||||
| 		if ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) { | ||||
| 			q("update hubloc set hubloc_flags = (hubloc_flags & ~%d) where hubloc_id = %d", | ||||
| 				intval(HUBLOC_FLAGS_ORPHANCHECK), | ||||
| 				intval($hub['hubloc_id']) | ||||
| @@ -714,12 +712,10 @@ function post_post(&$a) { | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	/**  | ||||
| 	/* | ||||
| 	 * This hub has now been proven to be valid. | ||||
| 	 * Any hub with the same URL and a different sitekey cannot be valid. | ||||
| 	 * Get rid of them (mark them deleted). There's a good chance they were re-installs. | ||||
| 	 * | ||||
| 	 */ | ||||
|  | ||||
| 	q("update hubloc set hubloc_flags = ( hubloc_flags | %d ) where hubloc_url = '%s' and hubloc_sitekey != '%s' ", | ||||
| @@ -728,15 +724,15 @@ function post_post(&$a) { | ||||
| 		dbesc($hub['hubloc_sitekey']) | ||||
| 	); | ||||
|  | ||||
| 	// TODO: check which hub is primary and take action if mismatched | ||||
| 	/** @TODO check which hub is primary and take action if mismatched */ | ||||
|  | ||||
| 	if(array_key_exists('recipients',$data)) | ||||
| 	if (array_key_exists('recipients', $data)) | ||||
| 		$recipients = $data['recipients']; | ||||
|  | ||||
|  | ||||
| 	if($msgtype === 'auth_check') { | ||||
| 	if ($msgtype === 'auth_check') { | ||||
|  | ||||
| 		/** | ||||
| 		/* | ||||
| 		 * Requestor visits /magic/?dest=somewhere on their own site with a browser | ||||
| 		 * magic redirects them to $destsite/post [with auth args....] | ||||
| 		 * $destsite sends an auth_check packet to originator site | ||||
| @@ -751,7 +747,7 @@ function post_post(&$a) { | ||||
| 		 */ | ||||
| 		logger('mod_zot: auth_check', LOGGER_DEBUG); | ||||
|  | ||||
| 		if(! $encrypted_packet) { | ||||
| 		if (! $encrypted_packet) { | ||||
| 			logger('mod_zot: auth_check packet was not encrypted.'); | ||||
| 			$ret['message'] .= 'no packet encryption' . EOL; | ||||
| 			json_return_and_die($ret); | ||||
| @@ -774,7 +770,7 @@ function post_post(&$a) { | ||||
| 		// First verify their signature. We will have obtained a zot-info packet from them as part of the sender | ||||
| 		// verification.  | ||||
|  | ||||
| 		if((! $y) || (! rsa_verify($data['secret'],base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { | ||||
| 		if ((! $y) || (! rsa_verify($data['secret'], base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { | ||||
| 			logger('mod_zot: auth_check: sender not found or secret_sig invalid.'); | ||||
| 			$ret['message'] .= 'sender not found or sig invalid ' . print_r($y,true) . EOL; | ||||
| 			json_return_and_die($ret); | ||||
| @@ -784,14 +780,14 @@ function post_post(&$a) { | ||||
|  | ||||
| 		$ret['message'] .= 'recipients ' . print_r($recipients,true) . EOL; | ||||
|  | ||||
| 		if($data['recipients']) { | ||||
| 		if ($data['recipients']) { | ||||
|  | ||||
| 			$arr = $data['recipients'][0]; | ||||
| 			$recip_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); | ||||
| 			$recip_hash = make_xchan_hash($arr['guid'], $arr['guid_sig']); | ||||
| 			$c = q("select channel_id, channel_account_id, channel_prvkey from channel where channel_hash = '%s' limit 1", | ||||
| 				dbesc($recip_hash) | ||||
| 			); | ||||
| 			if(! $c) { | ||||
| 			if (! $c) { | ||||
| 				logger('mod_zot: auth_check: recipient channel not found.'); | ||||
| 				$ret['message'] .= 'recipient not found.' . EOL; | ||||
| 				json_return_and_die($ret); | ||||
| @@ -807,7 +803,7 @@ function post_post(&$a) { | ||||
| 				dbesc($data['secret']), | ||||
| 				dbesc($data['sender']['url']) | ||||
| 			); | ||||
| 			if(! $z) { | ||||
| 			if (! $z) { | ||||
| 				logger('mod_zot: auth_check: verification key not found.'); | ||||
| 				$ret['message'] .= 'verification key not found' . EOL; | ||||
| 				json_return_and_die($ret); | ||||
| @@ -823,56 +819,53 @@ function post_post(&$a) { | ||||
| 			logger('mod_zot: auth_check: success', LOGGER_DEBUG); | ||||
| 			$ret['success'] = true; | ||||
| 			$ret['confirm'] = $confirm; | ||||
| 			if($u && $u[0]['account_service_class']) | ||||
| 			if ($u && $u[0]['account_service_class']) | ||||
| 				$ret['service_class'] = $u[0]['account_service_class']; | ||||
|  | ||||
| 			// Set "do not track" flag if this site or this channel's profile is restricted | ||||
| 			// in some way | ||||
|  | ||||
| 			if(intval(get_config('system','block_public'))) | ||||
| 			if (intval(get_config('system','block_public'))) | ||||
| 				$ret['DNT'] = true; | ||||
| 			if(! perm_is_allowed($c[0]['channel_id'],'','view_profile')) | ||||
| 			if (! perm_is_allowed($c[0]['channel_id'],'','view_profile')) | ||||
| 				$ret['DNT'] = true; | ||||
| 			if(get_pconfig($c[0]['channel_id'],'system','do_not_track')) | ||||
| 			if (get_pconfig($c[0]['channel_id'],'system','do_not_track')) | ||||
| 				$ret['DNT'] = true; | ||||
| 			if(get_pconfig($c[0]['channel_id'],'system','hide_online_status')) | ||||
| 			if (get_pconfig($c[0]['channel_id'],'system','hide_online_status')) | ||||
| 				$ret['DNT'] = true; | ||||
|  | ||||
| 			json_return_and_die($ret); | ||||
|  | ||||
| 		} | ||||
| 		json_return_and_die($ret); | ||||
| 	} | ||||
|  | ||||
| 	if($msgtype === 'request') { | ||||
| 	if ($msgtype === 'request') { | ||||
| 		// request a particular post/conversation by message_id | ||||
| 		$x = zot_process_message_request($data); | ||||
| 		json_return_and_die($x);		 | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	if($msgtype === 'purge') { | ||||
| 		if($recipients) { | ||||
| 	if ($msgtype === 'purge') { | ||||
| 		if ($recipients) { | ||||
| 			// basically this means "unfriend" | ||||
| 			foreach($recipients as $recip) { | ||||
| 			foreach ($recipients as $recip) { | ||||
| 				$r = q("select channel.*,xchan.* from channel  | ||||
| 					left join xchan on channel_hash = xchan_hash | ||||
| 					where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", | ||||
| 					dbesc($recip['guid']), | ||||
| 					dbesc($recip['guid_sig']) | ||||
| 				); | ||||
| 				if($r) { | ||||
| 				if ($r) { | ||||
| 					$r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1", | ||||
| 						intval($r[0]['channel_id']), | ||||
| 						dbesc(make_xchan_hash($sender['guid'],$sender['guid_sig'])) | ||||
| 					); | ||||
| 					if($r) { | ||||
| 					if ($r) { | ||||
| 						contact_remove($r[0]['channel_id'],$r[0]['abook_id']); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			// Unfriend everybody - basically this means the channel has committed suicide | ||||
| 			$arr = $data['sender']; | ||||
| 			$sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); | ||||
| @@ -882,11 +875,10 @@ function post_post(&$a) { | ||||
|  | ||||
| 			$ret['success'] = true; | ||||
| 			json_return_and_die($ret); | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(($msgtype === 'refresh') || ($msgtype === 'force_refresh')) { | ||||
| 	if (($msgtype === 'refresh') || ($msgtype === 'force_refresh')) { | ||||
|  | ||||
| 		// remote channel info (such as permissions or photo or something) | ||||
| 		// has been updated. Grab a fresh copy and sync it. | ||||
| @@ -894,11 +886,11 @@ function post_post(&$a) { | ||||
| 		// force_refresh unconditionally creates a directory update record, | ||||
| 		// even if no changes were detected upon processing. | ||||
|  | ||||
| 		if($recipients) { | ||||
| 		if ($recipients) { | ||||
|  | ||||
| 			// This would be a permissions update, typically for one connection | ||||
|  | ||||
| 			foreach($recipients as $recip) {	 | ||||
| 			foreach ($recipients as $recip) { | ||||
| 				$r = q("select channel.*,xchan.* from channel  | ||||
| 					left join xchan on channel_hash = xchan_hash | ||||
| 					where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", | ||||
| @@ -910,10 +902,9 @@ function post_post(&$a) { | ||||
| 						'xchan_guid'     => $sender['guid'],  | ||||
| 						'xchan_guid_sig' => $sender['guid_sig'], | ||||
| 						'hubloc_url'     => $sender['url'] | ||||
| 				),$r[0], (($msgtype === 'force_refresh') ? true : false)); | ||||
| 				), $r[0], (($msgtype === 'force_refresh') ? true : false)); | ||||
| 			} | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
|  | ||||
| 			// system wide refresh | ||||
|  | ||||
| @@ -921,33 +912,27 @@ function post_post(&$a) { | ||||
| 				'xchan_guid'     => $sender['guid'],  | ||||
| 				'xchan_guid_sig' => $sender['guid_sig'], | ||||
| 				'hubloc_url'     => $sender['url'] | ||||
| 			),null,(($msgtype === 'force_refresh') ? true : false)); | ||||
| 			), null, (($msgtype === 'force_refresh') ? true : false)); | ||||
| 		} | ||||
| 		$ret['success'] = true; | ||||
| 		json_return_and_die($ret); | ||||
| 	} | ||||
|  | ||||
| 	if($msgtype === 'notify') { | ||||
| 	if ($msgtype === 'notify') { | ||||
| 		$async = get_config('system','queued_fetch'); | ||||
|  | ||||
| 		if($async) { | ||||
| 		if ($async) { | ||||
| 			// add to receive queue | ||||
| 			// qreceive_add($data); | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			$x = zot_fetch($data); | ||||
| 			$ret['delivery_report'] = $x; | ||||
| 		} | ||||
|  | ||||
| 		$ret['success'] = true; | ||||
| 		json_return_and_die($ret); | ||||
|  | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	// catchall | ||||
| 	json_return_and_die($ret); | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ function randprof_init(&$a) { | ||||
| 	$x = random_profile(); | ||||
| 	if($x) | ||||
| 		goaway(chanlink_url($x)); | ||||
| 	// FIXME this doesn't work at the moment as a fallback | ||||
|  | ||||
| 	/** FIXME this doesn't work at the moment as a fallback */ | ||||
| 	goaway($a->get_baseurl() . '/profile'); | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,17 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * With args, register a directory server for this realm | ||||
|  * With no args, return a JSON array of directory servers for this realm | ||||
|  | ||||
|  * FIXME: Not yet implemented: Some realms may require authentication to join their realm. | ||||
|  * With args, register a directory server for this realm. | ||||
|  * With no args, return a JSON array of directory servers for this realm. | ||||
|  * | ||||
|  * @FIXME Not yet implemented: Some realms may require authentication to join their realm. | ||||
|  * The RED_GLOBAL realm does not require authentication. | ||||
|  * We would then need a flag in the site table to indicate that they've been | ||||
|  * validated by the PRIMARY directory for that realm. Sites claiming to be PRIMARY | ||||
|  * but are not the realm PRIMARY will be marked invalid. | ||||
|  *  | ||||
|  * @param App &$a | ||||
|  */ | ||||
|  | ||||
|  | ||||
| function regdir_init(&$a) { | ||||
|  | ||||
| 	$result = array('success' => false); | ||||
| @@ -31,8 +30,7 @@ function regdir_init(&$a) { | ||||
|  | ||||
| 	if($realm === DIRECTORY_REALM) { | ||||
| 		$valid = 1; | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
| 		$token = get_config('system','realm_token'); | ||||
| 		if($token && $access_token != $token) { | ||||
| 			$result['message'] = 'This realm requires an access token'; | ||||
| @@ -43,16 +41,16 @@ function regdir_init(&$a) { | ||||
|  | ||||
| 	$dirmode = intval(get_config('system','directory_mode')); | ||||
|  | ||||
| 	if($dirmode == DIRECTORY_MODE_NORMAL) { | ||||
| 	if ($dirmode == DIRECTORY_MODE_NORMAL) { | ||||
| 		$ret['message'] = t('This site is not a directory server'); | ||||
| 		json_return_and_die($ret); | ||||
| 	} | ||||
|  | ||||
| 	$m = null; | ||||
| 	if($url) { | ||||
| 	if ($url) { | ||||
| 		$m = parse_url($url); | ||||
|  | ||||
| 		if((! $m) || (! @dns_get_record($m['host'], DNS_A + DNS_CNAME + DNS_PTR)) || (! filter_var($m['host'], FILTER_VALIDATE_IP) )) { | ||||
| 		if ((! $m) || (! @dns_get_record($m['host'], DNS_A + DNS_CNAME + DNS_PTR)) || (! filter_var($m['host'], FILTER_VALIDATE_IP) )) { | ||||
| 			$result['message'] = 'unparseable url'; | ||||
| 			json_return_and_die($result); | ||||
| 		} | ||||
| @@ -75,31 +73,28 @@ function regdir_init(&$a) { | ||||
| 		); | ||||
|  | ||||
| 		json_return_and_die($result); | ||||
| 	} | ||||
| 	else { | ||||
| 	} else { | ||||
|  | ||||
| 		// We can put this in the sql without the condition after 31 april 2015 assuming | ||||
| 		// most directory servers will have updated by then | ||||
| 		// This just makes sure it happens if I forget | ||||
|  | ||||
| 		$sql_extra = ((datetime_convert() > datetime_convert('UTC','UTC','2015-04-31')) ? ' and site_valid = 1 ' : '' ); | ||||
| 		if($dirmode == DIRECTORY_MODE_STANDALONE) { | ||||
| 		if ($dirmode == DIRECTORY_MODE_STANDALONE) { | ||||
| 			$r = array(array('site_url' => z_root())); | ||||
| 		} | ||||
| 		else { | ||||
| 		} else { | ||||
| 			$r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' $sql_extra ", | ||||
| 				dbesc(get_directory_realm()) | ||||
| 			); | ||||
| 		} | ||||
| 		if($r) { | ||||
| 		if ($r) { | ||||
| 			$result['success'] = true; | ||||
| 			$result['directories'] = array(); | ||||
| 			foreach($r as $rr) | ||||
| 			foreach ($r as $rr) | ||||
| 				$result['directories'][] = $rr['site_url']; | ||||
|  | ||||
| 			json_return_and_die($result); | ||||
| 		} | ||||
| 	} | ||||
| 	json_return_and_die($result); | ||||
| 		 | ||||
|  | ||||
| } | ||||
| @@ -13,7 +13,6 @@ function share_init(&$a) { | ||||
| 	if(! (local_channel() || remote_channel())) | ||||
| 		killme(); | ||||
|  | ||||
|  | ||||
| 	$r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d  LIMIT 1", | ||||
| 		intval($post_id) | ||||
| 	); | ||||
| @@ -30,13 +29,12 @@ function share_init(&$a) { | ||||
| 	if(! $r) | ||||
| 		killme(); | ||||
|  | ||||
| 	// FIXME - we only share bbcode | ||||
| 	/** @FIXME we only share bbcode */ | ||||
|  | ||||
| 	if($r[0]['mimetype'] !== 'text/bbcode') | ||||
| 		killme(); | ||||
|  | ||||
| 	// FIXME - eventually we want to post remotely via rpost | ||||
| 	// on your home site. | ||||
| 	/** @FIXME eventually we want to post remotely via rpost on your home site */ | ||||
| 	// When that works remove this next bit: | ||||
|  | ||||
| 	if(! local_channel()) | ||||
| @@ -70,14 +68,14 @@ function share_init(&$a) { | ||||
| 	if($parsed) { | ||||
| 		$post_url = $parsed['scheme'] . ':' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') | ||||
| 			. '/rpost'; | ||||
| 		// FIXME - we were probably called from JS | ||||
| 		// so we don't know the return page. | ||||
| 		// in fact we won't be able to load the remote page. | ||||
| 		// we might need an iframe | ||||
|  | ||||
| 		/** | ||||
| 		 * @FIXME we were probably called from JS so we don't know the return page. | ||||
| 		 * In fact we won't be able to load the remote page. | ||||
| 		 * we might need an iframe | ||||
| 		 */ | ||||
|  | ||||
| 		$x = z_post_url($post_url, array('f' => '', 'body' => $o )); | ||||
| 		killme(); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,8 @@ | ||||
| <?php /** @file */ | ||||
| <?php | ||||
| /** | ||||
|  * @file mod/thing.php | ||||
|  * @brief | ||||
|  */ | ||||
|  | ||||
| require_once('include/items.php'); | ||||
| require_once('include/contact_selectors.php'); | ||||
| @@ -9,9 +13,6 @@ function thing_init(&$a) { | ||||
| 	if(! local_channel()) | ||||
| 		return; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	$account_id = $a->get_account(); | ||||
| 	$channel    = $a->get_channel(); | ||||
|  | ||||
| @@ -26,19 +27,18 @@ function thing_init(&$a) { | ||||
|  | ||||
| 	$hash = random_string(); | ||||
|  | ||||
|  | ||||
| 	$verbs = obj_verbs(); | ||||
|  | ||||
| 	/** | ||||
| 	 * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"  | ||||
| 	 * We use the first person form when creating an activity, but the third person for use in activities | ||||
| 	 * FIXME: There is no accounting for verb gender for languages where this is significant. We may eventually | ||||
| 	 * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually | ||||
| 	 * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module. | ||||
| 	 */ | ||||
|  | ||||
| 	$translated_verb = $verbs[$verb][1]; | ||||
|  | ||||
| 	/**  | ||||
| 	/* | ||||
| 	 * The site administrator can do things that normals cannot. | ||||
| 	 * This is restricted because it will likely cause | ||||
| 	 * an activitystreams protocol violation and the activity might | ||||
| @@ -52,12 +52,12 @@ function thing_init(&$a) { | ||||
| 			$translated_verb = $verb; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Things, objects: We do not provide definite (a, an) or indefinite (the) articles or singular/plural designators | ||||
| 	 * That needs to be specified in your thing. e.g. Mike has "a carrot", Greg wants "balls", Bob likes "the Boston Red Sox".   | ||||
| 	 */ | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * Future work on this module might produce more complex activities with targets, e.g. Phillip likes Karen's moustache | ||||
| 	 * and to describe other non-thing objects like channels, such as Karl wants Susan - where Susan represents a channel profile. | ||||
| 	 */ | ||||
| @@ -65,8 +65,6 @@ function thing_init(&$a) { | ||||
| 	if((! $name) || (! $translated_verb)) | ||||
| 		return; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	if($term_hash) { | ||||
| 		$t = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", | ||||
| 			intval(TERM_OBJ_THING), | ||||
| @@ -115,7 +113,6 @@ function thing_init(&$a) { | ||||
| 		$local_photo_type = $arr[3]; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	$r = q("select * from term where uid = %d and otype = %d and type = %d and term = '%s' limit 1", | ||||
| 		intval(local_channel()), | ||||
| 		intval(TERM_OBJ_THING), | ||||
| @@ -159,14 +156,12 @@ function thing_init(&$a) { | ||||
|  | ||||
| 	info( t('Thing added')); | ||||
|  | ||||
|  | ||||
| 	if($activity) { | ||||
| 		$arr = array(); | ||||
| 		$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $term['url'])); | ||||
| 		if($local_photo) | ||||
| 			$links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo); | ||||
|  | ||||
|  | ||||
| 		$objtype = ACTIVITY_OBJ_THING; | ||||
|  | ||||
| 		$obj = json_encode(array( | ||||
| @@ -182,7 +177,6 @@ function thing_init(&$a) { | ||||
| 		$arr['owner_xchan']  = $channel['channel_hash']; | ||||
| 		$arr['author_xchan'] = $channel['channel_hash']; | ||||
|  | ||||
|  | ||||
| 		$arr['item_flags'] = ITEM_ORIGIN|ITEM_WALL|ITEM_THREAD_TOP; | ||||
|  | ||||
| 		$ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]'; | ||||
| @@ -250,11 +244,9 @@ function thing_content(&$a) { | ||||
|  | ||||
| 	$thing_hash = ''; | ||||
|  | ||||
|  | ||||
| 	if(argc() == 3 && argv(1) === 'edit') { | ||||
| 		$thing_hash = argv(2); | ||||
|  | ||||
|  | ||||
| 		$r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", | ||||
| 			intval(TERM_OBJ_THING), | ||||
| 			dbesc($thing_hash) | ||||
| @@ -265,7 +257,6 @@ function thing_content(&$a) { | ||||
| 			return ''; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		$o .= replace_macros(get_markup_template('thing_edit.tpl'),array( | ||||
| 			'$thing_hdr' => t('Edit Thing'), | ||||
| 			'$multiprof' => feature_enabled(local_channel(),'multi_profiles'), | ||||
| @@ -300,7 +291,6 @@ function thing_content(&$a) { | ||||
| 			return ''; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		$x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d", | ||||
| 			dbesc($thing_hash), | ||||
| 			intval(TERM_OBJ_THING), | ||||
| @@ -310,6 +300,7 @@ function thing_content(&$a) { | ||||
| 			dbesc($thing_hash), | ||||
| 			intval(local_channel()) | ||||
| 		); | ||||
|  | ||||
| 		return $o; | ||||
| 	} | ||||
|  | ||||
| @@ -328,6 +319,4 @@ function thing_content(&$a) { | ||||
| 	)); | ||||
|  | ||||
| 	return $o; | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| INPUT = index.php boot.php mod/ include/ setup/ util/ view/ | ||||
| INPUT = README.md index.php boot.php mod/ include/ util/ view/ version.inc | ||||
| RECURSIVE = YES | ||||
| PROJECT_NAME = "The RedMatrix" | ||||
| PROJECT_LOGO = images/rm-64.png | ||||
| @@ -12,9 +12,12 @@ GENERATE_LATEX = NO | ||||
| EXTRACT_ALL = YES | ||||
| EXTRACT_PRIVATE = YES | ||||
| GENERATE_TODOLIST = YES | ||||
| USE_MDFILE_AS_MAINPAGE = README | ||||
| USE_MDFILE_AS_MAINPAGE = README.md | ||||
| REFERENCED_BY_RELATION = YES | ||||
| GENERATE_TREEVIEW = YES | ||||
| HTML_FOOTER = util/Doxygen.footer | ||||
| ALIASES += "license=@par License:\n" | ||||
| ALIASES += "fixme=\xrefitem fixme \"Fixme\" \"Fixme List\"" | ||||
| ALIASES += "FIXME=\fixme" | ||||
| ALIASES += "TODO=\todo" | ||||
| ALIASES += "BUG=\bug" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user