account.php 24.2 KB
Newer Older
1 2 3 4 5
<?php
/**
 * @file include/account.php
 * @brief Somme account related functions.
 */
friendica's avatar
friendica committed
6 7 8 9 10 11 12

require_once('include/config.php');
require_once('include/network.php');
require_once('include/plugin.php');
require_once('include/text.php');
require_once('include/language.php');
require_once('include/datetime.php');
13
require_once('include/crypto.php');
14
require_once('include/channel.php');
friendica's avatar
friendica committed
15

16

17 18 19 20 21 22 23
function get_account_by_id($account_id) {
	$r = q("select * from account where account_id = %d",
		intval($account_id)
	);
	return (($r) ? $r[0] : false);
}

24 25
function check_account_email($email) {

26
	$email = punify($email);
27 28
	$result = array('error' => false, 'message' => '');

29 30
	// Caution: empty email isn't counted as an error in this function. 
	// Check for empty value separately. 
31 32 33 34

	if(! strlen($email))
		return $result;

35
	if(! validate_email($email))
36 37 38 39 40 41 42
		$result['message'] .= t('Not a valid email address') . EOL;
	elseif(! allowed_email($email))
		$result['message'] = t('Your email domain is not among those allowed on this site');
	else {	
		$r = q("select account_email from account where account_email = '%s' limit 1",
			dbesc($email)
		);
43
		if($r) {
44 45 46 47 48 49
			$result['message'] .= t('Your email address is already registered at this site.');
		}
	}
	if($result['message'])
		$result['error'] = true;

50 51 52 53
	$arr = array('email' => $email, 'result' => $result);
	call_hooks('check_account_email', $arr);

	return $arr['result'];
54 55
}

56 57 58
function check_account_password($password) {
	$result = array('error' => false, 'message' => '');

59
	// The only validation we perform by default is pure Javascript to
60
	// check minimum length and that both entered passwords match.
61
	// Use hooked functions to perform complexity requirement checks.
62 63 64

	$arr = array('password' => $password, 'result' => $result);
	call_hooks('check_account_password', $arr);
65

66 67
	return $arr['result'];
}
68

69 70
function check_account_invite($invite_code) {
	$result = array('error' => false, 'message' => '');
friendica's avatar
friendica committed
71 72 73 74

	$using_invites = get_config('system','invitation_only');

	if($using_invites) {
75
		if(! $invite_code) {
friendica's avatar
friendica committed
76 77
			$result['message'] .= t('An invitation is required.') . EOL;
		}
Zot's avatar
Zot committed
78
		$r = q("select * from register where hash = '%s' limit 1", dbesc($invite_code));
jeroenpraat's avatar
jeroenpraat committed
79
		if(! $r) {
friendica's avatar
friendica committed
80 81
			$result['message'] .= t('Invitation could not be verified.') . EOL;
		}
82 83 84 85 86 87 88 89 90 91
	}
	if(strlen($result['message']))
		$result['error'] = true;

	$arr = array('invite_code' => $invite_code, 'result' => $result);
	call_hooks('check_account_invite', $arr);

	return $arr['result'];
}

92 93 94
function check_account_admin($arr) {
	if(is_site_admin())
		return true;
friendica's avatar
friendica committed
95
	$admin_email = trim(get_config('system','admin_email'));
96 97 98 99 100
	if(strlen($admin_email) && $admin_email === trim($arr['email']))
		return true;
	return false;
}

101
function account_total() {
friendica's avatar
friendica committed
102
	$r = q("select account_id from account where true");
103 104 105 106 107
	if(is_array($r))
		return count($r);
	return false;
}

108

