aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2021-05-11 11:59:49 +0000
committerMario <mario@mariovavti.com>2021-05-11 11:59:49 +0000
commit26e851ff7fc074592f93088dbd96713b22defe8b (patch)
treee727d9a83590b152ddd63a8c8e7756835c45de4a /include
parent406ca206347152cf4acbdcb81fc8152d83f99182 (diff)
parent89ec043ce1183dbae5ff10a994f0f819a8544ba9 (diff)
downloadvolse-hubzilla-26e851ff7fc074592f93088dbd96713b22defe8b.tar.gz
volse-hubzilla-26e851ff7fc074592f93088dbd96713b22defe8b.tar.bz2
volse-hubzilla-26e851ff7fc074592f93088dbd96713b22defe8b.zip
Merge branch '5.6RC'
Diffstat (limited to 'include')
-rw-r--r--include/account.php619
-rw-r--r--include/acl_selectors.php9
-rw-r--r--include/bbcode.php21
-rw-r--r--include/bookmarks.php2
-rw-r--r--include/channel.php2
-rw-r--r--include/conversation.php9
-rw-r--r--include/datetime.php36
-rw-r--r--include/event.php10
-rw-r--r--include/features.php73
-rw-r--r--include/feedutils.php22
-rw-r--r--include/html2plain.php47
-rw-r--r--include/hubloc.php50
-rw-r--r--include/import.php5
-rw-r--r--include/items.php143
-rw-r--r--include/js_strings.php7
-rw-r--r--include/menu.php2
-rw-r--r--include/network.php12
-rw-r--r--include/photo/photo_driver.php3
-rw-r--r--include/queue_fn.php2
-rw-r--r--include/security.php106
-rw-r--r--include/taxonomy.php10
-rw-r--r--include/text.php73
22 files changed, 1015 insertions, 248 deletions
diff --git a/include/account.php b/include/account.php
index fefe61d15..d138dab41 100644
--- a/include/account.php
+++ b/include/account.php
@@ -34,18 +34,29 @@ function check_account_email($email) {
if(! strlen($email))
return $result;
- if(! validate_email($email))
- $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');
+ if(! validate_email($email)) {
+ $result['message'] = t('The provided email address is not valid');
+ }
+ elseif(! allowed_email($email)) {
+ $result['message'] = t('The provided email domain is not among those allowed on this site');
+ }
else {
- $r = q("select account_email from account where account_email = '%s' limit 1",
+ $account = q("select account_email from account where account_email = '%s' limit 1",
dbesc($email)
);
- if($r) {
- $result['message'] .= t('Your email address is already registered at this site.');
+ if ($account) {
+ $result['message'] = t('The provided email address is already registered at this site');
+ }
+
+ $register = q("select reg_did2 from register where reg_vital = 1 and reg_did2 = '%s' limit 1",
+ dbesc($email)
+ );
+ if ($register) {
+ $result['message'] = t('There is a pending registration for this address - click "Register" to continue verification');
+ $result['email_unverified'] = true;
}
}
+
if($result['message'])
$result['error'] = true;
@@ -71,17 +82,30 @@ function check_account_password($password) {
function check_account_invite($invite_code) {
$result = array('error' => false, 'message' => '');
- $using_invites = get_config('system','invitation_only');
+ // [hilmar ->
+ $using_invites = (get_config('system','invitation_only')
+ || get_config('system','invitation_also'));
if($using_invites) {
+
if(! $invite_code) {
- $result['message'] .= t('An invitation is required.') . EOL;
- }
- $r = q("select * from register where hash = '%s' limit 1", dbesc($invite_code));
- if(! $r) {
- $result['message'] .= t('Invitation could not be verified.') . EOL;
+
+ $result['message']
+ .= 'ZAR0510E,' . t('An invitation is required.') . EOL;
+
+ } else {
+
+ // check if invite code exists
+ $r = q("SELECT * FROM register WHERE reg_hash = '%s' AND reg_vital = 1 LIMIT 1",
+ dbesc($invite_code));
+ if(! $r) {
+ $result['message']
+ .= 'ZAR0511E,' . t('Invitation could not be verified.') . EOL;
+ }
}
}
+ // <- hilmar]
+
if(strlen($result['message']))
$result['error'] = true;
@@ -107,8 +131,8 @@ function account_total() {
return false;
}
-
-function account_store_lowlevel($arr) {
+// legacy
+function account_store_lowlevel_IS_OBSOLETE($arr) {
$store = [
'account_parent' => ((array_key_exists('account_parent',$arr)) ? $arr['account_parent'] : '0'),
@@ -130,12 +154,21 @@ function account_store_lowlevel($arr) {
'account_password_changed' => ((array_key_exists('account_password_changed',$arr)) ? $arr['account_password_changed'] : '0001-01-01 00:00:00')
];
+ // never ever is this a create table but a pdo insert into account
+ // strange function placement in text.php (obscure by design :-)
return create_table_from_array('account',$store);
-
+ // the TODO may be to adjust others using create_table_from_array():
+ // channel.php
+ // connections.php
+ // event.php
+ // hubloc.php
+ // import.php
}
-function create_account($arr) {
+
+// legacy
+function create_account_IS_OBSOLETE($arr) {
// Required: { email, password }
@@ -259,10 +292,161 @@ function create_account($arr) {
return $result;
}
+/**
+ * create_account_from_register
+ * @author hilmar runge
+ * @since 2020-02-20
+ *
+ * Account creation only happens via table register.
+ * This function creates the account when all conditions are solved.
+ *
+ */
+function create_account_from_register($arr) {
+
+ $result = array('success' => false, 'message' => 'rid:' . $arr['reg_id']);
+ $now = datetime_convert();
+
+ // reg_flags 0x0020 = REGISTER_AGREED = register request verified by user @ regate
+ $register = q("SELECT * FROM register WHERE reg_id = %d AND (reg_flags & 31) = 0 "
+ . " AND reg_startup < '%s' AND reg_expires > '%s' ",
+ intval($arr['reg_id']),
+ dbesc($now),
+ dbesc($now)
+ );
+
+ if ( ! $register ) return $result;
+
+ // account
+ $expires = NULL_DATE;
+
+ $default_service_class = get_config('system','default_service_class');
+ if($default_service_class === false)
+ $default_service_class = '';
+
+ $roles = 0;
+ // prevent form hackery
+ if($roles & ACCOUNT_ROLE_ADMIN) {
+ $admin_result = check_account_admin($arr);
+ if(! $admin_result) {
+ $roles = 0;
+ }
+ }
+
+ // any accounts available ?
+ $isa = q("SELECT COUNT(*) AS isa FROM account");
+ if ($isa && $isa[0]['isa'] == 0) {
+ $roles = ACCOUNT_ROLE_ADMIN;
+ }
+
+ $password_parts = explode(',', $register[0]['reg_pass']);
+ $salt = $password_parts[0];
+ $password_encoded = $password_parts[1];
+
+ $ri = q(
+ "INSERT INTO account ("
+ . " account_parent, account_salt, account_password, account_email, "
+ . " account_language, account_created, account_flags, account_roles, account_level, "
+ . " account_expires, account_service_class) VALUES( "
+ . " %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', '%s' ) ",
+ intval($parent),
+ dbesc($salt),
+ dbesc($password_encoded),
+ dbesc($register[0]['reg_did2']),
+ dbesc($register[0]['reg_lang']),
+ dbesc($now),
+ intval($register[0]['reg_flags'] & 31), // off REGISTER_AGREE at ACCOUNT
+ intval($roles),
+ intval(5),
+ dbesc($expires),
+ dbesc($default_service_class)
+ );
+
+ if(! $ri) {
+ logger('create_account: DB INSERT failed.');
+ $result['message'] = 'ZAR ' . t('Failed to store account information.');
+ return($result);
+ }
+
+ $r = q("SELECT * FROM account WHERE account_email = '%s' AND account_password = '%s' LIMIT 1",
+ dbesc($register[0]['reg_did2']),
+ dbesc($password_encoded)
+ );
+ if($r && count($r)) {
+ $result['account'] = $r[0];
+ }
+ else {
+ logger('create_account: could not retrieve newly created account');
+ }
+
+ // Set the parent record to the current record_id if no parent was provided
+ if(! $parent) {
+ $r = q("UPDATE account SET account_parent = %d WHERE account_id = %d",
+ 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'];
+ }
+
+ $result['success'] = true;
+
+ //call_hooks('register_account',$result);
+
+ return $result;
+}
+
+/**
+ * @brief as far to see, email validation for register account verification
+ * @param array (account)
+ * @param array ('resend' => true, 'email' = > email)
+ *
+ */
function verify_email_address($arr) {
+ // $hash = random_string(24);
+
+ // [hilmar ->
+ $reg = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_email = 's%' ",
+ dbesc($arr['email'])
+ );
+ if ( ! $reg)
+ return false;
+
+ push_lang(($reg[0]['email']) ? $reg[0]['email'] : 'en');
+
+ $email_msg = replace_macros(get_intltext_template('register_verify_member.tpl'),
+ [
+ '$sitename' => get_config('system','sitename'),
+ '$siteurl' => z_root(),
+ '$email' => $arr['email'],
+ '$uid' => 1,
+ '$hash' => $hash,
+ '$details' => ''
+ ]
+ );
+
+ $res = z_mail(
+ [
+ 'toEmail' => $arr['email'],
+ 'messageSubject' => sprintf( t('Registration confirmation for %s'), get_config('system','sitename')),
+ 'textVersion' => $email_msg,
+ ]
+ );
+
+ pop_lang();
+
+ if(! $res)
+ logger('send_reg_approval_email: failed to account_id: ' . $arr['account']['account_id']);
+
+ return $res;
+}
+
+function verify_email_addressNOP($arr) {
+
if(array_key_exists('resend',$arr)) {
$a = q("select * from account where account_email = '%s' limit 1",
dbesc($arr['email'])
@@ -271,11 +455,14 @@ function verify_email_address($arr) {
return false;
}
$account = $a[0];
- $v = q("select * from register where uid = %d and password = 'verify' limit 1",
+ // [hilmar ->
+ $v = q("SELECT * FROM register WHERE reg_uid = %d AND reg_vital = 1 "
+ . " AND reg_pass = 'verify' LIMIT 1",
intval($account['account_id'])
);
+ // <- hilmar]
if($v) {
- $hash = $v[0]['hash'];
+ $hash = $v[0]['reg_hash'];
}
else {
return false;
@@ -284,13 +471,16 @@ function verify_email_address($arr) {
else {
$hash = random_string(24);
- q("INSERT INTO register ( hash, created, uid, password, lang ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
+ // [hilmar ->
+ q("INSERT INTO register ( reg_hash, reg_created, reg_uid, reg_pass, reg_lang, reg_stuff ) "
+ ." VALUES ( '%s', '%s', %d, '%s', '%s', '' ) ",
dbesc($hash),
dbesc(datetime_convert()),
intval($arr['account']['account_id']),
dbesc('verify'),
dbesc($arr['account']['account_language'])
);
+ // <- hilmar]
$account = $arr['account'];
}
@@ -347,11 +537,17 @@ function send_reg_approval_email($arr) {
$hash = random_string();
- $r = q("INSERT INTO register ( hash, created, uid, password, lang ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
+ // [hilmar ->
+ // code before fetches the $admins as recipients for the approval request mail
+ // $arr has a user (self registered) account
+ // ... $arr['email'] ???
+ // ... reg expiration ?
+ $r = q("INSERT INTO register ( reg_hash, reg_email, reg_created, reg_uid, reg_pass, reg_lang, reg_stuff )"
+ . " VALUES ( '%s', '%s', '%s', %d, '', '%s', '' ) ",
dbesc($hash),
+ dbesc($arr['account']['account_email']),
dbesc(datetime_convert()),
intval($arr['account']['account_id']),
- dbesc(''),
dbesc($arr['account']['account_language'])
);
@@ -425,7 +621,7 @@ function account_allow($hash) {
$ret = array('success' => false);
- $register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1",
+ $register = q("SELECT * FROM register WHERE reg_hash = '%s' LIMIT 1",
dbesc($hash)
);
@@ -433,57 +629,89 @@ function account_allow($hash) {
return $ret;
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
+ // a register entry without account assigned to
if(! $account)
return $ret;
- q("DELETE FROM register WHERE hash = '%s'",
- dbesc($register[0]['hash'])
+ // [hilmar ->
+
+ q("START TRANSACTION");
+ //q("DELETE FROM register WHERE reg_hash = '%s'",
+ // dbesc($register[0]['reg_hash'])
+ //);
+ $r1 = q("UPDATE register SET reg_vital = 0 WHERE reg_hash = '%s'",
+ dbesc($register[0]['reg_hash'])
);
- q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
+ /* instead of ...
+
+ // unblock
+ q("UPDATE account SET account_flags = (account_flags & ~%d) "
+ . " WHERE (account_flags & %d)>0 AND account_id = %d",
intval(ACCOUNT_BLOCKED),
intval(ACCOUNT_BLOCKED),
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
- q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
+ // unpend
+ q("UPDATE account SET account_flags = (account_flags & ~%d) "
+ . " WHERE (account_flags & %d)>0 AND account_id = %d",
intval(ACCOUNT_PENDING),
intval(ACCOUNT_PENDING),
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
- push_lang($register[0]['lang']);
+ */
+ // together unblock and unpend
+ $r2 = q("UPDATE account SET account_flags = %d WHERE account_id = %d",
+ intval($account['account_flags']
+ &= $account['account_flags'] ^ (ACCOUNT_BLOCKED | ACCOUNT_PENDING)),
+ intval($register[0]['reg_uid'])
+ );
- $email_tpl = get_intltext_template("register_open_eml.tpl");
- $email_msg = replace_macros($email_tpl, array(
- '$sitename' => get_config('system','sitename'),
- '$siteurl' => z_root(),
- '$username' => $account[0]['account_email'],
- '$email' => $account[0]['account_email'],
- '$password' => '',
- '$uid' => $account[0]['account_id']
- ));
+ if($r1 && $r2) {
+ q("COMMIT");
- $res = z_mail(
- [
- 'toEmail' => $account[0]['account_email'],
- 'messageSubject' => sprintf( t('Registration details for %s'), get_config('system','sitename')),
- 'textVersion' => $email_msg,
- ]
- );
+ // <- hilmar]
- pop_lang();
+ push_lang($register[0]['reg_lang']);
- if(get_config('system','auto_channel_create'))
- auto_channel_create($register[0]['uid']);
+ $email_tpl = get_intltext_template("register_open_eml.tpl");
+ $email_msg = replace_macros($email_tpl, array(
+ '$sitename' => get_config('system','sitename'),
+ '$siteurl' => z_root(),
+ '$username' => $account[0]['account_email'],
+ '$email' => $account[0]['account_email'],
+ '$password' => '',
+ '$uid' => $account[0]['account_id']
+ ));
- if ($res) {
- info( t('Account approved.') . EOL );
- return true;
+ $res = z_mail(
+ [
+ 'toEmail' => $account[0]['account_email'],
+ 'messageSubject' => sprintf( t('Registration details for %s'), get_config('system','sitename')),
+ 'textVersion' => $email_msg,
+ ]
+ );
+
+ pop_lang();
+
+ if(get_config('system', 'auto_channel_create', 1))
+ auto_channel_create($register[0]['uid']);
+
+ if ($res) {
+ info( t('Account approved.') . EOL );
+ return true;
+ }
+
+ // [hilmar ->
+ } else {
+ q("ROLLBACK");
}
+ // <- hilmar]
}
@@ -500,42 +728,65 @@ function account_allow($hash) {
function account_deny($hash) {
- $register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1",
+ // [hilmar->
+ $register = q("SELECT * FROM register WHERE reg_hash = '%s' AND reg_vital = 1 LIMIT 1",
dbesc($hash)
);
+ // <-hilmar]
if(! count($register))
return false;
$account = q("SELECT account_id, account_email FROM account WHERE account_id = %d LIMIT 1",
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
if(! $account)
return false;
- q("DELETE FROM account WHERE account_id = %d",
- intval($register[0]['uid'])
- );
+ // [hilmar ->
+ q("START TRANSACTION");
- q("DELETE FROM register WHERE id = %d",
- dbesc($register[0]['id'])
+ $r1 = q("DELETE FROM account WHERE account_id = %d",
+ intval($register[0]['reg_uid'])
+ );
+ // q("DELETE FROM register WHERE reg_id = %d",
+ // dbesc($register[0]['reg_id'])
+ //);
+ $r2 = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND reg_vital = 1",
+ dbesc($register[0]['reg_id'])
);
- notice( sprintf(t('Registration revoked for %s'), $account[0]['account_email']) . EOL);
- return true;
+ if($r1 && $r2) {
+ q("COMMIT");
+ notice( 'ZAR0512I,' . sprintf( t('Registration revoked for %s'),
+ $account[0]['account_email']) . EOL);
+ return true;
-}
+ } else {
-// called from regver to activate an account from the email verification link
+ q("ROLLBACK");
+ notice( 'ZAR0513F,' . sprintf( t('Could not revoke registration for %s'),
+ $account[0]['account_email']) . EOL);
+ return false;
+ }
+ // <- hilmar]
+}
+/**
+ * called from Regver to allow/revoke an account
+ * Use case is under REGISTER_OPEN with APPROVAL
+ * Ref Regver, Email_validation, Email_resend
+ * ZAR052+
+ */
function account_approve($hash) {
$ret = false;
// Note: when the password in the register table is 'verify', the uid actually contains the account_id
+ // hmm
- $register = q("SELECT * FROM register WHERE hash = '%s' and password = 'verify' LIMIT 1",
+ $register = q("SELECT * FROM register WHERE reg_hash = '%s' and reg_pass = 'verify' LIMIT 1",
dbesc($hash)
);
@@ -543,45 +794,58 @@ function account_approve($hash) {
return $ret;
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
if(! $account)
return $ret;
- q("DELETE FROM register WHERE hash = '%s' and password = 'verify'",
- dbesc($register[0]['hash'])
+ // tr ?
+
+ q("DELETE FROM register WHERE reg_hash = '%s' and reg_pass = 'verify'",
+ dbesc($register[0]['reg_hash'])
);
q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
intval(ACCOUNT_BLOCKED),
intval(ACCOUNT_BLOCKED),
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
intval(ACCOUNT_PENDING),
intval(ACCOUNT_PENDING),
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
intval(ACCOUNT_UNVERIFIED),
intval(ACCOUNT_UNVERIFIED),
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
+ );
+
+ /*
+ // together unblock unpend and verified
+ q("UPDATE account SET account_flags = %d WHERE account_id = %d",
+ intval($account['account_flags']
+ &= $account['account_flags']
+ ^ (ACCOUNT_BLOCKED | ACCOUNT_PENDING | ACCOUNT_UNVERIFIED)),
+ intval($register[0]['reg_uid'])
);
+ */
+
// get a fresh copy after we've modified it.
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
- intval($register[0]['uid'])
+ intval($register[0]['reg_uid'])
);
if(! $account)
return $ret;
if(get_config('system','auto_channel_create'))
- auto_channel_create($register[0]['uid']);
+ auto_channel_create($register[0]['reg_uid']);
else {
$_SESSION['login_return_url'] = 'new_channel';
authenticate_success($account[0],null,true,true,false,true);
@@ -591,6 +855,118 @@ function account_approve($hash) {
}
+function verify_register_scheme() {
+
+ $dbc = db_columns('register');
+ if ($dbc) {
+
+ if ($dbc[0]=='id') {
+ // v1 format
+ dbq("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = dbq("ALTER TABLE register RENAME TO register100;");
+
+ $r2 = dbq("CREATE TABLE register ("
+ . "reg_id serial NOT NULL,"
+ . "reg_vital int DEFAULT 1 NOT NULL,"
+ . "reg_flags bigint DEFAULT 0 NOT NULL,"
+ . "reg_didx char(1) DEFAULT '' NOT NULL,"
+ . "reg_did2 text DEFAULT '' NOT NULL,"
+ . "reg_hash text DEFAULT '' NOT NULL,"
+ . "reg_email text DEFAULT '' NOT NULL,"
+ . "reg_created timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',"
+ . "reg_startup timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',"
+ . "reg_expires timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',"
+ . "reg_byc bigint DEFAULT 0 NOT NULL,"
+ . "reg_uid bigint DEFAULT 0 NOT NULL,"
+ . "reg_atip text DEFAULT '' NOT NULL,"
+ . "reg_pass text DEFAULT '' NOT NULL,"
+ . "reg_lang varchar(16) DEFAULT '' NOT NULL,"
+ . "reg_stuff text NOT NULL,"
+ . "PRIMARY KEY (reg_id) );"
+ );
+ $r0 = dbq("CREATE INDEX ix_reg_vital ON register (reg_vital);");
+ $r0 = dbq("CREATE INDEX ix_reg_flags ON register (reg_flags);");
+ $r0 = dbq("CREATE INDEX ix_reg_didx ON register (reg_didx);");
+ $r0 = dbq("CREATE INDEX ix_reg_did2 ON register (reg_did2);");
+ $r0 = dbq("CREATE INDEX ix_reg_hash ON register (reg_hash);");
+ $r0 = dbq("CREATE INDEX ix_reg_email ON register (reg_email);");
+ $r0 = dbq("CREATE INDEX ix_reg_created ON register (reg_created);");
+ $r0 = dbq("CREATE INDEX ix_reg_startup ON register (reg_startup);");
+ $r0 = dbq("CREATE INDEX ix_reg_expires ON register (reg_expires);");
+ $r0 = dbq("CREATE INDEX ix_reg_byc ON register (reg_byc);");
+ $r0 = dbq("CREATE INDEX ix_reg_uid ON register (reg_uid);");
+ $r0 = dbq("CREATE INDEX ix_reg_atip ON register (reg_atip);");
+
+ $r3 = dbq("INSERT INTO register (reg_id, reg_hash, reg_created, reg_uid, reg_pass, reg_lang, reg_stuff) "
+ . "SELECT id, hash, created, uid, password, lang, '' FROM register100;");
+
+ $r4 = dbq("DROP TABLE register100");
+
+ }
+ else {
+ $r1 = dbq("RENAME TABLE register TO register100;");
+
+ $r2 = dbq("CREATE TABLE IF NOT EXISTS register ("
+ . "reg_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,"
+ . "reg_vital int(10) UNSIGNED NOT NULL DEFAULT 1,"
+ . "reg_flags int(10) UNSIGNED NOT NULL DEFAULT 0,"
+ . "reg_didx char(1) NOT NULL DEFAULT '',"
+ . "reg_did2 char(191) NOT NULL DEFAULT '',"
+ . "reg_hash char(191) NOT NULL DEFAULT '',"
+ . "reg_email char(191) NOT NULL DEFAULT '',"
+ . "reg_created datetime NOT NULL DEFAULT '0001-01-01 00:00:00',"
+ . "reg_startup datetime NOT NULL DEFAULT '0001-01-01 00:00:00',"
+ . "reg_expires datetime NOT NULL DEFAULT '0001-01-01 00:00:00',"
+ . "reg_byc int(10) UNSIGNED NOT NULL DEFAULT 0 ,"
+ . "reg_uid int(10) UNSIGNED NOT NULL DEFAULT 0 ,"
+ . "reg_atip char(191) NOT NULL DEFAULT '',"
+ . "reg_pass char(191) NOT NULL DEFAULT '',"
+ . "reg_lang char(16) NOT NULL DEFAULT '',"
+ . "reg_stuff text NOT NULL,"
+ . "PRIMARY KEY (reg_id),"
+ . "KEY ix_reg_hash (reg_hash),"
+ . "KEY ix_reg_vital (reg_vital),"
+ . "KEY ix_reg_flags (reg_flags),"
+ . "KEY ix_reg_didx (reg_didx),"
+ . "KEY ix_reg_did2 (reg_did2),"
+ . "KEY ix_reg_email (reg_email),"
+ . "KEY ix_reg_created (reg_created),"
+ . "KEY ix_reg_startup (reg_startup),"
+ . "KEY ix_reg_expires (reg_expires),"
+ . "KEY ix_reg_byc (reg_byc),"
+ . "KEY ix_reg_uid (reg_uid),"
+ . "KEY ix_reg_atip (reg_atip)"
+ . ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
+ );
+
+ $r3 = dbq("INSERT INTO register (reg_id, reg_hash, reg_created, reg_uid, reg_pass, reg_lang, reg_stuff) "
+ . "SELECT id, hash, created, uid, password, lang, '' FROM register100;");
+
+ $r4 = dbq("DROP TABLE register100");
+ }
+
+ // $r = ($r1 && $r2 && $r3 && $r4);
+ // the only important
+ $r = $r2;
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ dbq("ROLLBACK");
+ return UPDATE_FAILED;
+ }
+ elseif ( count($dbc) != 16 ) {
+ // ffu
+ // fields in v2.0.0 = 16
+ }
+ }
+}
+
+
/**
* @brief Checks for accounts that have past their expiration date.
*
@@ -828,3 +1204,100 @@ function get_account_techlevel($account_id = 0) {
return (5);
}
+
+function zar_log($msg='') {
+
+ if(get_config('system', 'register_logfile', 0)) {
+ file_put_contents('./zar.log',
+ date('Y-m-d_H:i:s') . ' ' . $msg . ', ip: § ' . $_SERVER['REMOTE_ADDR'] . ' §' . "\n", FILE_APPEND);
+ }
+ else {
+ logger('zar_log: ' . $msg . ', ip: § ' . $_SERVER['REMOTE_ADDR'] . ' §');
+ }
+
+ return;
+}
+
+function zar_reg_mail($reonar=false) {
+ if ($reonar) {
+ $zem = z_mail(
+ [
+ 'toEmail' => $reonar['to'],
+ 'fromName' => ' ',
+ 'fromEmail' => $reonar['from'],
+ 'messageSubject' => $reonar['subject'],
+ 'textVersion' => $reonar['txttemplate'],
+ ]
+ );
+ return $zem;
+ }
+}
+
+/**
+ * ckeck current day and time against register duties
+ *
+ * @author Hilmar Runge
+ * @since 2020-02-25
+ * @param the current date and time is taken as default
+ * @return ['isduty'] true/false
+ * ['nowfmt'] the textmsg about the current state
+ * ['atform'] the disabled html attribute for form input fields
+ *
+ */
+function zar_register_dutystate( $now=NULL, $day=NULL ) {
+
+ is_null($now) ? $now = date('Hi') : '';
+ is_null($day) ? $day = date('N') : '';
+
+ $isduty = zarIsDuty($day, $now, 'isOpen');
+
+ if ( $isduty === false ) {
+ return array( 'isduty' => $isduty, 'nowfmt' => '', 'atform' => '' );
+ }
+
+ $dutyis = $isduty ? t('open') : t('closed');
+ $atform = $isduty ? '' : 'disabled';
+ $utc_now = datetime_convert(date_default_timezone_get(), 'UTC', $now, 'c');
+
+ $nowfmt = '';
+
+ if (!$isduty) {
+ $nowfmt = t('Registration is currently');
+ $nowfmt .= ' (<span data-utc="' . $utc_now . '" class="register_date">' . $utc_now . '</span>) ';
+ $nowfmt .= $dutyis . ',<br>';
+
+ $pernext = zarIsDuty($day, $now, 'nextOpen');
+ $week_days = ['','monday','tuesday','wednesday','thursday','friday','saturday','sunday'];
+ $utc_next_open = datetime_convert(date_default_timezone_get(), 'UTC', $week_days[$pernext[0]] . ' ' . $pernext[1], 'c');
+
+ if (is_array($pernext)) {
+ $nowfmt .= t('please come back');
+ $nowfmt .= ' <span data-utc="' . $utc_next_open . '" class="register_date">' . $utc_next_open . '</span>.';
+ }
+ }
+ return array( 'isduty' => $isduty, 'nowfmt' => $nowfmt, 'atform' => $atform);
+
+}
+
+function get_pending_accounts($get_all = false) {
+
+ $sql_extra = " AND (reg_flags & " . ACCOUNT_UNVERIFIED . ") = 0 ";
+
+ if($get_all)
+ $sql_extra = '';
+
+ $r = q("SELECT reg_did2, reg_created, reg_startup, reg_expires, reg_email, reg_atip, reg_hash, reg_id, reg_flags, reg_stuff
+ FROM register WHERE reg_vital = 1 $sql_extra AND (reg_flags & %d) >= 0",
+ intval(ACCOUNT_PENDING)
+ );
+
+ return $r;
+}
+
+function remove_expired_registrations() {
+ q("DELETE FROM register WHERE (reg_expires < '%s' OR reg_expires = '%s') AND (reg_flags & %d) > 0",
+ dbesc(datetime_convert()),
+ dbesc(NULL_DATE),
+ dbesc(ACCOUNT_UNVERIFIED)
+ );
+}
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index 8da46649c..f158a439b 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -63,6 +63,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
$single_group = false;
$just_me = false;
$custom = false;
+ $groups = '';
if($allow_cid || $allow_gid || $deny_gid || $deny_cid) {
$has_acl = true;
@@ -112,11 +113,11 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
$forums_count = 0;
$forum_otions = '';
foreach($forums as $f) {
- if($f['no_post_perms'])
+ if(isset($f['no_post_perms']))
continue;
- $private = (($f['private_forum']) ? ' (' . t('Private Forum') . ')' : '');
- $selected = (($single_group && $f['hash'] === $allow_cid[0]) ? ' selected = "selected" ' : '');
+ $private = ((isset($f['private_forum'])) ? ' (' . t('Private Forum') . ')' : '');
+ $selected = (($single_group && isset($f['hash'], $allow_cid[0]) && $f['hash'] === $allow_cid[0]) ? ' selected = "selected" ' : '');
$forum_otions .= '<option id="^' . $f['abook_id'] . '" value="^' . $f['xchan_hash'] . '"' . $selected . '>' . $f['xchan_name'] . $private . '</option>' . "\r\n";
$forums_count++;
}
@@ -133,7 +134,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
$o = replace_macros($tpl, array(
'$showall' => $showall_caption,
'$onlyme' => t('Only me'),
- '$groups' => $groups,
+ '$groups' => $groups,
'$public_selected' => (($has_acl) ? false : true),
'$justme_selected' => $just_me,
'$custom_selected' => $custom,
diff --git a/include/bbcode.php b/include/bbcode.php
index 388a828c4..228af7faa 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -1113,6 +1113,13 @@ function bbcode($Text, $options = []) {
$Text = preg_replace_callback("/\[summary\](.*?)\[\/summary\]/ism", 'bb_spacefy',$Text);
}
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace_callback('/\[img(.*?)\[\/(img)\]/ism','\red_escape_codeblock',$Text);
+ }
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace_callback('/\[zmg(.*?)\[\/(zmg)\]/ism','\red_escape_codeblock',$Text);
+ }
+
$Text = bb_format_attachdata($Text);
// If we find any event code, turn it into an event.
@@ -1236,6 +1243,8 @@ function bbcode($Text, $options = []) {
if($tryoembed) {
$Text = preg_replace_callback("/([^\]\='".'"'."\;\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", 'tryoembed', $Text);
}
+ // Is this still desired?
+ // We already turn naked URLs into links during creation time cleanup_bbcode()
$Text = preg_replace("/([^\]\='".'"'."\;\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", '$1<a href="$2" ' . $target . ' rel="nofollow noopener">$2</a>', $Text);
}
@@ -1498,9 +1507,21 @@ function bbcode($Text, $options = []) {
"<span class=".'"bb-quote"'.">" . $t_wrote . "</span><blockquote>$2</blockquote>",
$Text);
+
// Images
+
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace_callback('/\[\$b64img(.*?)\[\/(img)\]/ism','\red_unescape_codeblock',$Text);
+ }
+
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace_callback('/\[\$b64zmg(.*?)\[\/(zmg)\]/ism','\red_unescape_codeblock',$Text);
+ }
+
+
// [img]pathtoimage[/img]
if (strpos($Text,'[/img]') !== false) {
+
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img style="max-width: 100%;" src="$1" alt="' . t('Image/photo') . '" loading="eager" />', $Text);
}
// [img=pathtoimage]image description[/img]
diff --git a/include/bookmarks.php b/include/bookmarks.php
index 145119347..207cf5a33 100644
--- a/include/bookmarks.php
+++ b/include/bookmarks.php
@@ -73,6 +73,6 @@ function get_bookmark_link($observer) {
$h = @parse_url($observer['xchan_url']);
if($h)
- return $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '') . '/rbmark?f=';
+ return $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '') . '/rbmark?f=';
return '';
}
diff --git a/include/channel.php b/include/channel.php
index 31c7c407f..bc9f686e7 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -2593,7 +2593,7 @@ function channelx_by_n($id) {
}
$r = q("SELECT * FROM channel LEFT JOIN xchan ON channel_hash = xchan_hash WHERE channel_id = %d AND channel_removed = 0 LIMIT 1",
- dbesc($id)
+ intval($id)
);
return(($r) ? $r[0] : false);
diff --git a/include/conversation.php b/include/conversation.php
index ae69b7a01..04aa1ef5a 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -865,7 +865,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
$x = [ 'mode' => $mode, 'item' => $item ];
call_hooks('stream_item',$x);
- if($x['item']['blocked'])
+ if(isset($x['item']['blocked']))
continue;
$item = $x['item'];
@@ -1313,6 +1313,7 @@ function hz_status_editor($a, $x, $popup = false) {
if($c && $c['channel_moved'])
return $o;
+ $webpage = ((x($x,'webpage')) ? $x['webpage'] : '');
$plaintext = true;
$feature_nocomment = feature_enabled($x['profile_uid'], 'disable_comments');
@@ -1366,8 +1367,6 @@ function hz_status_editor($a, $x, $popup = false) {
else
$id_select = '';
- $webpage = ((x($x,'webpage')) ? $x['webpage'] : '');
-
$reset = ((x($x,'reset')) ? $x['reset'] : '');
$feature_auto_save_draft = ((feature_enabled($x['profile_uid'], 'auto_save_draft')) ? "true" : "false");
@@ -1563,7 +1562,7 @@ function sort_item_children($items) {
$result = $items;
usort($result,'sort_thr_created_rev');
foreach($result as $k => $i) {
- if($result[$k]['children']) {
+ if(isset($result[$k]['children'])) {
$result[$k]['children'] = sort_item_children($result[$k]['children']);
}
}
@@ -1573,7 +1572,7 @@ function sort_item_children($items) {
function add_children_to_list($children, &$arr) {
foreach($children as $y) {
$arr[] = $y;
- if($y['children'])
+ if(isset($y['children']))
add_children_to_list($y['children'], $arr);
}
}
diff --git a/include/datetime.php b/include/datetime.php
index ef0927ea4..4c7105138 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -534,3 +534,39 @@ function update_birthdays() {
}
}
}
+
+/**
+ *
+ * Calculate a due by interval
+ * based on the current datetime the interval is added/subtracted
+ * @author Hilmar Runge
+ * @since 2020-02-20
+ * @param $duri the interval in the format n[n]i
+ * where n is a 1-2 digit numeric amount and i is a unit
+ * example $duri='1w' represents one week
+ * unit may be one of i(minutes), h(hours), d(days), w(weeks), m(months, y(years))
+ * @return array['due'] computed datetime in format 'Y-m-d H:i:s'
+ * ['durn'] the amount
+ * ['duru'] the unit
+ * or false
+ */
+ function calculate_adue($duri=false, $sign='+') {
+ if ( preg_match( '/^[0-9]{1,2}[ihdwmy]{1}$/', $duri ) && ($sign == '+' || $sign == '-') ) {
+ $duru = substr( $duri, -1);
+ $durn = substr( $duri, 0, -1);
+
+ if(!$durn)
+ return false;
+
+ $due = date( 'Y-m-d H:i:s', strtotime(
+ '+' . $durn . ' '
+ . str_replace( array(':i',':h',':d',':w',':m',':y'),
+ array('minutes', 'hours', 'days', 'weeks', 'months', 'years'),
+ ( ':'. $duru )
+ )
+ )
+ );
+ return array( 'durn' => $durn, 'duru' => $duru, 'due' => $due);
+ }
+ return false;
+ }
diff --git a/include/event.php b/include/event.php
index 765086167..440f559da 100644
--- a/include/event.php
+++ b/include/event.php
@@ -862,15 +862,15 @@ function event_import_ical($ical, $uid) {
// we do not have it here since parse_ical_file() is passing the vevent only.
$timezone_obj = \Sabre\VObject\TimeZoneUtil::getTimeZone($ical->DTSTART['TZID']);
$timezone = $timezone_obj->getName();
- $ev['timezone'] = $timezone;
+ $ev['timezone'] = (($timezone) ? $timezone : date_default_timezone_get());
}
- $ev['dtstart'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),$ev['timezone'],
+ $ev['dtstart'] = datetime_convert((($ev['adjust']) ? 'UTC' : $ev['timezone']), 'UTC',
$dtstart->format(\DateTime::W3C));
if(isset($ical->DTEND)) {
$dtend = $ical->DTEND->getDateTime();
- $ev['dtend'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),$ev['timezone'],
+ $ev['dtend'] = datetime_convert((($ev['adjust']) ? 'UTC' : $ev['timezone']), 'UTC',
$dtend->format(\DateTime::W3C));
}
else {
@@ -1311,9 +1311,9 @@ function event_store_item($arr, $event) {
}
// propagate the event resource_id so that posts containing it are easily searchable in downstream copies
- // of the item which have not stored the actual event. Required for Diaspora event federation as Diaspora
+ // of the item which have not stored the actual event. Required for Diaspora event federation as Diaspora
// event_participation messages refer to the event resource_id as a parent, while out own event attendance
- // activities refer to the item message_id as the parent.
+ // activities refer to the item message_id as the parent.
set_iconfig($item_arr, 'system','event_id',$event['event_hash'],true);
diff --git a/include/features.php b/include/features.php
index e1457604b..584d9cdfb 100644
--- a/include/features.php
+++ b/include/features.php
@@ -146,40 +146,40 @@ function get_features($filtered = true, $level = (-1)) {
t('Conversation'),
/* disable until we agree on how to implemnt this in zot6/activitypub
[
- 'commtag',
- t('Community Tagging'),
+ 'commtag',
+ t('Community Tagging'),
t('Ability to tag existing posts'),
false,
get_config('feature_lock','commtag'),
],
*/
[
- 'emojis',
- t('Emoji Reactions'),
+ 'emojis',
+ t('Emoji Reactions'),
t('Add emoji reaction ability to posts'),
true,
get_config('feature_lock','emojis'),
],
[
- 'dislike',
- t('Dislike Posts'),
+ 'dislike',
+ t('Dislike Posts'),
t('Ability to dislike posts/comments'),
false,
get_config('feature_lock','dislike'),
],
[
- 'star_posts',
- t('Star Posts'),
+ 'star_posts',
+ t('Star Posts'),
t('Ability to mark special posts with a star indicator'),
false,
get_config('feature_lock','star_posts'),
],
-
+
[
- 'reply_to',
- t('Reply on comment'),
+ 'reply_to',
+ t('Reply on comment'),
t('Ability to reply on selected comment'),
false,
get_config('feature_lock','reply_to'),
@@ -211,60 +211,59 @@ function get_features($filtered = true, $level = (-1)) {
t('Add categories to your posts'),
false,
get_config('feature_lock','categories'),
- feature_level('categories',1),
],
[
- 'large_photos',
- t('Large Photos'),
+ 'large_photos',
+ t('Large Photos'),
t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'),
false,
get_config('feature_lock','large_photos'),
],
[
- 'content_encrypt',
- t('Even More Encryption'),
+ 'content_encrypt',
+ t('Even More Encryption'),
t('Allow optional encryption of content end-to-end with a shared secret key'),
false,
get_config('feature_lock','content_encrypt'),
],
[
- 'disable_comments',
- t('Disable Comments'),
+ 'disable_comments',
+ t('Disable Comments'),
t('Provide the option to disable comments for a post'),
false,
get_config('feature_lock','disable_comments'),
],
[
- 'delayed_posting',
- t('Delayed Posting'),
+ 'delayed_posting',
+ t('Delayed Posting'),
t('Allow posts to be published at a later date'),
false,
get_config('feature_lock','delayed_posting'),
],
- [
+ [
'content_expire',
t('Content Expiration'),
- t('Remove posts/comments and/or private messages at a future time'),
- false,
+ t('Remove posts/comments and/or private messages at a future time'),
+ false,
get_config('feature_lock','content_expire'),
],
[
- 'suppress_duplicates',
- t('Suppress Duplicate Posts/Comments'),
+ 'suppress_duplicates',
+ t('Suppress Duplicate Posts/Comments'),
t('Prevent posts with identical content to be published with less than two minutes in between submissions.'),
true,
get_config('feature_lock','suppress_duplicates'),
],
[
- 'auto_save_draft',
- t('Auto-save drafts of posts and comments'),
+ 'auto_save_draft',
+ t('Auto-save drafts of posts and comments'),
t('Automatically saves post and comment drafts in local browser storage to help prevent accidental loss of compositions'),
true,
get_config('feature_lock','auto_save_draft'),
@@ -277,8 +276,8 @@ function get_features($filtered = true, $level = (-1)) {
t('Manage'),
[
- 'nav_channel_select',
- t('Navigation Channel Select'),
+ 'nav_channel_select',
+ t('Navigation Channel Select'),
t('Change channels directly from within the navigation dropdown menu'),
false,
get_config('feature_lock','nav_channel_select'),
@@ -307,8 +306,8 @@ function get_features($filtered = true, $level = (-1)) {
],
[
- 'savedsearch',
- t('Saved Searches'),
+ 'savedsearch',
+ t('Saved Searches'),
t('Save search terms for re-use'),
false,
get_config('feature_lock','savedsearch')
@@ -339,8 +338,8 @@ function get_features($filtered = true, $level = (-1)) {
],
[
- 'forums_tab',
- t('Forum Filter'),
+ 'forums_tab',
+ t('Forum Filter'),
t('Ability to display only posts of a specific forum'),
false,
get_config('feature_lock','forums_tab')
@@ -401,8 +400,8 @@ function get_features($filtered = true, $level = (-1)) {
[
'multi_profiles',
t('Multiple Profiles'),
- t('Ability to create multiple profiles'),
- false,
+ t('Ability to create multiple profiles'),
+ false,
get_config('feature_lock','multi_profiles')
]
@@ -426,7 +425,7 @@ function get_features($filtered = true, $level = (-1)) {
for($y = 0; $y < count($arr[$k]); $y ++) {
$disabled = false;
if(is_array($arr[$k][$y])) {
- if($arr[$k][$y][4] !== false) {
+ if($arr[$k][$y][4] !== false) {
$disabled = true;
}
if(! $disabled) {
@@ -446,7 +445,7 @@ function get_features($filtered = true, $level = (-1)) {
return $narr;
}
-
+
function get_module_features($module) {
$features = get_features(false);
return $features[$module];
diff --git a/include/feedutils.php b/include/feedutils.php
index 9cb645ff8..e827bde98 100644
--- a/include/feedutils.php
+++ b/include/feedutils.php
@@ -324,7 +324,7 @@ function get_atom_author($feed, $item) {
// check for a yahoo media element (github etc.)
- if(! $author['author_photo']) {
+ if(! x($author,'author_photo') || ! $author['author_photo']) {
$rawmedia = $item->get_item_tags(NAMESPACE_YMEDIA,'thumbnail');
if($rawmedia && $rawmedia[0]['attribs']['']['url']) {
$author['author_photo'] = strip_tags(unxmlify($rawmedia[0]['attribs']['']['url']));
@@ -334,7 +334,7 @@ function get_atom_author($feed, $item) {
// No photo/profile-link on the item - look at the feed level
- if((! (x($author,'author_link'))) || (! (x($author,'author_photo')))) {
+ if(! x($author,'author_link') || ! x($author,'author_photo')) {
$rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
@@ -440,8 +440,7 @@ function get_atom_elements($feed, $item) {
$summary = '';
if(($summary) && ((strpos($summary,'<') !== false) || (strpos($summary,'>') !== false))) {
- $summary = purify_html($summary);
- $summary = html2bbcode($summary);
+ $summary = html2plain($summary);
}
@@ -479,13 +478,13 @@ function get_atom_elements($feed, $item) {
if($rawedited)
$res['edited'] = unxmlify($rawedited[0]['data']);
- if((x($res,'edited')) && (! (x($res,'created'))))
+ if(x($res,'edited') && ! x($res,'created'))
$res['created'] = $res['edited'];
- if(! $res['created'])
+ if(! x($res,'created'))
$res['created'] = $item->get_date('c');
- if(! $res['edited'])
+ if(! x($res,'edited'))
$res['edited'] = $item->get_date('c');
$rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
@@ -510,7 +509,7 @@ function get_atom_elements($feed, $item) {
}
}
- $ostatus_protocol = (($ostatus_conversation || $res['verb']) ? true : false);
+ $ostatus_protocol = ($ostatus_conversation || (x($res,'verb') && $res['verb']) ? true : false);
$mastodon = (($item->get_item_tags('http://mastodon.social/schema/1.0','scope')) ? true : false);
if($mastodon) {
@@ -732,7 +731,7 @@ function get_atom_elements($feed, $item) {
if((strpos($type,'audio') === 0) && (strpos($res['body'], ']' . $link . '[/audio]') === false) && (strpos($link,'http') === 0)) {
$res['body'] .= "\n\n" . '[audio]' . $link . '[/audio]';
}
-
+
$res['attach'][] = array('href' => $link, 'length' => $len, 'type' => $type, 'title' => $title );
}
}
@@ -1114,7 +1113,8 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$parent_link = $rawthread[0]['attribs']['']['href'];
}
- logger('in-reply-to: ' . $parent_mid, LOGGER_DEBUG);
+ if(isset($parent_mid))
+ logger('in-reply-to: ' . $parent_mid, LOGGER_DEBUG);
if($is_reply) {
@@ -1409,7 +1409,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// if we have everything but a photo, provide the default profile photo
- if($author['author_name'] && $author['author_link'] && (! $author['author_photo']))
+ if($author['author_name'] && $author['author_link'] && (! x($author,'author_photo') || ! $author['author_photo']))
$author['author_photo'] = z_root() . '/' . get_default_profile_photo(80);
if(is_array($contact)) {
diff --git a/include/html2plain.php b/include/html2plain.php
index 91a1f14cb..bf8581bdb 100644
--- a/include/html2plain.php
+++ b/include/html2plain.php
@@ -76,28 +76,47 @@ function quotelevel($message, $wraplength = 75)
return(implode("\n", $newlines));
}
+
function collecturls($message) {
+
$pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is';
preg_match_all($pattern, $message, $result, PREG_SET_ORDER);
-
- $urls = array();
- foreach ($result as $treffer) {
- // A list of some links that should be ignored
- $list = array("/user/", "/tag/", "/group/", "/profile/", "/channel/", "/search?search=", "/search?tag=", "mailto:", "/u/", "/node/",
- "//facebook.com/profile.php?id=", "//plus.google.com/");
- foreach ($list as $listitem)
- if (strpos($treffer[1], $listitem) !== false)
- $ignore = true;
-
- if ((strpos($treffer[1], "//plus.google.com/") !== false) and (strpos($treffer[1], "/posts") !== false))
+
+ $urls = [];
+ if ($result) {
+ $ignore = false;
+ foreach ($result as $treffer) {
+ // A list of some links that should be ignored
+ $list = [
+ "/user/",
+ "/tag/",
+ "/group/",
+ "/profile/",
+ "/channel/",
+ "/search?search=",
+ "/search?tag=",
+ "mailto:",
+ "/u/",
+ "/node/",
+ "//facebook.com/profile.php?id=",
+ "//plus.google.com/"
+ ];
+ foreach ($list as $listitem)
+ if (strpos($treffer[1], $listitem) !== false)
+ $ignore = true;
+
+ if ((strpos($treffer[1], "//plus.google.com/") !== false) and (strpos($treffer[1], "/posts") !== false))
$ignore = false;
-
- if (!$ignore)
- $urls[$treffer[1]] = $treffer[1];
+
+ if (! $ignore)
+ $urls[$treffer[1]] = $treffer[1];
+ }
}
+
return($urls);
}
+
function html2plain($html, $wraplength = 75, $compact = false)
{
diff --git a/include/hubloc.php b/include/hubloc.php
index e803b7852..2cce7a725 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -172,6 +172,46 @@ function remove_obsolete_hublocs() {
}
}
+/**
+ * @brief Remove duplicate singleton hublocs
+ *
+ * This should not actually happen but it appears it does - probably due to race conditions.
+ * This function will just leave the hubloc with the highest id (latest)
+ *
+ * TODO: we should probably do something about that at the DB level.
+ *
+ */
+function remove_duplicate_singleton_hublocs() {
+ $hublocs = dbq("SELECT hubloc_hash, COUNT(hubloc_hash) FROM hubloc WHERE
+ hubloc_network IN(
+ 'activitypub',
+ 'diaspora',
+ 'friendica-over-diaspora',
+ 'gnusoc'
+ )
+ GROUP BY hubloc_hash
+ HAVING COUNT(hubloc_hash) > 1"
+ );
+
+ foreach($hublocs as $hubloc) {
+ $hubloc_hash = $hubloc['hubloc_hash'];
+
+ $max_id = q("select max(hubloc_id) as max_id from hubloc where hubloc_hash = '%s'",
+ dbesc($hubloc_hash)
+ );
+
+ $id = $max_id[0]['max_id'];
+
+ if($hubloc_hash && $id) {
+ q("delete from hubloc where hubloc_hash = '%s' and hubloc_id != %d",
+ dbesc($hubloc_hash),
+ intval($id)
+ );
+ }
+ }
+
+}
+
/**
* @brief Change primary hubloc.
@@ -191,7 +231,7 @@ function hubloc_change_primary($hubloc) {
logger('setting primary: ' . $hubloc['hubloc_url'] . ((intval($hubloc['hubloc_primary'])) ? ' true' : ' false'));
- // See if this is a local hubloc and if so update the primary for the corresponding channel record.
+ // See if this is a local hubloc and if so update the primary for the corresponding channel record.
if($hubloc['hubloc_url'] === z_root()) {
$r = q("select channel_id from channel where channel_hash = '%s' limit 1",
@@ -205,7 +245,7 @@ function hubloc_change_primary($hubloc) {
}
}
- // we only need to proceed further if this particular hubloc is now primary
+ // we only need to proceed further if this particular hubloc is now primary
if(! (intval($hubloc['hubloc_primary']))) {
logger('not primary: ' . $hubloc['hubloc_url']);
@@ -273,7 +313,7 @@ function hubloc_mark_as_down($posturl) {
*
* @param string $netid network identity (typically xchan_hash or hubloc_hash)
* @return string
- */
+ */
function locations_by_netid($netid) {
@@ -281,7 +321,7 @@ function locations_by_netid($netid) {
dbesc($netid)
);
-
+
return array_elm_to_str($locs,'location',', ','trim_and_unpunify');
}
@@ -331,7 +371,7 @@ function z6_discover() {
if ($q2) {
continue;
}
- // zot6 hubloc not found.
+ // zot6 hubloc not found.
if(strpos($q['site_project'],'hubzilla') !== false && version_compare($q['site_version'],'4.0') >= 0) {
// probe and store results - only for zot6 (over-ride the zot default)
discover_by_webbie($q['hubloc_addr'],'zot6');
diff --git a/include/import.php b/include/import.php
index 42fa2f247..379789109 100644
--- a/include/import.php
+++ b/include/import.php
@@ -715,11 +715,6 @@ function import_items($channel, $items, $sync = false, $relocate = null) {
continue;
}
- // deprecated
-
- if(array_key_exists('diaspora_meta',$item))
- unset($item['diaspora_meta']);
-
if($relocate && $item['mid'] === $item['parent_mid']) {
item_url_replace($channel,$item,$relocate['url'],z_root(),$relocate['channel_address']);
}
diff --git a/include/items.php b/include/items.php
index 5aee7a51c..9e2a1c10e 100644
--- a/include/items.php
+++ b/include/items.php
@@ -758,22 +758,34 @@ function get_item_elements($x,$allow_code = false) {
// and not enough info to be able to look you up from your hash - which is the only thing stored with the post.
$xchan_hash = import_author_xchan($x['author']);
- if($xchan_hash)
+ if($xchan_hash) {
$arr['author_xchan'] = $xchan_hash;
- else
- return array();
+ }
+ else {
+ return [];
+ }
// save a potentially expensive lookup if author == owner
+ $legacy_sig = false;
+ $owner_hash = '';
+ if(isset($x['owner']['id']) && isset($x['owner']['key']) && isset($x['owner']['network']) && $x['owner']['network'] === 'zot6') {
+ $owner_hash = Libzot::make_xchan_hash($x['owner']['id'], $x['owner']['key']);
+ }
+ else {
+ $owner_hash = make_xchan_hash($x['owner']['guid'],$x['owner']['guid_sig']);
+ $legacy_sig = true;
+ }
- if($arr['author_xchan'] === make_xchan_hash($x['owner']['guid'],$x['owner']['guid_sig']))
+ if($arr['author_xchan'] === $owner_hash) {
$arr['owner_xchan'] = $arr['author_xchan'];
+ }
else {
$xchan_hash = import_author_xchan($x['owner']);
if($xchan_hash) {
$arr['owner_xchan'] = $xchan_hash;
}
else {
- return array();
+ return [];
}
}
@@ -793,7 +805,15 @@ function get_item_elements($x,$allow_code = false) {
);
if($r) {
if($r[0]['xchan_pubkey'] && $r[0]['xchan_network'] === 'zot6') {
- if(Libzot::verify($x['body'], $arr['sig'], $r[0]['xchan_pubkey'])) {
+ $item_verified = false;
+ if($legacy_sig) {
+ $item_verified = Crypto::verify($x['body'], base64url_decode($arr['sig']), $r[0]['xchan_pubkey']);
+ }
+ else {
+ $item_verified = Libzot::verify($x['body'], $arr['sig'], $r[0]['xchan_pubkey']);
+ }
+
+ if($item_verified) {
$arr['item_verified'] = 1;
}
else {
@@ -926,23 +946,41 @@ function import_author_xchan($x) {
* * \e string \b xchan_hash - Thre returned value
*/
call_hooks('import_author_xchan', $arr);
- if($arr['xchan_hash'])
+ if($arr['xchan_hash']) {
return $arr['xchan_hash'];
+ }
$y = false;
- if((! array_key_exists('network', $x)) || ($x['network'] === 'zot')) {
+ if((isset($x['id']) && isset($x['key'])) && (!isset($x['network']) || $x['network'] === 'zot6')) {
+ $y = Libzot::import_author_zot($x);
+ }
+
+ if(!$y && isset($x['url']) && isset($x['network']) && $x['network'] === 'zot6') {
+ $r = q("SELECT xchan_hash FROM xchan WHERE xchan_url = '%s' AND xchan_network = 'zot6'",
+ dbesc($x['url'])
+ );
+ if($r)
+ $y = $r[0]['xchan_hash'];
+ else
+ $y = discover_by_webbie($x['url'], 'zot6');
+ }
+
+ // if we were told that it's a zot6 connection, don't probe/import anything else
+
+ if($y)
+ return $y;
+
+ if(!$y && !isset($x['network']) || $x['network'] === 'zot') {
$y = import_author_zot($x);
}
- // if we were told that it's a zot connection, don't probe/import anything else
- if(array_key_exists('network',$x) && $x['network'] === 'zot') {
+ if(isset($x['network']) || $x['network'] === 'zot') {
if($x['url']) {
// check if we already have the zot6 xchan of this xchan_url. if not import it.
$r = q("SELECT xchan_hash FROM xchan WHERE xchan_url = '%s' AND xchan_network = 'zot6'",
dbesc($x['url'])
);
-
if(! $r)
discover_by_webbie($x['url'], 'zot6');
}
@@ -951,10 +989,8 @@ function import_author_xchan($x) {
}
// perform zot6 discovery
-
if($x['url']) {
- $y = discover_by_webbie($x['url'],'zot6');
-
+ $y = discover_by_webbie($x['url'], 'zot6');
if($y) {
return $y;
}
@@ -968,7 +1004,7 @@ function import_author_xchan($x) {
$y = import_author_unknown($x);
}
- return($y);
+ return $y;
}
/**
@@ -1206,10 +1242,10 @@ function encode_item($item,$mirror = false,$zap_compat = false) {
else
$x['comment_scope'] = $c_scope;
- if($item['term'])
- $x['tags'] = encode_item_terms($item['term'],$mirror);
+ if(! empty($item['term']))
+ $x['tags'] = encode_item_terms($item['term'],$mirror);
- if($item['iconfig']) {
+ if(! empty($item['iconfig'])) {
if ($zap_compat) {
for ($y = 0; $y < count($item['iconfig']); $y ++) {
if (preg_match('|^a:[0-9]+:{.*}$|s', $item['iconfig'][$y]['v'])) {
@@ -1217,7 +1253,7 @@ function encode_item($item,$mirror = false,$zap_compat = false) {
}
}
}
- $x['meta'] = encode_item_meta($item['iconfig'],$mirror);
+ $x['meta'] = encode_item_meta($item['iconfig'],$mirror);
}
logger('encode_item: ' . print_r($x,true), LOGGER_DATA);
@@ -1296,6 +1332,10 @@ function encode_item_xchan($xchan) {
$ret['guid'] = $xchan['xchan_guid'];
$ret['guid_sig'] = $xchan['xchan_guid_sig'];
+ $ret['id'] = $xchan['xchan_guid'];
+ $ret['id_sig'] = $xchan['xchan_guid_sig'];
+ $ret['key'] = $xchan['xchan_pubkey'];
+
return $ret;
}
@@ -1432,7 +1472,7 @@ function purify_imported_object($obj) {
elseif (is_string($obj)) {
$ret = purify_html($obj);
}
-
+
return $ret;
}
@@ -1690,14 +1730,14 @@ function item_sign(&$item) {
if(array_key_exists('sig',$item) && $item['sig'])
return;
- $r = q("select channel_prvkey from channel where channel_id = %d and channel_hash = '%s' ",
+ $r = q("select * from channel where channel_id = %d and channel_hash = '%s' ",
intval($item['uid']),
dbesc($item['author_xchan'])
);
if(! $r)
return;
- $item['sig'] = base64url_encode(Crypto::sign($item['body'], $r[0]['channel_prvkey']));
+ $item['sig'] = Libzot::sign($item['body'], $r[0]['channel_prvkey']);
$item['item_verified'] = 1;
}
@@ -2832,11 +2872,11 @@ function tag_deliver($uid, $item_id) {
* Now we've got those out of the way. Let's see if this is a post that's tagged for re-delivery
*/
- $terms = array_merge(get_terms_oftype($item['term'],TERM_MENTION),get_terms_oftype($item['term'],TERM_FORUM));
-
- if($terms)
+ $terms = [];
+ if (array_key_exists('term', $item)) {
+ $terms = array_merge(get_terms_oftype($item['term'],TERM_MENTION),get_terms_oftype($item['term'],TERM_FORUM));
logger('Post mentions: ' . print_r($terms,true), LOGGER_DATA);
-
+ }
$max_forums = get_config('system','max_tagged_forums',2);
$matched_forums = 0;
@@ -2845,7 +2885,7 @@ function tag_deliver($uid, $item_id) {
$link = normalise_link($u[0]['xchan_url']);
- if($terms) {
+ if(count($terms) > 0) {
foreach($terms as $term) {
if(! link_compare($term['url'],$link)) {
continue;
@@ -4235,9 +4275,9 @@ function list_post_dates($uid, $wall, $mindate) {
$start_month = datetime_convert('','',$dstart,'Y-m-d');
$end_month = datetime_convert('','',$dend,'Y-m-d');
$str = day_translate(datetime_convert('','',$dnow,'F'));
- if(! $ret[$dyear])
- $ret[$dyear] = array();
- $ret[$dyear][] = array($str,$end_month,$start_month);
+ if(! isset($ret[$dyear]))
+ $ret[$dyear] = [];
+ $ret[$dyear][] = [ $str, $end_month, $start_month ];
$dnow = datetime_convert('','',$dnow . ' -1 month', 'Y-m-d');
}
@@ -4316,17 +4356,17 @@ function fetch_post_tags($items, $link = false) {
foreach($tags as $t) {
if(($link) && ($t['ttype'] == TERM_MENTION))
$t['url'] = chanlink_url($t['url']);
- if(array_key_exists('item_id',$items[$x])) {
+ if(array_key_exists('item_id', $items[$x])) {
if($t['oid'] == $items[$x]['item_id']) {
- if(! is_array($items[$x]['term']))
- $items[$x]['term'] = array();
+ if(array_key_exists('term', $items[$x]) && ! is_array($items[$x]['term']))
+ $items[$x]['term'] = [];
$items[$x]['term'][] = $t;
}
}
else {
if($t['oid'] == $items[$x]['id']) {
- if(! is_array($items[$x]['term']))
- $items[$x]['term'] = array();
+ if(array_key_exists('term', $items[$x]) && ! is_array($items[$x]['term']))
+ $items[$x]['term'] = [];
$items[$x]['term'][] = $t;
}
}
@@ -4336,16 +4376,16 @@ function fetch_post_tags($items, $link = false) {
foreach($imeta as $i) {
if(array_key_exists('item_id',$items[$x])) {
if($i['iid'] == $items[$x]['item_id']) {
- if(! is_array($items[$x]['iconfig']))
- $items[$x]['iconfig'] = array();
+ if(! isset($items[$x]['iconfig']))
+ $items[$x]['iconfig'] = [];
$i['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$i['v'])) ? unserialize($i['v']) : $i['v']);
$items[$x]['iconfig'][] = $i;
}
}
else {
if($i['iid'] == $items[$x]['id']) {
- if(! is_array($items[$x]['iconfig']))
- $items[$x]['iconfig'] = array();
+ if(array_key_exists('iconfig', $items[$x]) && ! is_array($items[$x]['iconfig']))
+ $items[$x]['iconfig'] = [];
$i['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$i['v'])) ? unserialize($i['v']) : $i['v']);
$items[$x]['iconfig'][] = $i;
}
@@ -4488,18 +4528,23 @@ function zot_feed($uid, $observer_hash, $arr) {
function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = CLIENT_MODE_NORMAL,$module = 'network') {
- $result = array('success' => false);
-
- $sql_extra = '';
- $sql_nets = '';
+ $result = ['success' => false];
+ $sql_extra = '';
+ $sql_nets = '';
$sql_options = '';
- $sql_extra2 = '';
- $sql_extra3 = '';
- $def_acl = '';
-
- $item_uids = ' true ';
+ $sql_extra2 = '';
+ $sql_extra3 = '';
+ $def_acl = '';
+ $item_uids = ' true ';
$item_normal = item_normal();
+ if (! (isset($arr['include_follow']) && intval($arr['include_follow']))) {
+ $item_normal .= sprintf(" and not verb in ('%s', '%s') ",
+ dbesc(ACTIVITY_FOLLOW),
+ dbesc(ACTIVITY_UNFOLLOW)
+ );
+ }
+
if($arr['uid']) {
$uid = $arr['uid'];
}
@@ -4861,7 +4906,7 @@ function item_remove_cid($xchan_hash,$mid,$uid) {
}
// Set item permissions based on results obtained from linkify_tags()
-function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, $profile_uid, $parent_item = false, &$private) {
+function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, $profile_uid, &$private, $parent_item = false) {
$first_access_tag = true;
foreach($linkified as $x) {
diff --git a/include/js_strings.php b/include/js_strings.php
index e06e105fd..ed73b0420 100644
--- a/include/js_strings.php
+++ b/include/js_strings.php
@@ -116,6 +116,11 @@ function js_strings() {
'$allday' => t('All day','calendar'),
// mod cloud
- '$download_info' => t('Please stand by while your download is being prepared.')
+ '$download_info' => t('Please stand by while your download is being prepared.'),
+
+ // mod register
+ '$email_not_valid' => t('Email address not valid'),
+ '$email_required' => t('Required')
+
));
}
diff --git a/include/menu.php b/include/menu.php
index 88863f57b..02b05a36e 100644
--- a/include/menu.php
+++ b/include/menu.php
@@ -111,7 +111,7 @@ function menu_render($menu, $class='', $edit = false, $var = array()) {
$menu['items'][$x]['mitem_desc'] = zidify_links(smilies(bbcode($menu['items'][$x]['mitem_desc'])));
}
- $wrap = (($var['wrap'] === 'none') ? false : true);
+ $wrap = (! x($var, 'wrap') || $var['wrap'] === 'none' ? false : true);
$ret = replace_macros(get_markup_template('usermenu.tpl'),array(
'$menu' => $menu['menu'],
diff --git a/include/network.php b/include/network.php
index f5ff48fce..fcc7b4289 100644
--- a/include/network.php
+++ b/include/network.php
@@ -1134,11 +1134,15 @@ function discover_by_webbie($webbie, $protocol = '') {
foreach($x['links'] as $link) {
if(array_key_exists('rel',$link)) {
if($link['rel'] === PROTOCOL_ZOT6 && ((! $protocol) || (strtolower($protocol) === 'zot6'))) {
+
logger('zot6 found for ' . $webbie, LOGGER_DEBUG);
$record = Zotfinger::exec($link['href']);
+ if (! $record) {
+ logger('Record not found for ' . $link['href']);
+ continue;
+ }
// Check the HTTP signature
-
$hsig = $record['signature'];
if($hsig && $hsig['signer'] === $link['href'] && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
$hsig_valid = true;
@@ -1226,7 +1230,7 @@ function webfinger_rfc7033($webbie, $zot = false) {
if($m['scheme'] !== 'https')
return false;
- $rhs = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+ $rhs = $m['host'] . (array_key_exists('port', $m) ? ':' . $m['port'] : '');
$resource = urlencode($webbie);
}
}
@@ -1957,10 +1961,10 @@ function service_plink($contact, $guid) {
$m = parse_url($contact['xchan_url']);
if($m) {
- $url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+ $url = $m['scheme'] . '://' . $m['host'] . (array_key_exists('port', $m) ? ':' . $m['port'] : '');
}
else {
- $url = 'https://' . substr($contact['xchan_addr'],strpos($contact['xchan_addr'],'@')+1);
+ $url = 'https://' . substr($contact['xchan_addr'], strpos($contact['xchan_addr'], '@') + 1);
}
$handle = substr($contact['xchan_addr'], 0, strpos($contact['xchan_addr'],'@'));
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 8de5185af..256369c69 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -239,7 +239,7 @@ function import_xchan_photo($photo, $xchan, $thing = false, $force = false) {
if($force || empty($modified))
$result = z_fetch_url($photo, true);
- elseif($exp - 60 < time()) {
+ else {
$h = [];
$h[] = "If-Modified-Since: " . gmdate("D, d M Y H:i:s", $exp) . " GMT";
if(! empty($etag))
@@ -247,6 +247,7 @@ function import_xchan_photo($photo, $xchan, $thing = false, $force = false) {
$result = z_fetch_url($photo, true, 0, [ 'headers' => $h ]);
}
+
if(isset($result)) {
$hdrs = [];
$h = explode("\n", $result['header']);
diff --git a/include/queue_fn.php b/include/queue_fn.php
index b72730d2f..1e8171b1d 100644
--- a/include/queue_fn.php
+++ b/include/queue_fn.php
@@ -132,7 +132,7 @@ function queue_deliver($outq, $immediate = false) {
$base = null;
$h = parse_url($outq['outq_posturl']);
if($h !== false)
- $base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
+ $base = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
if(($base) && ($base !== z_root()) && ($immediate)) {
$y = q("select site_update, site_dead from site where site_url = '%s' ",
diff --git a/include/security.php b/include/security.php
index 066b1dcf4..f433f8094 100644
--- a/include/security.php
+++ b/include/security.php
@@ -592,10 +592,9 @@ function check_form_security_token($typename = '', $formname = 'form_security_to
$hash = $_REQUEST[$formname];
$max_livetime = 10800; // 3 hours
- $min_livetime = 3; // 3 sec
$x = explode('.', $hash);
- if (time() > (IntVal($x[0]) + $max_livetime) || time() < (IntVal($x[0]) + $min_livetime))
+ if (time() > (IntVal($x[0]) + $max_livetime))
return false;
$sec_hash = hash('whirlpool', App::$observer['xchan_guid'] . ((local_channel()) ? App::$channel['channel_prvkey'] : '') . session_id() . $x[0] . $typename);
@@ -834,3 +833,106 @@ function stream_perms_xchans($perms = NULL) {
return $str;
}
+
+
+/**
+ * Duty day / time checks for account register
+ * @author hilmar runge
+ * @since 2020.02.10
+ * @param $op what to test: isOpen, nextOpen
+ * @param $wd weekday according ISO-8601 (1 monday, 7 sunday)
+ * @param $hhmm a 24h clock value hours and minutes
+ * if no params are given, the values are taken from the current time
+ * return is bool(false) if register_duty is not available
+ */
+function zarIsDuty($wd=NULL, $hhmm=NULL, $op='isOpen') {
+
+ $isduty = get_config('system', 'register_duty_jso');
+
+ if (!$isduty)
+ return (bool)false;
+
+ is_null($wd) ? $wd = date('N') : '';
+ is_null($hhmm) ? $hhmm = date('Hi') : '';
+
+ if (!intval($wd . $hhmm)) return (bool)false;
+
+ // be sure to have a valid weekday as index
+ $wd = (7 + $wd) % 7;
+ $wd === 0 ? $wd = 7 : '';
+
+ $duty = json_decode($isduty, true);
+ if (!$duty)
+ return (bool)false;
+
+ switch ($op) {
+ case 'isOpen':
+ /**
+ * Check if registration is open
+ * @return int(0) for not close (open) or int(1) for closed.
+ * return is bool(false) if register_duty is not available
+ */
+ if (!$duty[$wd]) return (bool)false;
+ $dutyis = 0;
+ foreach ($duty[$wd] as $o => $tf) {
+ if ($o > $hhmm) {
+ $dutyis = $tf;
+ break;
+ }
+ }
+ return $dutyis;
+ break;
+
+ case 'nextOpen':
+ /**
+ * Look for next period opens
+ * @return "=>N =>Hi" date value of the next period register is open for requests
+ * where N is a weekday (1=monday ... 7=sunday) according ISO-8601
+ * where Hi is a 24h clock value hhmm by hours and minutes.
+ * If no next period open is available, return results to false.
+ */
+ $myd = $wd;
+ $myh = $hhmm;
+ $is1 = false;
+
+ // $myd = "5"; // testcase only
+ // $myh = "1110"; // testcase only
+
+ // a 1st match may be applied below my time and is to see as a cycle to the next week
+ // but looking is also for a open time after my time is available this week
+ foreach ($duty as $dd => $dhs) {
+
+ if ($is1 && $dd < $myd)
+ continue;
+
+ foreach ($dhs as $dh => $tf) {
+
+ if ($tf) continue; // close
+
+ // a weeks 1st open
+ if (!$is1) $is1 = array($dd, $dh);
+
+ // but is a match after now?
+ //if ($dd == $myd && $myh >= $dh && $myh <= $dh) continue;
+
+ // if the day is not (more) today start find early morning
+ if ($dd > $myd) $myh = "0000";
+
+ // a next period after now in the remainder of the week
+ if ($dd >= $myd && $dh >= $myh && !$tf)
+ return array($dd, $dh);
+ else
+ continue;
+ }
+ }
+ return $is1; // false or array
+ break;
+
+ default:
+ //
+ break;
+ }
+
+}
+
+
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 5fa4fde3f..f765a9f0e 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -331,11 +331,11 @@ function pubtagblock($net,$site,$limit,$recent = 0,$safemode = 1, $type = TERM_H
}
-function pub_tagadelic($net,$site,$limit,$recent,$safemode,$type) {
-
- $item_normal = item_normal();
- $count = intval($limit);
-
+function pub_tagadelic($net, $site, $limit, $recent, $safemode, $type) {
+
+ $item_normal = item_normal();
+ $count = intval($limit);
+ $sql_extra = "";
if($site)
$uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 ";
else {
diff --git a/include/text.php b/include/text.php
index ac22fe565..622c44f14 100644
--- a/include/text.php
+++ b/include/text.php
@@ -1108,7 +1108,7 @@ function magiclink_url($observer,$myaddr,$url) {
function micropro($contact, $redirect = false, $class = '', $mode = false) {
- if($contact['click'])
+ if(x($contact,'click'))
$url = '#';
else
$url = chanlink_hash($contact['xchan_hash']);
@@ -1121,10 +1121,10 @@ function micropro($contact, $redirect = false, $class = '', $mode = false) {
$tpl = 'micropro_card.tpl';
return replace_macros(get_markup_template($tpl), array(
- '$click' => (($contact['click']) ? $contact['click'] : ''),
- '$class' => $class . (($contact['archived']) ? ' archived' : ''),
- '$oneway' => (($contact['oneway']) ? true : false),
- '$perminfo' => $contact['perminfo'],
+ '$click' => (x($contact,'click') ? $contact['click'] : ''),
+ '$class' => $class . (x($contact,'archived') && $contact['archived'] ? ' archived' : ''),
+ '$oneway' => (x($contact,'oneway') && $contact['oneway'] ? true : false),
+ '$perminfo' => (x($contact,'perminfo') ? $contact['perminfo'] : ''),
'$url' => $url,
'$photo' => $contact['xchan_photo_s'],
'$name' => $contact['xchan_name'],
@@ -1535,39 +1535,46 @@ function unobscure_mail(&$item) {
function theme_attachments(&$item) {
+ $s = '';
$arr = json_decode($item['attach'],true);
-
if(is_array($arr) && count($arr)) {
- $attaches = array();
+
+ $attaches = [];
foreach($arr as $r) {
- $icon = getIconFromType($r['type']);
+ if(isset($r['type']))
+ $icon = getIconFromType($r['type']);
- if($r['title'])
+ if(isset($r['title']))
$label = urldecode(htmlspecialchars($r['title'], ENT_COMPAT, 'UTF-8'));
- if(! $label && $r['href'])
+ if(! $label && isset($r['href']))
$label = basename($r['href']);
//some feeds provide an attachment where title an empty space
if(! $label || $label == ' ')
$label = t('Unknown Attachment');
- $title = t('Size') . ' ' . (($r['length']) ? userReadableSize($r['length']) : t('unknown'));
+ $title = t('Size') . ' ' . (isset($r['length']) ? userReadableSize($r['length']) : t('unknown'));
require_once('include/channel.php');
- if(is_foreigner($item['author_xchan']))
- $url = $r['href'];
- else
- $url = z_root() . '/magic?f=&owa=1&hash=' . $item['author_xchan'] . '&bdest=' . bin2hex($r['href'] . '/' . $r['revision']);
+
+ if (isset($r['href'])) {
+ if(is_foreigner($item['author_xchan']))
+ $url = $r['href'];
+ else
+ $url = z_root() . '/magic?f=&owa=1&hash=' . $item['author_xchan'] . '&bdest=' . bin2hex($r['href'] . '/' . $r['revision']);
+ }
//$s .= '<a href="' . $url . '" title="' . $title . '" class="attachlink" >' . $icon . '</a>';
- $attaches[] = array('label' => $label, 'url' => $url, 'icon' => $icon, 'title' => $title);
+ if (isset($label) && isset($url) && isset($icon) && isset($title))
+ $attaches[] = array('label' => $label, 'url' => $url, 'icon' => $icon, 'title' => $title);
}
- $s = replace_macros(get_markup_template('item_attach.tpl'), array(
- '$attaches' => $attaches
- ));
+ if (count($attaches) > 0)
+ $s = replace_macros(get_markup_template('item_attach.tpl'), [
+ '$attaches' => $attaches
+ ]);
}
return $s;
@@ -1605,8 +1612,8 @@ function format_categories(&$item,$writeable) {
*/
function format_hashtags(&$item) {
- $s = '';
+ $s = '';
$terms = get_terms_oftype($item['term'], array(TERM_HASHTAG,TERM_COMMUNITYTAG));
if($terms) {
foreach($terms as $t) {
@@ -1628,13 +1635,14 @@ function format_hashtags(&$item) {
}
-
function format_mentions(&$item) {
- $s = '';
+ $s = '';
$terms = get_terms_oftype($item['term'],TERM_MENTION);
if($terms) {
foreach($terms as $t) {
+ if(! isset($t['term']))
+ continue;
$term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
if(! trim($term))
continue;
@@ -2307,6 +2315,18 @@ function undo_post_tagging($s) {
return $s;
}
+/**
+ * @brief php to js string transfer
+ * Hilmar, 20200227
+ * String values built in php for using as content for js variables become sanitized. Often required
+ * in cases, where some content will be translated by t(any text...) and is furthermore transfered via
+ * templates to the outputted html stream. Redecoding in js not required nor useful.
+ * Apply like: p2j(t('any text\nI will place on a "next line"'));
+ */
+function p2j($string) {
+ return preg_replace('/\r?\n/', '\\n', addslashes($string));
+}
+
function quote_tag($s) {
if(strpos($s,' ') !== false)
return '&quot;' . $s . '&quot;';
@@ -3559,6 +3579,8 @@ function cleanup_bbcode($body) {
$body = preg_replace_callback('/\[url(.*?)\[\/(url)\]/ism','\red_escape_codeblock',$body);
$body = preg_replace_callback('/\[zrl(.*?)\[\/(zrl)\]/ism','\red_escape_codeblock',$body);
$body = preg_replace_callback('/\[svg(.*?)\[\/(svg)\]/ism','\red_escape_codeblock',$body);
+ $body = preg_replace_callback('/\[img(.*?)\[\/(img)\]/ism','\red_escape_codeblock',$body);
+ $body = preg_replace_callback('/\[zmg(.*?)\[\/(zmg)\]/ism','\red_escape_codeblock',$body);
$body = preg_replace_callback("/([^\]\='".'"'."\;\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
+\,\(\)]+)/ismu", '\nakedoembed', $body);
@@ -3571,6 +3593,8 @@ function cleanup_bbcode($body) {
$body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body);
$body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body);
$body = preg_replace_callback('/\[\$b64svg(.*?)\[\/(svg)\]/ism','\red_unescape_codeblock',$body);
+ $body = preg_replace_callback('/\[\$b64img(.*?)\[\/(img)\]/ism','\red_unescape_codeblock',$body);
+ $body = preg_replace_callback('/\[\$b64zmg(.*?)\[\/(zmg)\]/ism','\red_unescape_codeblock',$body);
// fix any img tags that should be zmg
@@ -3676,7 +3700,7 @@ function get_forum_channels($uid) {
if(! $uid)
return;
- if(App::$data['forum_channels'])
+ if(isset(App::$data['forum_channels']))
return App::$data['forum_channels'];
$xf = '';
@@ -3724,6 +3748,9 @@ function get_forum_channels($uid) {
intval($uid)
);
+ if(!$r)
+ $r = [];
+
for($x = 0; $x < count($r); $x ++) {
if($x3) {
foreach($x3 as $xx) {