Zot's avatar
Zot committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
function account_store_lowlevel($arr) {

    $store = [
        'account_parent'           => ((array_key_exists('account_parent',$arr))           ? $arr['account_parent']           : '0'),
        'account_default_channel'  => ((array_key_exists('account_default_channel',$arr))  ? $arr['account_default_channel']  : '0'),
        'account_salt'             => ((array_key_exists('account_salt',$arr))             ? $arr['account_salt']             : ''),
        'account_password'         => ((array_key_exists('account_password',$arr))         ? $arr['account_password']         : ''),
        'account_email'            => ((array_key_exists('account_email',$arr))            ? $arr['account_email']            : ''),
        'account_external'         => ((array_key_exists('account_external',$arr))         ? $arr['account_external']         : ''),
        'account_language'         => ((array_key_exists('account_language',$arr))         ? $arr['account_language']         : 'en'),
        'account_created'          => ((array_key_exists('account_created',$arr))          ? $arr['account_created']          : '0001-01-01 00:00:00'),
        'account_lastlog'          => ((array_key_exists('account_lastlog',$arr))          ? $arr['account_lastlog']          : '0001-01-01 00:00:00'),
        'account_flags'            => ((array_key_exists('account_flags',$arr))            ? $arr['account_flags']            : '0'),
        'account_roles'            => ((array_key_exists('account_roles',$arr))            ? $arr['account_roles']            : '0'),
        'account_reset'            => ((array_key_exists('account_reset',$arr))            ? $arr['account_reset']            : ''),
        'account_expires'          => ((array_key_exists('account_expires',$arr))          ? $arr['account_expires']          : '0001-01-01 00:00:00'),
        'account_expire_notified'  => ((array_key_exists('account_expire_notified',$arr))  ? $arr['account_expire_notified']  : '0001-01-01 00:00:00'),
        'account_service_class'    => ((array_key_exists('account_service_class',$arr))    ? $arr['account_service_class']    : ''),
M. Dent's avatar
M. Dent committed
127
        'account_level'            => '5',
Zot's avatar
Zot committed
128 129 130 131 132 133 134 135
        'account_password_changed' => ((array_key_exists('account_password_changed',$arr)) ? $arr['account_password_changed'] : '0001-01-01 00:00:00')
	];

	return create_table_from_array('account',$store);

}


136 137 138 139 140 141 142
function create_account($arr) {

	// Required: { email, password }

	$result = array('success' => false, 'email' => '', 'password' => '', 'message' => '');

	$invite_code = ((x($arr,'invite_code'))   ? notags(trim($arr['invite_code']))  : '');
143
	$email       = ((x($arr,'email'))         ? notags(punify(trim($arr['email']))) : '');
144 145 146 147
	$password    = ((x($arr,'password'))      ? trim($arr['password'])             : '');
	$password2   = ((x($arr,'password2'))     ? trim($arr['password2'])            : '');
	$parent      = ((x($arr,'parent'))        ? intval($arr['parent'])             : 0 );
	$flags       = ((x($arr,'account_flags')) ? intval($arr['account_flags'])      : ACCOUNT_OK);
148
	$roles       = ((x($arr,'account_roles')) ? intval($arr['account_roles'])      : 0 );
149
	$expires     = ((x($arr,'expires'))       ? intval($arr['expires'])            : NULL_DATE);
150
	$techlevel   = ((array_key_exists('techlevel',$arr)) ? intval($arr['techlevel']) : intval(get_config('system','techlevel')));
151

152
	$default_service_class = get_config('system','default_service_class');
153

154 155 156
	if($default_service_class === false)
		$default_service_class = '';

friendica's avatar
friendica committed
157
	if((! x($email)) || (! x($password))) {
158 159 160 161
		$result['message'] = t('Please enter the required information.');
		return $result;
	}

162 163
	// prevent form hackery

164 165 166 167 168 169 170
	if($roles & ACCOUNT_ROLE_ADMIN) {
		$admin_result = check_account_admin($arr);
		if(! $admin_result) {
			$roles = 0;
		}
	}

171 172 173
	// allow the admin_email account to be admin, but only if it's the first account.

	$c = account_total();
174
	if (($c === 0) && (check_account_admin($arr)))
175 176
		$roles |= ACCOUNT_ROLE_ADMIN;

177
	// Ensure that there is a host keypair.
178

179 180 181 182 183
	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']);
	}
184

185
	$invite_result = check_account_invite($invite_code);
friendica's avatar
friendica committed
186
	if($invite_result['error']) {
187 188
		$result['message'] = $invite_result['message'];
		return $result;
friendica's avatar
friendica committed
189 190
	}

191
	$email_result = check_account_email($email);
192

friendica's avatar
friendica committed
193
	if($email_result['error']) {
194
		$result['message'] = $email_result['message'];
friendica's avatar
friendica committed
195 196 197
		return $result;
	}

198 199
	$password_result = check_account_password($password);

friendica's avatar
friendica committed
200
	if($password_result['error']) {
201 202 203 204
		$result['message'] = $password_result['message'];
		return $result;
	}

friendica's avatar
friendica committed
205 206
	$salt = random_string(32);
	$password_encoded = hash('whirlpool', $salt . $password);
friendica's avatar
friendica committed
207

Zot's avatar
Zot committed
208 209 210 211 212 213 214 215 216 217
	$r = account_store_lowlevel(
		[
			'account_parent'        => intval($parent),
			'account_salt'          => $salt,
			'account_password'      => $password_encoded,
			'account_email'         => $email,
			'account_language'      => get_best_language(),
			'account_created'       => datetime_convert(),
			'account_flags'         => intval($flags),
			'account_roles'         => intval($roles),
M. Dent's avatar
M. Dent committed
218
			'account_level'         => 5,
Zot's avatar
Zot committed
219 220 221
			'account_expires'       => $expires,
			'account_service_class' => $default_service_class
		]
friendica's avatar
friendica committed
222
	);
223 224 225 226 227
	if(! $r) {
		logger('create_account: DB INSERT failed.');
		$result['message'] = t('Failed to store account information.');
		return($result);
	}
friendica's avatar
friendica committed
228

friendica's avatar
friendica committed
229
	$r = q("select * from account where account_email = '%s' and account_password = '%s' limit 1",
friendica's avatar
friendica committed
230 231 232 233 234 235
		dbesc($email),
		dbesc($password_encoded)
	);
	if($r && count($r)) {
		$result['account'] = $r[0];
	}
236
	else {
friendica's avatar
friendica committed
237 238 239
		logger('create_account: could not retrieve newly created account');
	}

friendica's avatar
friendica committed
240 241 242
	// Set the parent record to the current record_id if no parent was provided

	if(! $parent) {
243
		$r = q("update account set account_parent = %d where account_id = %d",
friendica's avatar
friendica committed
244 245 246 247 248 249 250 251
			intval($result['account']['account_id']),
			intval($result['account']['account_id'])
		);
		if(! $r) {
			logger('create_account: failed to set parent');
		}
		$result['account']['parent'] = $result['account']['account_id'];
	}
252

friendica's avatar
friendica committed
253
	$result['success']  = true;
254 255
	$result['email']    = $email;
	$result['password'] = $password;
friendica's avatar
friendica committed
256

257 258
	call_hooks('register_account',$result);

259
	return $result;
friendica's avatar
friendica committed
260
}
friendica's avatar
friendica committed
261 262 263



264 265
function verify_email_address($arr) {

266 267 268 269
	if(array_key_exists('resend',$arr)) {
		$email = $arr['email'];
		$a = q("select * from account where account_email = '%s' limit 1",
			dbesc($arr['email'])
270
		);
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
		if(! ($a && ($a[0]['account_flags'] & ACCOUNT_UNVERIFIED))) {
			return false;
		}
		$account = $a[0];
		$v = q("select * from register where uid = %d and password = 'verify' limit 1",
			intval($account['account_id'])
		);
		if($v) {
			$hash = $v[0]['hash'];
		}
		else {
			return false;
		}
	}
	else {
		$hash = random_string(24);

		$r = q("INSERT INTO register ( hash, created, uid, password, lang ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
			dbesc($hash),
			dbesc(datetime_convert()),
			intval($arr['account']['account_id']),
			dbesc('verify'),
			dbesc($arr['account']['account_language'])
		);
		$account = $arr['account'];
	}
297

298
	push_lang(($account['account_language']) ? $account['account_language'] : 'en');
299

Zot's avatar
Zot committed
300 301 302 303 304
	$email_msg = replace_macros(get_intltext_template('register_verify_member.tpl'),
		[
			'$sitename' => get_config('system','sitename'),
			'$siteurl'  => z_root(),
			'$email'    => $arr['email'],
305
			'$uid'      => $account['account_id'],
Zot's avatar
Zot committed
306 307 308 309
			'$hash'     => $hash,
			'$details'  => $details
	 	]
	);
310

311 312 313 314 315 316
	$res = z_mail(
		[ 
		'toEmail' => $arr['email'], 
		'messageSubject' => sprintf( t('Registration confirmation for %s'), get_config('system','sitename')),
		'textVersion' => $email_msg,
		]
317 318
	);

Zot's avatar
Zot committed
319 320
	pop_lang();

321 322 323
	if($res)
		$delivered ++;
	else
Zot's avatar
Zot committed
324
		logger('send_reg_approval_email: failed to account_id: ' . $arr['account']['account_id']);
325

326
	return $res;
327 328 329 330 331
}




332 333
function send_reg_approval_email($arr) {

334 335 336
	$r = q("select * from account where (account_roles & %d) >= 4096",
		 intval(ACCOUNT_ROLE_ADMIN)
	);
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
	if(! ($r && count($r)))
		return false;

	$admins = array();

	foreach($r as $rr) {
		if(strlen($rr['account_email'])) {
			$admins[] = array('email' => $rr['account_email'], 'lang' => $rr['account_lang']);
		}
	}

	if(! count($admins))
		return false;

	$hash = random_string();

353
	$r = q("INSERT INTO register ( hash, created, uid, password, lang ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
354 355 356
		dbesc($hash),
		dbesc(datetime_convert()),
		intval($arr['account']['account_id']),
friendica's avatar
friendica committed
357
		dbesc(''),
358 359 360
		dbesc($arr['account']['account_language'])
	);

361 362 363 364
	$ip = $_SERVER['REMOTE_ADDR'];

	$details = (($ip) ? $ip . ' [' . gethostbyaddr($ip) . ']' : '[unknown or stealth IP]');

365 366 367 368 369 370 371 372
	$delivered = 0;

	foreach($admins as $admin) {
		if(strlen($admin['lang']))
			push_lang($admin['lang']);
		else
			push_lang('en');

373
		$email_msg = replace_macros(get_intltext_template('register_verify_eml.tpl'), array(
374
			'$sitename' => get_config('system','sitename'),
375 376 377
			'$siteurl'  =>  z_root(),
			'$email'    => $arr['email'],
			'$uid'      => $arr['account']['account_id'],
378 379
			'$hash'     => $hash,
			'$details'  => $details
380 381
		 ));

382 383 384 385 386 387
		$res = z_mail(
			[ 
			'toEmail' => $admin['email'], 
			'messageSubject' => sprintf( t('Registration request at %s'), get_config('system','sitename')),
			'textVersion' => $email_msg,
			]
388 389 390 391
		);

		if($res)
			$delivered ++;
392 393 394
		else
			logger('send_reg_approval_email: failed to ' . $admin['email'] . 'account_id: ' . $arr['account']['account_id']);

395 396 397 398 399 400
		pop_lang();
	}

	return($delivered ? true : false);
}

401
function send_register_success_email($email,$password) {
402 403

	$email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), array(
404
		'$sitename' => get_config('system','sitename'),
405 406
		'$siteurl' =>  z_root(),
		'$email'    => $email,
407
		'$password' => t('your registration password'),
408 409
	));

410 411
	$res = z_mail(
		[ 
Zot's avatar
Zot committed
412 413 414
			'toEmail' => $email,
			'messageSubject' => sprintf( t('Registration details for %s'), get_config('system','sitename')),
			'textVersion' => $email_msg,
415
		]
416
	);
417

418 419
	return($res ? true : false);
}
420

421 422 423 424 425 426
/**
 * @brief Allows a user registration.
 *
 * @param string $hash
 * @return array|boolean
 */
427
function account_allow($hash) {
428 429 430

	$ret = array('success' => false);

Zot's avatar
Zot committed
431
	$register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1",
432 433 434 435 436 437 438 439 440
		dbesc($hash)
	);

	if(! $register)
		return $ret;

	$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
		intval($register[0]['uid'])
	);
441

442 443 444
	if(! $account)
		return $ret;

445
	$r = q("DELETE FROM register WHERE hash = '%s'",
446 447 448
		dbesc($register[0]['hash'])
	);

449
	$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
450 451 452 453
		intval(ACCOUNT_BLOCKED),
		intval(ACCOUNT_BLOCKED),
		intval($register[0]['uid'])
	);
454
	$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
455 456 457 458
		intval(ACCOUNT_PENDING),
		intval(ACCOUNT_PENDING),
		intval($register[0]['uid'])
	);
459

460
	push_lang($register[0]['lang']);
461 462

	$email_tpl = get_intltext_template("register_open_eml.tpl");
463
	$email_msg = replace_macros($email_tpl, array(
464 465 466 467 468 469 470 471
			'$sitename' => get_config('system','sitename'),
			'$siteurl' =>  z_root(),
			'$username' => $account[0]['account_email'],
			'$email' => $account[0]['account_email'],
			'$password' => '',
			'$uid' => $account[0]['account_id']
	));

472 473 474 475 476 477 478
	$res = z_mail(
		[ 
		'toEmail' => $account[0]['account_email'],
		'messageSubject' => sprintf( t('Registration details for %s'), get_config('system','sitename')),
		'textVersion' => $email_msg,
		]
	);
479 480 481

	pop_lang();

Zot's avatar
Zot committed
482
	if(get_config('system','auto_channel_create'))
483 484
		auto_channel_create($register[0]['uid']);

485
	if ($res) {
486 487
		info( t('Account approved.') . EOL );
		return true;
488
	}
489 490 491
}


492
/**
493
 * @brief Denies an account registration.
494 495 496 497 498 499 500 501
 *
 * 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
 */
502 503

function account_deny($hash) {
504 505 506 507 508 509 510 511

	$register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1",
		dbesc($hash)
	);

	if(! count($register))
		return false;

friendica's avatar
friendica committed
512
	$account = q("SELECT account_id, account_email FROM account WHERE account_id = %d LIMIT 1",
513 514
		intval($register[0]['uid'])
	);
515

516
	if(! $account)
517 518
		return false;

519
	$r = q("DELETE FROM account WHERE account_id = %d",
520 521 522
		intval($register[0]['uid'])
	);

Zot's avatar
Zot committed
523
	$r = q("DELETE FROM register WHERE id = %d",
524 525 526
		dbesc($register[0]['id'])
	);
	notice( sprintf(t('Registration revoked for %s'), $account[0]['account_email']) . EOL);
527

528
	return true;
529

530
}
531

532
// called from regver to activate an account from the email verification link
533

534
function account_approve($hash) {
535

Zot's avatar
Zot committed
536
	$ret = false;
537

538 539
	// Note: when the password in the register table is 'verify', the uid actually contains the account_id

Zot's avatar
Zot committed
540
	$register = q("SELECT * FROM register WHERE hash = '%s' and password = 'verify' LIMIT 1",
541 542 543 544 545 546 547 548 549
		dbesc($hash)
	);

	if(! $register)
		return $ret;

	$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
		intval($register[0]['uid'])
	);
550

551 552 553
	if(! $account)
		return $ret;

554
	$r = q("DELETE FROM register WHERE hash = '%s' and password = 'verify'",
555 556 557
		dbesc($register[0]['hash'])
	);

558
	$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
559 560 561 562
		intval(ACCOUNT_BLOCKED),
		intval(ACCOUNT_BLOCKED),
		intval($register[0]['uid'])
	);
563
	$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
564 565 566 567
		intval(ACCOUNT_PENDING),
		intval(ACCOUNT_PENDING),
		intval($register[0]['uid'])
	);
568
	$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
569 570 571 572
		intval(ACCOUNT_UNVERIFIED),
		intval(ACCOUNT_UNVERIFIED),
		intval($register[0]['uid'])
	);
573

574 575 576 577 578 579 580 581 582
	// get a fresh copy after we've modified it.

	$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
		intval($register[0]['uid'])
	);

	if(! $account)
		return $ret;

Zot's avatar
Zot committed
583
	if(get_config('system','auto_channel_create'))
584
		auto_channel_create($register[0]['uid']);
585 586
	else {
		$_SESSION['login_return_url'] = 'new_channel';
587
		authenticate_success($account[0],null,true,true,false,true);
588 589
	}	

590 591 592 593
	return true;
}


594
/**
595 596
 * @brief Checks for accounts that have past their expiration date.
 *
597 598 599 600 601 602 603 604 605 606 607
 * 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.
 * called from include/poller.php as a scheduled task.
 *
 * Reclaiming resources which are no longer within the service class limits is
 * 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() {

Zot's avatar
Zot committed
608 609
	$r = q("select * from account where not ( account_flags & %d ) > 0 
		and account_expires > '%s' 
610
		and account_expires < %s ",
611
		intval(ACCOUNT_EXPIRED),
612 613
		dbesc(NULL_DATE),
		db_getfunc('UTC_TIMESTAMP')
614 615 616 617 618 619 620 621 622 623
	);

	if(! $r)
		return;

	$basic = get_config('system','default_service_class');

	foreach($r as $rr) {
		if(($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) {
			$x = q("UPDATE account set account_service_class = '%s', account_expires = '%s'
624
				where account_id = %d",
625
				dbesc($basic),
626
				dbesc(NULL_DATE),
627 628
				intval($rr['account_id'])
			);
629 630
			$ret = array('account' => $rr);
			call_hooks('account_downgrade', $ret );
631 632 633
			logger('downgrade_accounts: Account id ' . $rr['account_id'] . ' downgraded.');
		}
		else {
634
			$x = q("UPDATE account SET account_flags = (account_flags | %d) where account_id = %d",
635 636 637
				intval(ACCOUNT_EXPIRED),
				intval($rr['account_id'])
			);
638 639
			$ret = array('account' => $rr);
			call_hooks('account_downgrade', $ret);
640 641 642
			logger('downgrade_accounts: Account id ' . $rr['account_id'] . ' expired.');
		}
	}
643 644
}

645

646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
/**
 * @brief Check service_class restrictions.
 *
 * If there are no service_classes defined, everything is allowed.
 * If $usage is supplied, we check against a maximum count and return true if
 * the current usage is less than the subscriber plan allows. Otherwise we
 * return boolean true or false if the property is allowed (or not) in this
 * subscriber plan. An unset property for this service plan means the property
 * is allowed, so it is only necessary to provide negative properties for each
 * plan, or what the subscriber is not allowed to do.
 *
 * Like account_service_class_allows() but queries directly by account rather
 * than channel. Service classes are set for accounts, so we look up the
 * account for the channel and fetch the service class restrictions of the
 * account.
 *
 * @see account_service_class_allows() if you have a channel_id already
 * @see service_class_fetch()
 *
 * @param int $uid The channel_id to check
 * @param string $property The service class property to check for
 * @param string|boolean $usage (optional) The value to check against
 * @return boolean
 */
670
function service_class_allows($uid, $property, $usage = false) {
671
	$limit = service_class_fetch($uid, $property);
672

673 674
	if($limit === false)
		return true; // No service class set => everything is allowed
675

676
	$limit = engr_units_to_bytes($limit);
677 678 679 680 681
	if($usage === false) {
		// We use negative values for not allowed properties in a subscriber plan
		return ((x($limit)) ? (bool) $limit : true);
	} else {
		return (((intval($usage)) < intval($limit)) ? true : false);
682 683 684
	}
}

685
/**
686
 * @brief Check service class restrictions by account.
687
 *
688 689 690 691 692 693 694
 * If there are no service_classes defined, everything is allowed.
 * If $usage is supplied, we check against a maximum count and return true if
 * the current usage is less than the subscriber plan allows. Otherwise we
 * return boolean true or false if the property is allowed (or not) in this
 * subscriber plan. An unset property for this service plan means the property
 * is allowed, so it is only necessary to provide negative properties for each
 * plan, or what the subscriber is not allowed to do.
695
 *
696
 * Like service_class_allows() but queries directly by account rather than channel.
697
 *
698 699
 * @see service_class_allows() if you have a channel_id instead of an account_id
 * @see account_service_class_fetch()
700
 *
701 702
 * @param int $aid The account_id to check
 * @param string $property The service class property to check for
703
 * @param int|boolean $usage (optional) The value to check against
704
 * @return boolean
705 706
 */
function account_service_class_allows($aid, $property, $usage = false) {
707

708
	$limit = account_service_class_fetch($aid, $property);
709

710 711
	if($limit === false)
		return true; // No service class is set => everything is allowed
712

713 714
	$limit = engr_units_to_bytes($limit);

715 716 717 718 719
	if($usage === false) {
		// We use negative values for not allowed properties in a subscriber plan
		return ((x($limit)) ? (bool) $limit : true);
	} else {
		return (((intval($usage)) < intval($limit)) ? true : false);
720 721 722
	}
}

723
/**
724 725 726 727
 * @brief Queries a service class value for a channel and property.
 *
 * Service classes are set for accounts, so look up the account for this channel
 * and fetch the service classe of the account.
728 729 730 731
 *
 * If no service class is available it returns false and everything should be
 * allowed.
 *
732 733 734 735
 * @see account_service_class_fetch()
 *
 * @param int $uid The channel_id to query
 * @param string $property The service property name to check for
736
 * @return boolean|int
737 738
 *
 * @todo Should we merge this with account_service_class_fetch()?
739 740
 */
function service_class_fetch($uid, $property) {
redmatrix's avatar
redmatrix committed
741 742


friendica's avatar
friendica committed
743
	if($uid == local_channel()) {
redmatrix's avatar
redmatrix committed
744
		$service_class = App::$account['account_service_class'];
745 746 747 748 749 750 751 752 753 754 755 756 757 758
	}
	else {
		$r = q("select account_service_class as service_class 
				from channel c, account a 
				where c.channel_account_id=a.account_id and c.channel_id= %d limit 1",
				intval($uid)
		);
		if($r !== false and count($r)) {
			$service_class = $r[0]['service_class'];
		}
	}
	if(! x($service_class))
		return false; // everything is allowed

759
	$arr = get_config('service_class', $service_class);
760 761 762 763

	if(! is_array($arr) || (! count($arr)))
		return false;

764
	return((array_key_exists($property, $arr)) ? $arr[$property] : false);
765 766
}

767 768 769 770 771 772 773 774 775 776 777 778
/**
 * @brief Queries a service class value for an account and property.
 *
 * Like service_class_fetch() but queries by account rather than channel.
 *
 * @see service_class_fetch() if you have channel_id.
 * @see account_service_class_allows()
 *
 * @param int $aid The account_id to query
 * @param string $property The service property name to check for
 * @return boolean|int
 */
779
function account_service_class_fetch($aid, $property) {
780 781 782 783 784 785 786 787 788 789 790

	$r = q("select account_service_class as service_class from account where account_id = %d limit 1",
		intval($aid)
	);
	if($r !== false && count($r)) {
		$service_class = $r[0]['service_class'];
	}

	if(! x($service_class))
		return false; // everything is allowed

791
	$arr = get_config('service_class', $service_class);
792 793 794 795

	if(! is_array($arr) || (! count($arr)))
		return false;

796
	return((array_key_exists($property, $arr)) ? $arr[$property] : false);
797 798 799
}


800
function upgrade_link($bbcode = false) {
801
	$l = get_config('service_class', 'upgrade_link');
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
	if(! $l)
		return '';
	if($bbcode)
		$t = sprintf('[zrl=%s]' . t('Click here to upgrade.') . '[/zrl]', $l);
	else
		$t = sprintf('<a href="%s">' . t('Click here to upgrade.') . '</div>', $l);
	return $t;
}

function upgrade_message($bbcode = false) {
	$x = upgrade_link($bbcode);
	return t('This action exceeds the limits set by your subscription plan.') . (($x) ? ' ' . $x : '') ;
}

function upgrade_bool_message($bbcode = false) {
	$x = upgrade_link($bbcode);
	return t('This action is not available under your subscription plan.') . (($x) ? ' ' . $x : '') ;
jeroenpraat's avatar
jeroenpraat committed
819
}
820 821 822 823


function get_account_techlevel($account_id = 0) {

M. Dent's avatar
M. Dent committed
824
	return (5);
825

826
}