diff options
author | Mario <mario@mariovavti.com> | 2021-05-11 11:59:49 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2021-05-11 11:59:49 +0000 |
commit | 26e851ff7fc074592f93088dbd96713b22defe8b (patch) | |
tree | e727d9a83590b152ddd63a8c8e7756835c45de4a /Zotlabs/Module | |
parent | 406ca206347152cf4acbdcb81fc8152d83f99182 (diff) | |
parent | 89ec043ce1183dbae5ff10a994f0f819a8544ba9 (diff) | |
download | volse-hubzilla-26e851ff7fc074592f93088dbd96713b22defe8b.tar.gz volse-hubzilla-26e851ff7fc074592f93088dbd96713b22defe8b.tar.bz2 volse-hubzilla-26e851ff7fc074592f93088dbd96713b22defe8b.zip |
Merge branch '5.6RC'
Diffstat (limited to 'Zotlabs/Module')
29 files changed, 2439 insertions, 761 deletions
diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php index 88b84b9d2..44c10b339 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -101,11 +101,14 @@ class Admin extends \Zotlabs\Web\Controller { // pending registrations - $pdg = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) > 0 ", - intval(ACCOUNT_PENDING) + // $pdg = q("SELECT account.*, register.reg_hash from account left join register on account_id = register.reg_uid // where (account_flags & %d ) > 0 ", + // intval(ACCOUNT_PENDING) + // ); + $pdg = q("SELECT COUNT(*) AS pdg FROM register WHERE reg_vital = 1 AND reg_expires > '%s' ", + dbesc(date('Y-m-d H:i:s')) ); - $pending = (($pdg) ? count($pdg) : 0); + $pending = ($pdg ? $pdg[0]['pdg'] : 0); // available channels, primary and clones $channels = array(); diff --git a/Zotlabs/Module/Admin/Accounts.php b/Zotlabs/Module/Admin/Accounts.php index 0c7e089be..1c1911b3a 100644 --- a/Zotlabs/Module/Admin/Accounts.php +++ b/Zotlabs/Module/Admin/Accounts.php @@ -5,7 +5,7 @@ namespace Zotlabs\Module\Admin; class Accounts { - + /** * @brief Handle POST actions on accounts admin page. * @@ -15,14 +15,105 @@ class Accounts { * */ + const MYP = 'ZAR'; // ZAR2x + const VERSION = '2.0.0'; + function post() { $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() ); $users = ( x($_POST, 'user') ? $_POST['user'] : array() ); $blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() ); - + check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts'); - + + $isajax = is_ajax(); + $rc = 0; + + If (!is_site_admin()) { + if ($isajax) { + killme(); + exit; + } + goaway(z_root() . '/'); + } + + if ($isajax) { + //$debug = print_r($_SESSION[self::MYP],true); + $zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) ) + ? $_POST['zardo'] : ''; + // zarat arrives with leading underscore _n + $zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) ) + ? substr($_POST['zarat'],1) : ''; + $zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) ) + ? hex2bin($_POST['zarse']) : ''; + + if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) { + + // + if ($zarop == 'd') { + $rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ", + intval($_SESSION[self::MYP]['i'][$zarat]), + dbesc($_SESSION[self::MYP]['h'][$zarat]) + ); + $rc = '×'; + } + elseif ($zarop == 'a') { + // approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate + $rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), " + . " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) " + . " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ", + intval($_SESSION[self::MYP]['i'][$zarat]), + dbesc($_SESSION[self::MYP]['h'][$zarat]) + ); + $rc = 0; + $rs = q("SELECT * from register WHERE reg_id = %d ", + intval($_SESSION[self::MYP]['i'][$zarat]) + ); + if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) { + // create account + $rc = 'ok'.$rs[0]['reg_id']; + $ac = create_account_from_register($rs[0]); + if ( $ac['success'] ) { + $rc .= '✔'; + + $auto_create = get_config('system','auto_channel_create',1); + + if($auto_create) { + $reonar = json_decode($rs[0]['reg_stuff'], true); + // prepare channel creation + if($reonar['chan.name']) + set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']); + + if($reonar['chan.did1']) + set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']); + + $permissions_role = get_config('system','default_permissions_role'); + if($permissions_role) + set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role); + + // create channel + $new_channel = auto_channel_create($ac['account']['account_id']); + + if($new_channel['success']) { + $rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔'; + } + else { + $rc .= ' c ×'; + } + } + + + } + } else { + $rc='oh ×'; + } + } + echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc)); + } + killme(); + exit; + } + // change to switch structure? // account block/unblock button was submitted if (x($_POST, 'page_accounts_block')) { @@ -55,7 +146,7 @@ class Accounts { account_deny($hash); } } - + goaway(z_root() . '/admin/accounts' ); } @@ -75,19 +166,21 @@ class Accounts { $account = q("SELECT * FROM account WHERE account_id = %d", intval($uid) ); - + if (! $account) { notice( t('Account not found') . EOL); goaway(z_root() . '/admin/accounts' ); } - + check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts', 't'); - + + $debug = ''; + switch (argv(2)){ case 'delete': // delete user account_remove($uid,true,false); - + notice( sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL); break; case 'block': @@ -95,7 +188,7 @@ class Accounts { intval(ACCOUNT_BLOCKED), intval($uid) ); - + notice( sprintf( t("Account '%s' blocked") , $account[0]['account_email']) . EOL); break; case 'unblock': @@ -103,27 +196,74 @@ class Accounts { intval(ACCOUNT_BLOCKED), intval($uid) ); - + notice( sprintf( t("Account '%s' unblocked"), $account[0]['account_email']) . EOL); break; } - + goaway(z_root() . '/admin/accounts' ); } - - /* get pending */ - $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ", - intval(ACCOUNT_PENDING) - ); - + + $tao = 'tao.zar.zarax = ' . "'" . '<img src="' . z_root() . '/images/zapax16.gif">' . "';\n"; + + + // by default we will only return verified results. if reg_all is set we will return everything'' + $get_all = isset($_REQUEST['get_all']); + $pending = get_pending_accounts($get_all); + + unset($_SESSION[self::MYP]); + + if ($pending) { + // collect and group all ip + $atips = dbq("SELECT reg_atip AS atip, COUNT(reg_atip) AS atips FROM register + WHERE reg_vital = 1 GROUP BY reg_atip" + ); + + (($atips) ? $atipn = array_column($atips, 'atips', 'atip') : $atipn = ['' => 0]); + + $tao .= 'tao.zar.zarar = {'; + foreach ($pending as $n => $v) { + + $stuff = json_decode($v['reg_stuff'], true); + + if(isset($stuff['msg'])) { + $pending[$n]['msg'] = $stuff['msg']; + } + + if (array_key_exists($v['reg_atip'], $atipn)) { + $pending[$n]['reg_atip'] = $v['reg_atip']; + $pending[$n]['reg_atip_n'] = $atipn[$v['reg_atip']]; + } + + $pending[$n]['status'] = ''; + if($pending[$n]['reg_flags'] & ACCOUNT_UNVERIFIED > 0) + $pending[$n]['status'] = [t('Unverified'), 'bg-warning']; + + if($pending[$n]['status'] && $pending[$n]['reg_expires'] < datetime_convert()) + $pending[$n]['status'] = [t('Expired'), 'bg-danger text-white']; + + // timezone adjust date_time for display + $pending[$n]['reg_created'] = datetime_convert('UTC', date_default_timezone_get(), $pending[$n]['reg_created']); + $pending[$n]['reg_startup'] = datetime_convert('UTC', date_default_timezone_get(), $pending[$n]['reg_startup']); + $pending[$n]['reg_expires'] = datetime_convert('UTC', date_default_timezone_get(), $pending[$n]['reg_expires']); + + // better secure + $tao .= $n . ": '" . substr(bin2hex($v['reg_hash']),0,8) . "',"; + $_SESSION[self::MYP]['h'][] = substr($v['reg_hash'],0,4); + $_SESSION[self::MYP]['i'][] = $v['reg_id']; + } + $tao = rtrim($tao,',') . '};' . "\n"; + } + // <- hilmar] + /* get accounts */ - + $total = q("SELECT count(*) as total FROM account"); if (count($total)) { \App::set_pager_total($total[0]['total']); \App::set_pager_itemspage(100); } - + $serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : ''); $key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id'); @@ -134,8 +274,8 @@ class Accounts { $base = z_root() . '/admin/accounts?f='; $odir = (($dir === 'asc') ? '0' : '1'); - $users = q("SELECT account_id , account_email, account_lastlog, account_created, account_expires, account_service_class, ( account_flags & %d ) > 0 as blocked, - (SELECT %s FROM channel as ch WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as channels FROM account as ac + $users = q("SELECT account_id , account_email, account_lastlog, account_created, account_expires, account_service_class, ( account_flags & %d ) > 0 as blocked, + (SELECT %s FROM channel as ch WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as channels FROM account as ac where true $serviceclass and account_flags != %d order by $key $dir limit %d offset %d ", intval(ACCOUNT_BLOCKED), db_concat('ch.channel_address', ' '), @@ -143,15 +283,15 @@ class Accounts { intval(\App::$pager['itemspage']), intval(\App::$pager['start']) ); - + // function _setup_users($e){ // $accounts = Array( - // t('Normal Account'), + // t('Normal Account'), // t('Soapbox Account'), // t('Community/Celebrity Account'), // t('Automatic Friend Account') // ); - + // $e['page_flags'] = $accounts[$e['page-flags']]; // $e['register_date'] = relative_date($e['register_date']); // $e['login_date'] = relative_date($e['login_date']); @@ -159,49 +299,57 @@ class Accounts { // return $e; // } // $users = array_map("_setup_users", $users); - + $t = get_markup_template('admin_accounts.tpl'); $o = replace_macros($t, array( // strings // + '$debug' => $debug, '$title' => t('Administration'), '$page' => t('Accounts'), '$submit' => t('Submit'), - '$select_all' => t('select all'), - '$h_pending' => t('Registrations waiting for confirm'), - '$th_pending' => array( t('Request date'), t('Email') ), - '$no_pending' => t('No registrations.'), + '$get_all' => (($get_all) ? t('Show verified registrations') : t('Show all registrations')), + '$get_all_link' => (($get_all) ? z_root() .'/admin/accounts' : z_root() .'/admin/accounts?get_all'), + '$sel_tall' => t('Select toggle'), + '$sel_deny' => t('Deny selected'), + '$sel_aprv' => t('Approve selected'), + '$h_pending' => (($get_all) ? t('All registrations') : t('Verified registrations waiting for approval')), + '$th_pending' => array(t('Request date'), 'dId2', t('Email'), 'IP', t('Requests')), + '$no_pending' => (($get_all) ? t('No registrations available') : t('No verified registrations available')), '$approve' => t('Approve'), '$deny' => t('Deny'), '$delete' => t('Delete'), '$block' => t('Block'), '$unblock' => t('Unblock'), + '$verified' => t('Verified'), + '$not_verified' => t('Not yet verified'), '$odir' => $odir, '$base' => $base, '$h_users' => t('Accounts'), - '$th_users' => array( + '$th_users' => array( [ t('ID'), 'account_id' ], [ t('Email'), 'account_email' ], - [ t('All Channels'), 'channels' ], + [ t('All channels'), 'channels' ], [ t('Register date'), 'account_created' ], [ t('Last login'), 'account_lastlog' ], [ t('Expires'), 'account_expires' ], - [ t('Service Class'), 'account_service_class'] ), - - '$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'), - '$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'), - + [ t('Service class'), 'account_service_class'] ), + + '$confirm_delete_multi' => p2j(t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?')), + '$confirm_delete' => p2j(t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?')), + '$form_security_token' => get_form_security_token("admin_accounts"), - + // values // - '$baseurl' => z_root(), - - '$pending' => $pending, - '$users' => $users, + '$baseurl' => z_root(), + '$tao' => $tao, + '$pending' => $pending, + '$users' => $users, + '$msg' => t('Message') )); $o .= paginate($a); - + return $o; } - } + diff --git a/Zotlabs/Module/Admin/Channels.php b/Zotlabs/Module/Admin/Channels.php index e0f26112d..09769a166 100644 --- a/Zotlabs/Module/Admin/Channels.php +++ b/Zotlabs/Module/Admin/Channels.php @@ -173,4 +173,4 @@ class Channels { return $o; } -}
\ No newline at end of file +} diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index 011bf3ce4..3b2632411 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -5,14 +5,25 @@ namespace Zotlabs\Module\Admin; class Site { + /** * @brief POST handler for Admin Site Page. * */ function post(){ + // [hilmar-> + $this->isajax = is_ajax(); + $this->eol = $this->isajax ? "\n" : EOL; + // ] if (!x($_POST, 'page_site')) { - return; + // [ + if (!$this->isajax) + // ] + return; } + // [ + $this->msgbg = ''; + // <-hilmar] check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); @@ -24,14 +35,17 @@ class Site { $siteinfo = ((x($_POST,'siteinfo')) ? trim($_POST['siteinfo']) : ''); $language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : ''); $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : ''); -// $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : ''); -// $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : ''); + // $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : ''); + // $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : ''); $maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0); $register_policy = ((x($_POST,'register_policy')) ? intval(trim($_POST['register_policy'])) : 0); + $register_wo_email = ((x($_POST,'register_wo_email')) ? intval(trim($_POST['register_wo_email'])) : 0); $minimum_age = ((x($_POST,'minimum_age')) ? intval(trim($_POST['minimum_age'])) : 13); $access_policy = ((x($_POST,'access_policy')) ? intval(trim($_POST['access_policy'])) : 0); - $invite_only = ((x($_POST,'invite_only')) ? True : False); + $reg_autochannel = ((x($_POST,'auto_channel_create')) ? True : False); + $invitation_only = ((x($_POST,'invitation_only')) ? True : False); + $invitation_also = ((x($_POST,'invitation_also')) ? True : False); $abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0); $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : ''); @@ -75,6 +89,16 @@ class Site { $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50); $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); $verify_email = ((x($_POST,'verify_email')) ? 1 : 0); + $register_perday = ((x($_POST,'register_perday')) ? intval(trim($_POST['register_perday'])) : 50); + $register_sameip = ((x($_POST,'register_sameip')) ? intval(trim($_POST['register_sameip'])) : 3); + + $regdelayn = ((x($_POST,'zardelayn')) ? intval(trim($_POST['zardelayn'])) : 0); + $regdelayu = ((x($_POST,'zardelay')) ? notags(trim($_POST['zardelay'])) : ''); + $reg_delay = (preg_match('/^[a-z]{1,1}$/', $regdelayu) ? $regdelayn . $regdelayu : ''); + $regexpiren = ((x($_POST,'zarexpiren')) ? intval(trim($_POST['zarexpiren'])) : 0); + $regexpireu = ((x($_POST,'zarexpire')) ? notags(trim($_POST['zarexpire'])) : ''); + $reg_expire = (preg_match('/^[a-z]{1,1}$/', $regexpireu) ? $regexpiren . $regexpireu : ''); + $imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : ''); $force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000); $pub_incl = escape_tags(trim($_POST['pub_incl'])); @@ -82,6 +106,35 @@ class Site { $permissions_role = escape_tags(trim($_POST['permissions_role'])); + // [hilmar-> + $this->register_duty = ((x($_POST,'register_duty')) ? notags(trim($_POST['register_duty'])) : ''); + if (! preg_match('/^[0-9 .,:\-]{0,191}$/', $this->register_duty)) { + $this->msgbg .= 'ZAR0131E,' . t('Invalid input') . $this->eol; + $this->error++; + } else { + + $this->duty(); + + if ($this->isajax) { + echo json_encode(array('msgbg' => $this->msgbg, 'me' => 'zar')); + // that mission is complete + killme(); + exit; + + } else { + + //logger( print_r( $this->msgbg, true) ); + //logger( print_r( $this->joo, true) ); + if ($this->error === 0) { + set_config('system', 'register_duty', $this->register_duty); + set_config('system', 'register_duty_jso', $this->joo); + } else { + notice('ZAR0130E,'.t('Errors') . ': ' . $this->error) . EOL . $this->msgfg; + } + } + } + // <-hilmar] + set_config('system', 'feed_contacts', $feed_contacts); set_config('system', 'delivery_interval', $delivery_interval); set_config('system', 'delivery_batch_count', $delivery_batch_count); @@ -96,6 +149,10 @@ class Site { set_config('system', 'login_on_homepage', $login_on_homepage); set_config('system', 'enable_context_help', $enable_context_help); set_config('system', 'verify_email', $verify_email); + set_config('system', 'max_daily_registrations', $register_perday); + set_config('system', 'register_sameip', $register_sameip); + set_config('system', 'register_delay', $reg_delay); + set_config('system', 'register_expire', $reg_expire); set_config('system', 'default_expire_days', $default_expire_days); set_config('system', 'active_expire_days', $active_expire_days); set_config('system', 'reply_address', $reply_address); @@ -126,17 +183,20 @@ class Site { set_config('system','siteinfo',$siteinfo); set_config('system', 'language', $language); set_config('system', 'theme', $theme); -// if ( $theme_mobile === '---' ) { -// del_config('system', 'mobile_theme'); -// } else { -// set_config('system', 'mobile_theme', $theme_mobile); -// } - // set_config('system','site_channel', $site_channel); + // if ( $theme_mobile === '---' ) { + // del_config('system', 'mobile_theme'); + // } else { + // set_config('system', 'mobile_theme', $theme_mobile); + // } + // set_config('system','site_channel', $site_channel); set_config('system','maximagesize', $maximagesize); set_config('system','register_policy', $register_policy); + set_config('system','register_wo_email', $register_wo_email); set_config('system','minimum_age', $minimum_age); - set_config('system','invitation_only', $invite_only); + set_config('system','auto_channel_create', $reg_autochannel); + set_config('system', 'invitation_only', $invitation_only); + set_config('system', 'invitation_also', $invitation_also); set_config('system','access_policy', $access_policy); set_config('system','account_abandon_days', $abandon_days); set_config('system','register_text', $register_text); @@ -260,6 +320,8 @@ class Site { REGISTER_APPROVE => t("Yes - with approval"), REGISTER_OPEN => t("Yes") ); + $this->register_duty = get_config('system', 'register_duty', '-:-'); + $register_perday = get_config('system','max_daily_registrations', 50); /* Acess policy */ $access_choices = Array( @@ -286,9 +348,66 @@ class Site { $homelogin = get_config('system','login_on_homepage'); $enable_context_help = get_config('system','enable_context_help'); + // for reuse reg_delay and reg_expire + $reg_rabots = array( + 'i' => t('Minute(s)'), + 'h' => t('Hour(s)') , + 'd' => t('Day(s)') , + 'w' => t('Week(s)') , + 'm' => t('Month(s)') , + 'y' => t('Year(s)') + ); + $regdelay_n = $regdelay_u = false; + $regdelay = get_config('system','register_delay'); + if ($regdelay) + list($regdelay_n, $regdelay_u) = array(substr($regdelay,0,-1),substr($regdelay,-1)); + $reg_delay = replace_macros(get_markup_template('field_duration.qmc.tpl'), + array( + 'label' => t('Register verification delay'), + 'qmc' => 'zar', + 'qmcid' => '', + 'help' => t('Time to wait before a registration can be verified'), + 'field' => array( + 'name' => 'delay', + 'title' => t('duration up from now'), + 'value' => ($regdelay_n === false ? 0 : $regdelay_n), + 'min' => '0', + 'max' => '99', + 'size' => '2', + 'default' => ($regdelay_u === false ? 'i' : $regdelay_u) + ), + 'rabot' => $reg_rabots + ) + ); + $regexpire_n = $regexpire_u = false; + $regexpire = get_config('system','register_expire'); + if ($regexpire) + list($regexpire_n, $regexpire_u) = array(substr($regexpire,0,-1),substr($regexpire,-1)); + $reg_expire = replace_macros(get_markup_template('field_duration.qmc.tpl'), + array( + 'label' => t('Register verification expiration time'), + 'qmc' => 'zar', + 'qmcid' => '', + 'help' => t('Time before an unverified registration will expire'), + 'field' => array( + 'name' => 'expire', + 'title' => t('duration up from now'), + 'value' => ($regexpire_n === false ? 3 : $regexpire_n), + 'min' => '0', + 'max' => '99', + 'size' => '2', + 'default' => ($regexpire_u === false ? 'd' : $regexpire_u) + ), + 'rabot' => $reg_rabots + ) + ); + + $tao = ''; $t = get_markup_template("admin_site.tpl"); return replace_macros($t, array( '$title' => t('Administration'), + // interfacing js vars + '$tao' => $tao, '$page' => t('Site'), '$submit' => t('Submit'), '$registration' => t('Registration'), @@ -305,21 +424,87 @@ class Site { '$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")), '$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices), '$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices), -// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile), -// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")), + // '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile), + // '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")), '$feed_contacts' => array('feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)')), '$maximagesize' => array('maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")), - '$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices), - '$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")), '$minimum_age' => array('minimum_age', t("Minimum age"), (x(get_config('system','minimum_age'))?get_config('system','minimum_age'):13), t("Minimum age (in years) for who may register on this site.")), '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), t("This is displayed on the public server site list."), $access_choices), - '$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")), + + // Register + // [hilmar-> + '$register_text' => [ + 'register_text', + t("Register text"), + htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), + t("This text will be displayed prominently at the registration page") + ], + '$register_policy' => [ + 'register_policy', + t("Does this site allow new member registration?"), + get_config('system','register_policy'), + "", + $register_choices, + ], + '$register_duty' => [ + 'register_duty', + t('Configure the registration open days/hours'), + get_config('system', 'register_duty', '-:-'), + t('Empty or \'-:-\' value will keep registration open 24/7 (default)') . EOL . + t('Weekdays and hours must be separated by colon \':\', From-To ranges with a dash `-` example: 1:800-1200') . EOL . + t('Weekday:Hour pairs must be separated by space \' \' example: 1:900-1700 2:900-1700') . EOL . + t('From-To ranges must be separated by comma \',\' example: 1:800-1200,1300-1700 or 1-2,4-5:900-1700') . EOL . + t('Advanced examples:') . ' 1-5:0900-1200,1300-1700 6:900-1230 ' . t('or') . ' 1-2,4-5:800-1800<br>' . EOL . + '<a id="zar083a" class="btn btn-sm btn-outline-secondary zuia">' . t('Check your configuration') . '</a>'. EOL + ], + '$register_perday' => [ + 'register_perday', + t('Max account registrations per day'), + get_config('system', 'max_daily_registrations', 50), + t('Unlimited if zero or no value - default 50') + ], + '$register_sameip' => [ + 'register_sameip', + t('Max account registrations from same IP'), + get_config('system', 'register_sameip', 3), + t('Unlimited if zero or no value - default 3') + ], + '$reg_delay' => $reg_delay, + '$reg_expire' => $reg_expire, + '$reg_autochannel' => [ + 'auto_channel_create', + t("Auto channel create"), + get_config('system','auto_channel_create', 1), + t("If disabled the channel will be created in a separate step during the registration process") + ], + '$invitation_only' => [ + 'invitation_only', + t("Require invite code"), + $invitation_only + ], + '$invitation_also' => [ + 'invitation_also', + t("Allow invite code"), + $invitation_also + ], + '$verify_email' => [ + 'verify_email', + t("Require email address"), + get_config('system','verify_email'), + t("The provided email address will be verified (recommended)") + ], + '$abandon_days' => [ + 'abandon_days', + t('Abandon account after x days'), + get_config('system','account_abandon_days'), + t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.') + ], + // <-hilmar] + '$role' => $role, '$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'pubstream' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")), '$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')), - '$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')), '$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")), - '$verify_email' => array('verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).")), '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")), '$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')), '$site_firehose' => array('site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.')), @@ -350,15 +535,184 @@ class Site { '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")), '$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')), '$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''), - '$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())), '$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles')), - '$location' => array('site_location', t('Optional: site location'), get_config('system','site_location',''), t('Region or country')), - - '$form_security_token' => get_form_security_token("admin_site"), )); } + /** + * @brief Admin page site common post submit and ajax interaction + * @author hilmar runge + * @since 2020-02-04 + * Configure register office duty weekdays and hours + * Syntax: weekdays:hours [weekdays:hours] + * [.d[,d-d.]]]:hhmm-hhmm[,hhmm-hhmm...] + * ranges are between blanks, days are 1-7, where 1 = Monday + * hours are [h]hmm 3-4digit 24 clock values + * ie 0900-1200,1300-1800 for hours + * ie 1-2,4,5 for weekdays + * ie 1-2:900-1800 monday and tuesday open from 9 to 18h + * + * @var $register_duty is the input field from the admin -> site page + * @return the results are in the class vars $error, $msgbg and $jsoo + * $jsoo is + */ + + // 3-4 digit 24h clock regex + const regxTime34 = '/^(?:2[0-3]|[01][0-9]|[0-9])[0-5][0-9]$/'; + var $wdconst = array('','mo','tu','we','th','fr','sa','so'); + + // in + var $register_duty; + // intermediate + var $isajax; + // return + var $jsoo; + var $msgbg; + var $error = 0; + var $msgfg = ''; + + private function duty() { + + $aro=array_fill(1, 7, 0); + + if ($this->isajax) { + $op = (preg_match('/[a-z]{2,4}/', $_REQUEST['zarop'])) ? $_REQUEST['zarop'] : ''; + if ($op == 'zar083') { + $this->msgbg = 'Testmode:' . $this->eol . $this->msgbg; + } else { + killme(); + exit; + } + } + + $ranges = preg_split('/\s+/', $this->register_duty); + $this->msgbg .= '..ranges: ' . print_r(count($ranges),true) . $this->eol; + + foreach ($ranges as $rn => $range) { + list($ws,$hs,) = explode(':', $range); + + $ws ? $arw = explode( ',', $ws) : $arw=array(); + $this->msgbg .= ($rn+1).'.weekday ranges: ' . count($arw) . $this->eol; + // $this->msgbg .= print_r($arw,true); + $hs ? $arh = explode( ',', $hs) : $arh=array(); + $this->msgbg .= ($rn+1).'.hour ranges: ' . count($arh) . $this->eol; + + $this->msgbg .= ($rn+1).'.wdays: ' . ( $ws ? print_r($ws,true) : 'none') . ' : ' + . ' hours: ' . print_r($hs,true) . $this->eol; + + // several hs may belog to one wd + // aro[0] is tmp store + foreach ($arh as $hs) { + list($ho,$hc,) = explode( '-', $hs ); + + // no value forces open very early, and be sure having valid hhmm values + !$ho ? $ho = "0000" : ''; + !$hc ? $hc = "0000" : ''; // pseudo + if (preg_match(self::regxTime34, $ho) + && preg_match(self::regxTime34, $hc)) { + + // fix pseudo, allow no reverse range + $hc == "0000" || $ho > $hc ? $hc = "2400" : ''; + + $aro[0][$ho] = 0; + $aro[0][$hc] = 1; + + $this->msgbg .= ($ho ? ' .open:' . $ho : '') . ($hc ? ' close:' . $hc : '') .$this->eol; + } else { + $this->msgbg .= ' .' . t('Invalid 24h time value (hhmm/hmm)') . $this->eol; + $this->msgfg .= ' .ZAR0132E,' . t('Invalid 24h time value (hhmm/hmm)') . $this->eol; + $this->error++; + } + } + + // the weekday(s) values or ranges + foreach ($arw as $ds) { + $wd=explode('-', $ds); + array_key_exists("1", $wd) && $wd[1]=="" ? $wd[1] = "7" : ''; // a case 3- + array_key_exists("1", $wd) && $wd[0]=="" ? $wd[0] = "1" : ''; // a case -3 + !array_key_exists("1", $wd) ? $wd[1] = $wd[0] : ''; // a case 3 + if ($wd[0] > $wd[1]) continue; // reverse order will be ignored // a case 5-3 + if (preg_match('/^[1-7]{1}$/', $wd[0])) { + if (preg_match('/^[1-7]{1}$/', $wd[1])) { + // $this->msgbg .= print_r($wd,true); + for ($i=$wd[0]; $i<=$wd[1]; $i++) { + // take the tmp store for the selected day(s) + $aro[$i]=$aro[0]; + } + } + } + } + //$this->msgbg .= 'aro0: ' . print_r($aro,true) . $this->eol; // 4devels + // clear the tmp store + $aro[0]=array(); + } + // discart the tmp store + unset($aro[0]); + // not configured days close at the beginning 0000h + for ($i=1;$i<=7;$i++) { is_array($aro[$i]) ? '' : $aro[$i] = array("0000" => 1); } + // $this->msgbg .= 'aro: ' . print_r($aro,true) . $this->eol; // 4devels + + if ($this->isajax) { + // tell what we have + // $this->msgbg .= 'aro0: ' . print_r($aro,true) . $this->eol; // 4devels + $this->msgbg .= 'Duty time table:' . $this->eol; + foreach ($aro as $dow => $hrs) { + $this->msgbg .= ' ' . $this->wdconst[$dow] . ' '; + // $this->msgbg .= '**' . print_r($hrs,true); + foreach ($hrs as $h => $o) { + $this->msgbg .= ((!$o) ? $h . ':open' : $h . ':close') . ', '; + } + $this->msgbg = rtrim($this->msgbg, ', ') . $this->eol; + } + + $this->msgbg .= 'Generating 6 random times to check duty hours: ' . $this->eol; + // we only need some random dates from anyway in past or future + // because only the weekday and the clock is to test + for ($i=0; $i<6; $i++) { + $adow = rand(1, 7); // 1 to 7 (days) + $cdow = $this->wdconst[$adow]; + // below is the essential algo to verify a date (of format Hi) meets an open or closed condition + $t = date('Hi', ( rand(time(), 60*60*24+time()) ) ); + $how='close'; + foreach ($aro[$adow] as $o => $v) { + // $this->msgbg .= 'debug: ' . $o . ' gt ' . $t . ' / ' . $v . $this->eol; // 4devels + if ($o > $t) { + $how = ($v ? 'open' : 'close'); + break; + } + } + // now we know + $this->msgbg .= ' ' . $cdow . '.' . $t . '=' . $how . ', '; + } + $this->msgbg = rtrim($this->msgbg, ', ') . $this->eol; + } + + /* + //$jov1 = array( 'view1' => $aro, 'view2' => ''); + $jov2=array(); + foreach ($aro as $d => $ts) { + foreach ($ts as $t => $ft) { + $jov2['view2'][$ft][] = $d.$t; + //$ft=="1" && $t=="0000" ? $jov2['view2']["0"][] = $d."2400" : ''; + } + } + $this->msgbg .= print_r($jov2, true) . $this->eol; // 4devels + */ + + $this->joo = json_encode($aro); + // $this->msgbg .= $this->joo . $this->eol; // 4devels + // $this->msgbg .= print_r($aro, true) . $this->eol; // 4devels + $okko = (json_decode($this->joo, true) ? true : false); + if (!$okko) { + $this->msgbg .= 'ZAR0139D,json 4 duty KO crash' . $this->eol; + $this->msgfg .= 'ZAR0139D,json 4 duty KO crash' . $this->eol; + $this->error++; + } + return ; + } + + } diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index 4b4929c65..822b18308 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -16,8 +16,8 @@ class Bookmarks extends \Zotlabs\Web\Controller { nav_set_selected('Bookmarks'); - $item_id = intval($_REQUEST['item']); - $burl = trim($_REQUEST['burl']); + $item_id = (isset($_REQUEST['item']) ? $_REQUEST['item'] : false); + $burl = (isset($_REQUEST['burl']) ? trim($_REQUEST['burl']) : ''); if(! $item_id) return; @@ -38,7 +38,7 @@ class Bookmarks extends \Zotlabs\Web\Controller { $item = $i[0]; - $terms = get_terms_oftype($item['term'],TERM_BOOKMARK); + $terms = (x($item, 'term') ? get_terms_oftype($item['term'],TERM_BOOKMARK) : false); if($terms) { require_once('include/bookmarks.php'); diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 65dba927b..329150424 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -19,45 +19,45 @@ class Cal extends Controller { if(observer_prohibited()) { return; } - + if(argc() > 1) { $nick = argv(1); - + profile_load($nick); - + $channelx = channelx_by_nick($nick); - + if(! $channelx) { notice( t('Channel not found.') . EOL); return; } - + App::$data['channel'] = $channelx; - + $observer = App::get_observer(); App::$data['observer'] = $observer; - + head_set_icon(App::$data['channel']['xchan_photo_s']); - + App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ; - + } - + return; } - - - + + + function get() { - + if(observer_prohibited()) { return; } - + $channel = App::$data['channel']; // since we don't currently have an event permission - use the stream permission - + if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) { notice( t('Permissions denied.') . EOL); return; @@ -76,10 +76,10 @@ class Cal extends Controller { if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts') || App::$profile['hide_friends']) $sql_extra .= " and etype != 'birthday' "; - + $first_day = feature_enabled($channel['channel_id'], 'cal_first_day'); $first_day = (($first_day) ? $first_day : 0); - + $start = ''; $finish = ''; @@ -87,7 +87,7 @@ class Cal extends Controller { if (x($_GET,'start')) $start = $_GET['start']; if (x($_GET,'end')) $finish = $_GET['end']; } - + $start = datetime_convert('UTC','UTC',$start); $finish = datetime_convert('UTC','UTC',$finish); $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start); @@ -107,10 +107,10 @@ class Cal extends Controller { // Noting this for now - it will need to be fixed here and in Friendica. // Ultimately the finish date shouldn't be involved in the query. $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id - from event left join item on event.event_hash = item.resource_id - where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid - AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' ) - OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )) + from event left join item on event.event_hash = item.resource_id + where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid + AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' ) + OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )) $sql_extra", intval($channel['channel_id']), dbesc($start), @@ -119,7 +119,7 @@ class Cal extends Controller { dbesc($adjust_finish) ); } - + if($r) { xchan_query($r); $r = fetch_post_tags($r,true); @@ -127,20 +127,16 @@ class Cal extends Controller { } $events = []; - + if($r) { foreach($r as $rr) { - $tz = get_iconfig($rr, 'event', 'timezone'); - if(! $tz) - $tz = 'UTC'; - - $start = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c')); + $start = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c')); if ($rr['nofinish']){ $end = null; } else { - $end = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c')); + $end = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c')); } $html = ''; @@ -149,6 +145,10 @@ class Cal extends Controller { $html = format_event_html($rr); } + $tz = get_iconfig($rr, 'event', 'timezone'); + if(! $tz) + $tz = 'UTC'; + $events[] = array( 'calendar_id' => 'channel_calendar', 'rw' => true, @@ -178,7 +178,7 @@ class Cal extends Controller { echo json_encode($events); killme(); } - + if (x($_GET,'id')) { $o = replace_macros(get_markup_template("cal_event.tpl"), [ '$events' => $events @@ -210,7 +210,7 @@ class Cal extends Controller { ]); return $o; - + } - + } diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index fe697a526..e26cdd072 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -135,7 +135,7 @@ class Cdav extends Controller { $auth = new \Zotlabs\Storage\BasicAuth(); $auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'CalDAV/CardDAV'); - if (local_channel()) { + if(local_channel()) { logger('loggedin'); @@ -153,9 +153,9 @@ class Cdav extends Controller { $auth->observer = $channel['channel_hash']; $principalUri = 'principals/' . $channel['channel_address']; - if(!cdav_principal($principalUri)) { + if(! cdav_principal($principalUri)) { $this->activate($pdo, $channel); - if(!cdav_principal($principalUri)) { + if(! cdav_principal($principalUri)) { return; } } @@ -168,21 +168,24 @@ class Cdav extends Controller { if($httpmethod === 'PUT' || $httpmethod === 'DELETE') { + $channel = channelx_by_nick(argv(2)); + $principalUri = 'principals/' . $channel['channel_address']; $httpuri = $_SERVER['REQUEST_URI']; logger("debug: method: " . $httpmethod, LOGGER_DEBUG); logger("debug: uri: " . $httpuri, LOGGER_DEBUG); - if(strpos($httpuri, 'cdav/addressbooks')) { + if(strpos($httpuri, 'cdav/addressbooks') !== false) { $sync = 'addressbook'; $cdavtable = 'addressbooks'; } - elseif(strpos($httpuri, 'cdav/calendars')) { + elseif(strpos($httpuri, 'cdav/calendars') !== false) { $sync = 'calendar'; $cdavtable = 'calendarinstances'; } - else + else { $sync = false; + } if($sync) { @@ -191,14 +194,13 @@ class Cdav extends Controller { logger("debug: body: " . $httpbody, LOGGER_DEBUG); - if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $cdavtable)) { + if($x = get_cdav_id($principalUri, argv(3), $cdavtable)) { $cdavdata = $this->get_cdav_data($x['id'], $cdavtable); - $etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false); // delete - if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag) + if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag) { Libsync::build_sync_packet($channel['channel_id'], [ $sync => [ 'action' => 'delete_card', @@ -206,18 +208,18 @@ class Cdav extends Controller { 'carduri' => $uri ] ]); + } else { - if($etag) { + if($etag && $cdavdata['etag'] !== $etag) { // update - if($cdavdata['etag'] !== $etag) - Libsync::build_sync_packet($channel['channel_id'], [ - $sync => [ - 'action' => 'update_card', - 'uri' => $cdavdata['uri'], - 'carduri' => $uri, - 'card' => $httpbody - ] - ]); + Libsync::build_sync_packet($channel['channel_id'], [ + $sync => [ + 'action' => 'update_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri, + 'card' => $httpbody + ] + ]); } else { // new @@ -235,7 +237,6 @@ class Cdav extends Controller { } } - $principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo); $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); $caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); @@ -268,7 +269,7 @@ class Cdav extends Controller { // Plugins $server->addPlugin(new \Sabre\DAV\Auth\Plugin($auth)); - //$server->addPlugin(new \Sabre\DAV\Browser\Plugin()); + // $server->addPlugin(new \Sabre\DAV\Browser\Plugin()); $server->addPlugin(new \Sabre\DAV\Sync\Plugin()); $server->addPlugin(new \Sabre\DAV\Sharing\Plugin()); $server->addPlugin(new \Sabre\DAVACL\Plugin()); @@ -276,7 +277,7 @@ class Cdav extends Controller { // CalDAV plugins $server->addPlugin(new \Sabre\CalDAV\Plugin()); $server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); - //$server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); + // $server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); $server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); // CardDAV plugins diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 5cf24615d..a7deb4f6b 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -27,7 +27,7 @@ class Channel extends Controller { function init() { - if (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0) + if (array_key_exists('search', $_GET) && (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)) goaway(z_root() . '/search?f=&search=' . $_GET['search']); $which = null; @@ -155,7 +155,7 @@ class Channel extends Controller { intval($channel['channel_id']) ); - opengraph_add_meta($r ? $r[0] : [], $channel); + opengraph_add_meta((isset($r) && count($r) ? $r[0] : []), $channel); } function get($update = 0, $load = false) { @@ -168,7 +168,7 @@ class Channel extends Controller { if (strpos($mid, 'b64.') === 0) $decoded = @base64url_decode(substr($mid, 4)); - if ($decoded) + if (isset($decoded)) $mid = $decoded; $datequery = ((x($_GET, 'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); @@ -308,9 +308,9 @@ class Channel extends Controller { if (($update) && (!$load)) { if ($mid) { - $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update + $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal_update AND item_wall = 1 $simple_update $sql_extra limit 1", - dbesc($mid . '%'), + dbesc($mid), intval(App::$profile['profile_uid']) ); } @@ -328,6 +328,7 @@ class Channel extends Controller { } else { + $sql_extra2 = ''; if (x($category)) { $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY)); } @@ -355,9 +356,9 @@ class Channel extends Controller { if ($noscript_content || $load) { if ($mid) { - $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal + $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal AND item_wall = 1 $sql_extra limit 1", - dbesc($mid . '%'), + dbesc($mid), intval(App::$profile['profile_uid']) ); if (!$r) { @@ -419,7 +420,7 @@ class Channel extends Controller { if ((!$update) && (!$load)) { - if ($decoded) + if (isset($decoded)) $mid = 'b64.' . base64url_encode($mid); // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, @@ -485,7 +486,7 @@ class Channel extends Controller { $o .= conversation($items, $mode, $update, $page_mode); - if ($mid && $items[0]['title']) + if ($mid && count($items) > 0 && isset($items[0]['title'])) App::$page['title'] = $items[0]['title'] . " - " . App::$page['title']; } diff --git a/Zotlabs/Module/Channel_calendar.php b/Zotlabs/Module/Channel_calendar.php index ac1545644..26c6aaf40 100644 --- a/Zotlabs/Module/Channel_calendar.php +++ b/Zotlabs/Module/Channel_calendar.php @@ -116,7 +116,7 @@ class Channel_calendar extends Controller { if ($results) { // Set permissions based on tag replacements - set_linkified_perms($results, $str_contact_allow, $str_group_allow, $uid, false, $private); + set_linkified_perms($results, $str_contact_allow, $str_group_allow, $uid, $private); foreach ($results as $result) { $success = $result['success']; diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php index 3d1b97980..6ff95b5cf 100644 --- a/Zotlabs/Module/Cloud.php +++ b/Zotlabs/Module/Cloud.php @@ -123,7 +123,8 @@ class Cloud extends Controller { notice( t('Permission denied') . EOL); } elseif($err instanceof \Sabre\DAV\Exception\NotImplemented) { - notice( t('Please refresh page') . EOL); + // notice( t('Please refresh page') . EOL); + goaway(z_root() . '/' . \App::$query_string); } else { notice( t('Unknown error') . EOL); diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php index 31da42035..b934cb963 100644 --- a/Zotlabs/Module/Connect.php +++ b/Zotlabs/Module/Connect.php @@ -18,11 +18,11 @@ class Connect extends Controller { App::$error = 404; return; } - + $r = q("select * from channel where channel_address = '%s' limit 1", dbesc($which) ); - + if($r) App::$data['channel'] = $r[0]; @@ -30,36 +30,36 @@ class Connect extends Controller { profile_load($which,''); } - + function post() { - + if(! array_key_exists('channel', App::$data)) return; $channel_id = App::$data['channel']['channel_id']; $edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false); - + if($edit) { $has_premium = ((App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0); $premium = (($_POST['premium']) ? intval($_POST['premium']) : 0); $text = escape_tags($_POST['text']); - + if($has_premium != $premium) { $r = q("update channel set channel_pageflags = ( channel_pageflags %s %d ) where channel_id = %d", db_getfunc('^'), intval(PAGE_PREMIUM), - intval(local_channel()) + intval(local_channel()) ); - + \Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',$channel_id)); } set_pconfig($channel_id,'system','selltext',$text); // reload the page completely to get fresh data goaway(z_root() . '/' . App::$query_string); - + } - + $url = ''; $observer = App::get_observer(); if(($observer) && ($_POST['submit'] === t('Continue'))) { @@ -70,18 +70,18 @@ class Connect extends Controller { dbesc($observer['xchan_hash']) ); if($r) - $url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(App::$data['channel'])); + $url = $r[0]['hubloc_url'] . '/follow?f=&interactive=1&url=' . urlencode(channel_reddress(App::$data['channel'])); } } if($url) goaway($url . '&confirm=1'); else notice('Unable to connect to your home hub location.'); - + } - - - + + + function get() { if(! array_key_exists('channel', App::$data)) @@ -90,11 +90,11 @@ class Connect extends Controller { $channel_id = App::$data['channel']['channel_id']; $edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false); - + $text = get_pconfig($channel_id,'system','selltext'); - + if($edit) { - + $o = replace_macros(get_markup_template('sellpage_edit.tpl'),array( '$header' => t('Premium Channel Setup'), '$address' => App::$data['channel']['channel_address'], @@ -105,36 +105,36 @@ class Connect extends Controller { '$lbl2' => t('Potential connections will then see the following text before proceeding:'), '$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'), '$submit' => t('Submit'), - - + + )); return $o; } else { if(! $text) $text = t('(No specific instructions have been provided by the channel owner.)'); - + $submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array( - '$continue' => t('Continue'), + '$continue' => t('Continue'), '$address' => App::$data['channel']['channel_address'] )); - + $o = replace_macros(get_markup_template('sellpage_view.tpl'),array( '$header' => t('Restricted or Premium Channel'), '$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'), - '$text' => prepare_text($text), - + '$text' => prepare_text($text), + '$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'), '$submit' => $submit, - + )); - + $arr = array('channel' => App::$data['channel'],'observer' => App::get_observer(), 'sellpage' => $o, 'submit' => $submit); call_hooks('connect_premium', $arr); $o = $arr['sellpage']; - + } - + return $o; } } diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index 7295f3099..e1555fc2d 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -245,7 +245,7 @@ class Directory extends Controller { $profile_link = chanlink_url($rr['url']); $pdesc = (($rr['description']) ? $rr['description'] . '<br />' : ''); - $connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : ''); + $connect_link = ((local_channel()) ? z_root() . '/follow?f=&interactive=1&url=' . urlencode($rr['address']) : ''); // Checking status is disabled ATM until someone checks the performance impact more carefully //$online = remote_online_status($rr['address']); diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index 15dfb0dc9..e6caa9906 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -97,8 +97,8 @@ class Display extends \Zotlabs\Web\Controller { if($decoded) $item_hash = $decoded; - $r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid like '%s' limit 1", - dbesc($item_hash . '%') + $r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1", + dbesc($item_hash) ); if($r) { @@ -247,69 +247,62 @@ class Display extends \Zotlabs\Web\Controller { if($noscript_content || $load) { - $r = null; - require_once('include/channel.php'); $sys = get_sys_channel(); - $sysid = $sys['channel_id']; + // in case somebody turned off public access to sys channel content using permissions + // make that content unsearchable by ensuring the owner uid can't match + $sys_id = perm_is_allowed($sys['channel_id'], $observer_hash, 'view_stream') ? $sys['channel_id'] : 0; + + $r = null; if(local_channel()) { - $r = q("SELECT item.id as item_id from item WHERE uid = %d and mid = '%s' $item_normal limit 1", + $r = q("SELECT item.id AS item_id FROM item WHERE uid = %d AND mid = '%s' $item_normal LIMIT 1", intval(local_channel()), dbesc($target_item['parent_mid']) ); } - if($r === null) { - // in case somebody turned off public access to sys channel content using permissions - // make that content unsearchable by ensuring the owner uid can't match - - if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) - $sysid = 0; - - $r = q("SELECT item.id as item_id from item + if(!$r) { + $r = q("SELECT item.id AS item_id FROM item WHERE ((mid = '%s' - AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' + AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item_private = 0 ) - and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) + AND uid IN ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) OR uid = %d ))) OR (mid = '%s' $sql_extra )) $item_normal limit 1", dbesc($target_item['parent_mid']), - intval($sysid), + intval($sys_id), dbesc($target_item['parent_mid']) ); } } elseif($update && !$load) { - $r = null; - require_once('include/channel.php'); $sys = get_sys_channel(); - $sysid = $sys['channel_id']; + // in case somebody turned off public access to sys channel content using permissions + // make that content unsearchable by ensuring the owner uid can't match + $sys_id = perm_is_allowed($sys['channel_id'], $observer_hash, 'view_stream') ? $sys['channel_id'] : 0; + + $r = null; if(local_channel()) { $r = q("SELECT item.parent AS item_id from item WHERE uid = %d - and parent_mid = '%s' + AND parent_mid = '%s' $item_normal_update $simple_update - limit 1", + LIMIT 1", intval(local_channel()), dbesc($target_item['parent_mid']) ); } - if($r === null) { - // in case somebody turned off public access to sys channel content using permissions - // make that content unsearchable by ensuring the owner_xchan can't match - - if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) - $sysid = 0; + if(! $r) { $r = q("SELECT item.id as item_id from item WHERE ((parent_mid = '%s' - AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' + AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item_private = 0 ) and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) OR uid = %d ))) OR @@ -317,14 +310,14 @@ class Display extends \Zotlabs\Web\Controller { $item_normal limit 1", dbesc($target_item['parent_mid']), - intval($sysid), + intval($sys_id), dbesc($target_item['parent_mid']) ); } } else { - $r = array(); + $r = []; } if($r) { @@ -332,7 +325,7 @@ class Display extends \Zotlabs\Web\Controller { if($parents_str) { $items = q("SELECT item.*, item.id AS item_id FROM item - WHERE parent in ( %s ) $item_normal ", + WHERE parent in ( %s ) $sql_extra $item_normal ", dbesc($parents_str) ); xchan_query($items); diff --git a/Zotlabs/Module/Follow.php b/Zotlabs/Module/Follow.php index 11febd8fc..4fe20f56b 100644 --- a/Zotlabs/Module/Follow.php +++ b/Zotlabs/Module/Follow.php @@ -14,7 +14,7 @@ use Zotlabs\Daemon\Master; class Follow extends Controller { function init() { - + if (ActivityStreams::is_as_request() && argc() == 2) { $abook_id = intval(argv(1)); @@ -73,11 +73,11 @@ class Follow extends Controller { $url = notags(trim(punify($_REQUEST['url']))); $return_url = $_SESSION['return_url']; $confirm = intval($_REQUEST['confirm']); - $interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1); + $interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1); $channel = App::get_channel(); $result = Connect::connect($channel,$url); - + if ($result['success'] == false) { if ($result['message']) { notice($result['message']); @@ -89,9 +89,9 @@ class Follow extends Controller { json_return_and_die($result); } } - + info( t('Connection added.') . EOL); - + $clone = array(); foreach ($result['abook'] as $k => $v) { if (strpos($k,'abook_') === 0) { @@ -101,30 +101,30 @@ class Follow extends Controller { unset($clone['abook_id']); unset($clone['abook_account']); unset($clone['abook_channel']); - + $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); if ($abconfig) { $clone['abconfig'] = $abconfig; } Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true); - + $can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream'); - + // If we can view their stream, pull in some posts - + if (($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) { Master::Summon([ 'Onepoll', $result['abook']['abook_id'] ]); } - + if ($interactive) { goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1'); } else { json_return_and_die([ 'success' => true ]); } - + } - + function get() { if (! local_channel()) { return login(); diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 4c2067299..a2c4100ad 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -41,7 +41,7 @@ class Hq extends \Zotlabs\Web\Controller { if(argc() > 1 && argv(1) !== 'load') { $item_hash = argv(1); } - + if($_REQUEST['mid']) $item_hash = $_REQUEST['mid']; @@ -49,9 +49,9 @@ class Hq extends \Zotlabs\Web\Controller { $item_normal_update = item_normal_update(); if(! $item_hash) { - $r = q("SELECT mid FROM item + $r = q("SELECT mid FROM item WHERE uid = %d $item_normal - AND mid = parent_mid + AND mid = parent_mid ORDER BY created DESC LIMIT 1", intval(local_channel()) ); @@ -71,10 +71,10 @@ class Hq extends \Zotlabs\Web\Controller { $target_item = null; - $r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid like '%s' limit 1", - dbesc($item_hash . '%') + $r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid = '%s' limit 1", + dbesc($item_hash) ); - + if($r) { $target_item = $r[0]; } @@ -83,7 +83,7 @@ class Hq extends \Zotlabs\Web\Controller { if($target_item['item_blocked'] == ITEM_MODERATED) { goaway(z_root() . '/moderate/' . $target_item['id']); } - + $simple_update = ''; if($update && $_SESSION['loadtime']) $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; @@ -94,16 +94,16 @@ class Hq extends \Zotlabs\Web\Controller { $sys_item = false; } - + if(! $update) { $channel = \App::get_channel(); $channel_acl = [ - 'allow_cid' => $channel['channel_allow_cid'], - 'allow_gid' => $channel['channel_allow_gid'], - 'deny_cid' => $channel['channel_deny_cid'], + 'allow_cid' => $channel['channel_allow_cid'], + 'allow_gid' => $channel['channel_allow_gid'], + 'deny_cid' => $channel['channel_deny_cid'], 'deny_gid' => $channel['channel_deny_gid'] - ]; + ]; $x = [ 'is_owner' => true, @@ -143,7 +143,7 @@ class Hq extends \Zotlabs\Web\Controller { // if the target item is not a post (eg a like) we want to address its thread parent //$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']); $mid = $target_item['mid']; - // if we got a decoded hash we must encode it again before handing to javascript + // if we got a decoded hash we must encode it again before handing to javascript if($decoded) $mid = 'b64.' . base64url_encode($mid); } @@ -154,7 +154,7 @@ class Hq extends \Zotlabs\Web\Controller { $o .= '<div id="live-hq"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . local_channel() . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n"; - + \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[ '$baseurl' => z_root(), '$pgtype' => 'hq', @@ -241,14 +241,14 @@ class Hq extends \Zotlabs\Web\Controller { else { $r = []; } - + if($r) { - $items = q("SELECT item.*, item.id AS item_id + $items = q("SELECT item.*, item.id AS item_id FROM item WHERE parent = '%s' $item_normal ", dbesc($r[0]['item_id']) ); - + xchan_query($items,true,(($sys_item) ? local_channel() : 0)); $items = fetch_post_tags($items,true); $items = conv_sort($items,'created'); diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 6359da54c..34f1858fd 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -6,7 +6,7 @@ use Zotlabs\Lib\Apps; use Zotlabs\Web\Controller; /** - * module: invite.php + * module: invitexv2.php * * send email invitations to join social network * @@ -15,91 +15,291 @@ use Zotlabs\Web\Controller; class Invite extends Controller { + /** + * While coding this, I want to introduce a system of qualified messages and notifications. + * Each message consists of a 3 letter prefix, a 4 digit number and a one letter suffix (PREnnnnS). + * The spirit about is not from me, but many decades used by IBM inc. in devel with best success. + * + * The system prefix, used uppercase as system message id, lowercase as css and js prefix (classes, ids etc). + * Usually not used as self::MYP, but placed in the code dominant enough for easy to find. + * + * Concrete here: + * The prefix indicates Z for the Zlabs(core), A for Account stuff, I for Invite. + * The numbers scope will be 00xx within/for templates, 01xx for get, 02xx for post functions. + * Message qualification ends with a uppercase suffix, where + * I=Info(only), + * W=Warning(more then info and less then error), + * E=Error, + * F=Fatal(for unexpected errors). + * Btw, in case of using fail2ban, a scan of messages going to log is very much more with ease, + * esspecially in multi language driven systems where messages vary. + * + * @author Hilmar Runge + * @version 2.0.0 + * @since 2020-01-20 + * + */ + + const MYP = 'ZAI'; + const VERSION = '2.0.0'; + function post() { - - if(! local_channel()) { - notice( t('Permission denied.') . EOL); + + // zai02 + + if (! local_channel()) { + notice( 'ZAI0201E,' .t('Permission denied.') . EOL); return; } - if(! Apps::system_app_installed(local_channel(), 'Invite')) { + if (! Apps::system_app_installed(local_channel(), 'Invite')) { + notice( 'ZAI0202E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL); return; } - + check_form_security_token_redirectOnErr('/', 'send_invite'); - - $max_invites = intval(get_config('system','max_invites')); - if(! $max_invites) - $max_invites = 50; - - $current_invites = intval(get_pconfig(local_channel(),'system','sent_invites')); - if($current_invites > $max_invites) { - notice( t('Total invitation limit exceeded.') . EOL); + + $ok = $ko = 0; + $feedbk = ''; + $isajax = is_ajax(); + $eol = $isajax ? "\n" : EOL; + $policy = intval(get_config('system','register_policy')); + if ($policy == REGISTER_CLOSED) { + notice( 'ZAI0212E,' . t('Register is closed') . ')' . EOL); return; - }; - - - $recips = ((x($_POST,'recipients')) ? explode("\n",$_POST['recipients']) : array()); - $message = ((x($_POST,'message')) ? notags(trim($_POST['message'])) : ''); - - $total = 0; - - if(get_config('system','invitation_only')) { - $invonly = true; - $x = get_pconfig(local_channel(),'system','invites_remaining'); - if((! $x) && (! is_site_admin())) - return; - } - - foreach($recips as $recip) { - - $recip = trim($recip); - if(! $recip) - continue; - - if(! validate_email($recip)) { - notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL); - continue; + } + if ($policy == REGISTER_OPEN) + $flags = 0; + elseif ($policy == REGISTER_APPROVE) + $flags = ACCOUNT_PENDING; + $flags = ($flags | intval(get_config('system','verify_email'))); + + // how many max recipients in one mail submit + $maxto = get_config('system','invitation_max_recipients', 'na'); + If (is_site_admin()) { + // set, if admin is operator, default to 12 + if ($maxto === 'na') set_config('system','invitation_max_recipients', 12); + } + $maxto = ($maxto === 'na') ? 12 : $maxto; + + // language code current for the invitation + $lcc = x($_POST['zailcc']) && preg_match('/[a-z\-]{2,5}/', $_POST['zailcc']) + ? $_POST['zailcc'] + : ''; + + // expiration duration amount quantity, in case of doubts defaults 2 + $durn = x($_POST['zaiexpiren']) && preg_match('/[0-9]{1,2}/', $_POST['zaiexpiren']) + ? trim(intval($_POST['zaiexpiren'])) + : '2'; + !$durn ? $durn = 2 : ''; + + // expiration duration unit 1st letter (day, weeks, months, years), defaults days + $durq = x($_POST['zaiexpire']) && preg_match('/[ihd]{1,1}/', $_POST['zaiexpire']) + ? $_POST['zaiexpire'] + : 'd'; + + $dur = self::calcdue($durn.$durq); + $due = t('Note, the invitation code is valid up to') . ' ' . $dur['due']; + + if ($isajax) { + $feedbk .= 'ZAI0207I ' . $due . $eol; + } + + // take the received email addresses and discart duplicates + $recips = array_filter( array_unique( preg_replace('/^\s*$/', '', + ((x($_POST,'zaito')) ? explode( "\n",$_POST['zaito']) : array() ) ))); + + $havto = count($recips); + + if ( $havto > $maxto) { + $feedbk .= 'ZAI0210E ' . sprintf( t('Too many recipients for one invitation (max %d)'), $maxto) . $eol; + $ko++; + + } elseif ( $havto == 0 ) { + $feedbk .= 'ZAI0211E ' . t('No recipients for this invitation') . $eol; + $ko++; + + } else { + + // each email address + foreach($recips as $n => $recip) { + + // if empty ignore + $recip = $recips[$n] = trim($recip); + if(! $recip) continue; + + // see if we have an email address who@domain.tld + if (!preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $recip)) { + $feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol; + $ko++; + continue; + } + if(! validate_email($recip)) { + $feedbk .= 'ZAI0204E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a real email address'), $recip) . $eol; + $ko++; + continue; + } + + // do we accept the email (not black listed) + if(! allowed_email($recip)) { + $feedbk .= 'ZAI0205E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not allowed email address'), $recip) . $eol; + $ko++; + continue; + } + + // is the email address just in use for account or registered before + $r = q("SELECT account_email AS em FROM account WHERE account_email = '%s'" + . " UNION " + ."SELECT reg_email AS em FROM register WHERE reg_vital = 1 AND reg_email = '%s' LIMIT 1;", + dbesc($recip), + dbesc($recip) + ); + if($r && $r[0]['em'] == $recip) { + $feedbk .= 'ZAI0206E ' . ($n+1) . ': ' . sprintf( t('(%s) : email address already in use'), $recip) . $eol; + $ko++; + continue; + } + + if ($isajax) { + // seems we have an email address acceptable + $feedbk .= 'ZAI0209I ' . ($n+1) . ': ' . sprintf( t('(%s) : Accepted email address'), $recip) . $eol; + } } - - else - $nmessage = $message; - - $account = App::get_account(); - - $res = z_mail( - [ + } + + if ($isajax) { + // we are not silent on the ajax road + echo json_encode(array('feedbk' => $feedbk, 'due' => $due)); + + // that mission is complete + killme(); + exit; + } + + // Total ?todo notice( t('Invitation limit exceeded. Please contact your site administrator.') . EOL); + + // any errors up to now in fg? + + + // down from here, only on the main road (no more ajax) + + // tell if sth is to tell + $feedbk ? notice($feedbk) . $eol : ''; + + if ($ko > 0) return; + + // the personal mailtext + $mailtext = ((x($_POST,'zaitxt')) ? notags(trim($_POST['zaitxt'])) : ''); + + // to log in db + $reonar = json_decode( ((x($_POST,'zaireon')) ? notags(trim($_POST['zaireon'])) : ''), TRUE, 8) ; + + // me, the invitor + $account = App::get_account(); + $reonar['from'] = $account['account_email']; + $reonar['date'] = datetime_convert(); + $reonar['fromip'] = $_SERVER['REMOTE_ADDR']; + + // who is the invitor on + $inby = local_channel(); + + $ok = $ko = 0; + + // send the mail(s) + foreach($recips as $n => $recip) { + + $reonar['due'] = $due; + $reonar['to'] = $recip; + $reonar['txtpersonal'] = $mailtext; + + // generate an invide code to store and pm + $invite_code = autoname(8) . rand(1000,9999); + + // again the final localized templates $reonar['subject'] $reonar['lang'] $reonar['tpl'] + + // save current operators lc and take the desired to mail + push_lang($reonar['lang']); + // resolve + $tx = replace_macros(get_intltext_template('invite.'.$reonar['tpl'].'.tpl'), + array( + '$projectname' => t('$Projectname'), + '$invite_code' => $invite_code, + '$invite_where' => z_root() . '/register', + '$invite_whereami' => str_replace('@', '@+', $reonar['whereami']), + '$invite_whoami' => z_root() . '/channel/' . $reonar['whoami'], + '$invite_anywhere' => z_root() . '/pubsites' + ) + ); + // restore lc to operator + pop_lang(); + + $reonar['txttemplate'] = $tx; + + // pm + $zem = z_mail( + [ 'toEmail' => $recip, 'fromName' => ' ', - 'fromEmail' => $account['account_email'], - 'messageSubject' => t('Please join us on $Projectname'), - 'textVersion' => $nmessage, + 'fromEmail' => $reonar['from'], + 'messageSubject' => $reonar['subject'], + 'textVersion' => ($mailtext ? $mailtext . "\n\n" : '') . $tx . "\n" . $due, ] ); - - if($res) { - $total ++; - $current_invites ++; - set_pconfig(local_channel(),'system','sent_invites',$current_invites); - if($current_invites > $max_invites) { - notice( t('Invitation limit exceeded. Please contact your site administrator.') . EOL); - return; - } - } - else { - notice( sprintf( t('%s : Message delivery failed.'), $recip) . EOL); + + if(!$zem) { + + $ko++; + $msg = 'ZAI0208E,' . sprintf( t('%s : Message delivery failed.'), $recip); + + } else { + + $ok++; + $msg = 'ZAI0208I ' . sprintf( t('To %s : Message delivery success.'), $recip); + + // if verify_email is the rule, email becomes a dId2 - NO + // $did2 = ($flags & ACCOUNT_UNVERIFIED) == ACCOUNT_UNVERIFIED ? $recip : ''; + + // always enforce verify email with invitations, thus email becomes a dId2 + $did2 = $recip; + $flags |= ACCOUNT_UNVERIFIED; + + // defaults vital, reg_pass + $r = q("INSERT INTO register (" + . "reg_flags,reg_didx,reg_did2,reg_hash,reg_created,reg_startup,reg_expires,reg_email,reg_byc,reg_uid,reg_atip,reg_lang,reg_stuff)" + . " VALUES ( %d, 'i', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s') ", + intval($flags), + dbesc($did2), + dbesc($invite_code), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($dur['due']), + dbesc($recip), + intval($inby), + intval($account['account_id']), + dbesc($reonar['fromip']), + dbesc($reonar['lang']), + dbesc(json_encode( array('reon' => $reonar) )) + ); } - + $msg .= ' (a' . $account['account_id'] . ', c' . $inby . ', from:' . $reonar['from'] . ')'; + zar_log( $msg); } - notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL); + + $ok + $ko > 0 + ? notice( 'ZAI0212I ' . sprintf( t('%1$d mail(s) sent, %2$d mail error(s)'), $ok, $ko) . EOL) + : ''; + //logger( print_r( $reonar, true) ); + return; } - - + + function get() { - + + // zai1 + if(! local_channel()) { - notice( t('Permission denied.') . EOL); + notice( 'ZAI0101E,' . t('Permission denied.') . EOL); return; } @@ -107,68 +307,267 @@ class Invite extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '<b>' . t('Invite App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Send email invitations to join this network'); + $o = 'ZAI0102E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL; return $o; } + if (! (get_config('system','invitation_also') || get_config('system','invitation_only')) ) { + $o = 'ZAI0103E,' . t('Invites not proposed by configuration') . '. '; + $o .= t('Contact the site admin'); + return $o; + } + + // invitation_by_user may still not configured, the default 'na' will tell this + // if configured, 0 disables invitations by users, other numbers are how many invites a user may propagate + $invuser = get_config('system','invitation_by_user', 'na'); + + // if the mortal user drives the invitation + If (! is_site_admin()) { + + // when not configured, 4 is the default + $invuser = ($invuser === 'na') ? 4 : $invuser; + + // a config value 0 disables invitation by users + if (!$invuser) { + $o = 'ZAI0104E, ' . t('Invites by users not enabled') . '. '; + return $o; + } + + if ($ihave >= $invuser) { + notice( 'ZAI0105W,' . t('You have no more invitations available') . EOL); + return ''; + } + + } else { + // general deity admin invite limit infinite (theoretical) + if ($invuser === 'na') set_config('system','invitation_by_user', 4); + // for display only + $invuser = '∞'; + } + + // xchan record of the page observer + // while quoting matters the user, the sending is associated with a channel (of the user) + // also the admin may and should decide, which channel will told to the public + $ob = App::get_observer(); + if(! $ob) + return 'ZAI0109F,' . t('Not on xchan') . EOL; + $whereami = $ob['xchan_addr']; + $channel = App::get_channel(); + $whoami = $channel['channel_address']; + + // to pass also to post() + $tao = 'tao.zai.whereami = ' . "'" . $whereami . "';\n" + . 'tao.zai.whoami = ' . "'" . $whoami . "';\n"; + + // expirations, duration interval + $dur = self::calcdue(); + $tao .= 'tao.zai.expire = { durn: ' . $dur['durn'] + . ', durq: ' . "'" . $dur['durq'] . "'" + . ', due: ' . "'" . $dur['due'] . "' };\n"; + + // to easy redisplay the empty form nav_set_selected('Invite'); - + + // inform about the count of invitations we have at all + $r = q("SELECT count(reg_id) as ct FROM register WHERE reg_vital = 1"); // where not admin TODO + $wehave = ($r ? $r[0]['ct'] : 0); + + // invites max for all users except admins + $invmaxau = intval(get_config('system','invitations_max_users')); + if(! $invmaxau) { + $invmaxau = 50; + if (is_site_admin()) { + set_config('system','invitations_max_users',intval($invmaxau)); + } + } + + if ($wehave > $invmaxau) { + if (! is_site_admin()) { + $feedbk .= 'ZAI0200E,' . t('All users invitation limit exceeded.') . $eol; + } + } + + // let see how many invites currently used by the user + $r = q("SELECT count(reg_id) AS n FROM register WHERE reg_vital = 1 AND reg_byc = %d", + intval(local_channel())); + $ihave = $r ? $r[0]['n'] : 0; + $tpl = get_markup_template('invite.tpl'); - $invonly = false; - - if(get_config('system','invitation_only')) { - $invonly = true; - $x = get_pconfig(local_channel(),'system','invites_remaining'); - if((! $x) && (! is_site_admin())) { - notice( t('You have no more invitations available') . EOL); - return ''; + + $inv_rabots = array( + 'i' => t('Minute(s)'), + 'h' => t('Hour(s)') , + 'd' => t('Day(s)') + ); + $inv_expire = replace_macros(get_markup_template('field_duration.qmc.tpl'), + array( + 'label' => t('Invitation expires after'), + 'qmc' => 'zai', + 'qmcid' => 'ZAI0014I', + 'field' => array( + 'name' => 'expire', + 'title' => t('duration up from now'), + 'value' => ($invexpire_n ? $invexpire_n : 2), + 'min' => '1', + 'max' => '99', + 'size' => '2', + 'default' => ($invexpire_u ? $invexpire_u : 'd') + ), + 'rabot' => $inv_rabots + ) + ); + + // let generate an invite code that here and never will be applied (only to fill displayed template) + // real invite codes become generated for each recipient when we store the new invitation(s) + // $invite_code = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 8) . rand(1000,9999); + // let take one descriptive for template (as said is never used) + $invite_code = 'INVITATE2020'; + + // what languages we use now + $lccmy = ((isset(App::$config['system']['language'])) ? App::$config['system']['language'] : 'en'); + // and all the localized templates belonging to invite + $tpls = glob('view/*/invite.*.tpl'); + + $tpla=$tplx=$tplxs=array(); + foreach ($tpls as $tpli) { + list( $nop, $l, $t ) = explode( '/', $tpli); + if ( preg_match('/\.subject/', $t) =='1' ) { + // indicate a subject tpl exists + $t=str_replace(array('invite.', '.subject', '.tpl'), '', $t); + $tplxs[$l][$t]=true; + continue; } + // collect unique template names cross all languages and + // tpla[language][]=template those available in each language + $tplx[] = $tpla[$l][] = str_replace( array('invite.', '.tpl'), '', $t); } - - if($invonly && ($x || is_site_admin())) { - $invite_code = autoname(8) . rand(1000,9999); - $nmessage = str_replace('$invite_code',$invite_code,$message); - - $r = q("INSERT INTO register (hash,created,uid,password,lang) VALUES ('%s', '%s',0,'','') ", - dbesc($invite_code), - dbesc(datetime_convert()) + + $langs = array_keys($tpla); + asort($langs); + + $tplx = array_unique($tplx); + asort($tplx); + + // prepare current language and the default standard template (causual) for js + // With and in js, I use a var 'tao' as a shortcut for top array object + // and also qualify the object with the prefix zai = tao.zai as my var used outsite functions + // can be unique within the overall included spaghette whirls + // one can say Im too lazy to write prototypes and just I can agree. + // tao simply applies the fact of using the same var as object and/or array in ja. + $tao.='tao.zai.lccmy = ' . "'" . $lccmy . "';\n" . 'tao.zai.itpl = ' . "'" . 'casual' . "';\n"; + + $lcclane=$tx=$tplin=''; + //$lccsym='<span class="fa zai_fa zai_lccsym"></span>'; // alt + $tplsym='<span class="fa zai_fa"></span>'; + + // I will uncomment for js console debug + // $tao.='tao.zai.debug = ' . "'" . json_encode($tplxs) . "';\n"; + + // running thru the localized templates (subjects and textmsgs) and bring them to tao + // lcc LanguageCountryCode, + // lcc2 is a 2 character and lcc5 a 5 character LanguageCountryCode + foreach($tpla as $l => $tn) { + + // restyle lc to iso getttext format to avoid errors in js, hilite the current + $lcc = str_replace('-', '_', $l); + $hi = ($l == $lccmy) ? ' zai_hi' : ''; + $lcc2 = strlen($l) == 2 ? ' zai_lcc2' : ''; + $lcc5 = strlen($l) == 5 ? ' zai_lcc5' : ''; + $lccg = ' zai_lccg' . substr( $l, 0, 2 ); + $lcclane + .= '<span class="fa zai_fa zai_lccsym' . $lcc2 . $lcc5 . $lccg . '"></span>' + . '<a href="javascript:;" class="zai_lcc' . $lcc2 . $lcc5 . $lccg . $hi . '">' . $lcc . '</a>'; + // textmsg + $tao .= 'tao.zai.t.' . $lcc . ' = {};' . "\n"; + // subject + $tao .= 'tao.zai.s.' . $lcc . ' = {};' . "\n"; + + // resolve localized templates and take intented lc for + foreach($tn as $t1) { + + // save current lc and take the desired + push_lang($l); + + // resolve + $tx = replace_macros(get_intltext_template('invite.'.$t1.'.tpl'), + array( + '$projectname' => t('$Projectname'), + '$invite_code' => $invite_code, + '$invite_where' => z_root() . '/register', + '$invite_whereami' => $whereami, + '$invite_whoami' => z_root() . '/channel/' . $whoami, + '$invite_anywhere' => z_root() . '/pubsites' + ) ); - - if(! is_site_admin()) { - $x --; - if($x >= 0) - set_pconfig(local_channel(),'system','invites_remaining',$x); - else - return; - } + + // a default subject if no associated exists + $ts=t('Invitation'); + if ( $tplxs[$l][$t1] ) + $ts = replace_macros(get_intltext_template('invite.'.$t1.'.subject.tpl'), + array( + '$projectname' => t('$Projectname'), + '$invite_loc' => get_config('system','sitename') + ) + ); + + // restore lc to current foreground + pop_lang(); + + // bring to tao as js like it + $tao .= 'tao.zai.t.' . $lcc . '.' . $t1 . " = '" . rawurlencode($tx) . "';\n"; + $tao .= 'tao.zai.s.' . $lcc . '.' . $t1 . " = '" . rawurlencode($ts) . "';\n"; } - - $ob = App::get_observer(); - if(! $ob) - return $o; - - $channel = App::get_channel(); - + } + + // hilite the current defauls just from the beginning + foreach ($tplx as $t1) { + $hi = ($t1 == 'casual') ? ' zai_hi' : ''; + $tplin .= $tplsym.'<a href="javascript:;" id="zai-' . $t1 + . '" class="invites'.$hi.'">' . $t1 . '</a>'; + } + + // fill the form for foreground $o = replace_macros($tpl, array( '$form_security_token' => get_form_security_token("send_invite"), + '$zai' => strtolower(self::MYP), + '$tao' => $tao, '$invite' => t('Send invitations'), - '$addr_text' => t('Enter email addresses, one per line:'), - '$msg_text' => t('Your message:'), - '$default_message' => t('Please join my community on $Projectname.') . "\r\n" . "\r\n" - . $linktxt - . (($invonly) ? "\r\n" . "\r\n" . t('You will need to supply this invitation code:') . " " . $invite_code . "\r\n" . "\r\n" : '') - . t('1. Register at any $Projectname location (they are all inter-connected)') - . "\r\n" . "\r\n" . z_root() . '/register' - . "\r\n" . "\r\n" . t('2. Enter my $Projectname network address into the site searchbar.') - . "\r\n" . "\r\n" . $ob['xchan_addr'] . ' (' . t('or visit') . " " . z_root() . '/channel/' . $channel['channel_address'] . ')' - . "\r\n" . "\r\n" - . t('3. Click [Connect]') - . "\r\n" . "\r\n" , + '$ihave' => 'ZAI0106I, ' . t('Invitations I am using') . ': ' . $ihave . ' / ' . $invuser, + '$wehave' => 'ZAI0107I, ' . t('Invitations we are using') . ': ' . $wehave . ' / ' . $invmaxau, + '$n10' => 'ZAI0010I', '$m10' => t('§ Note, the email(s) sent will be recorded in the system logs'), + '$n11' => 'ZAI0011I', '$m11' => t('Enter email addresses, one per line:'), + '$n12' => 'ZAI0012I', '$m12' => t('Your message:'), + '$n13' => 'ZAI0013I', '$m13' => t('Invite template'), + '$inv_expire' => $inv_expire, + '$subject_label' => t('Subject:'), + '$subject' => t('Invitation'), + '$lcclane' => $lcclane, + '$tplin' => $tplin, + '$standard_message' => '', + '$personal_message' => '', + '$personal_pointer' => t('Here you may enter personal notes to the recipient(s)'), + '$due' => t('Note, the invitation code is valid up to') . ' ' . $dur['due'], '$submit' => t('Submit') )); - + return $o; } - + + function calcdue($duri=false) { + // expirations, duration interval + if ($duri===false) + $duri = get_config('system','register_expire', '2d'); + if ( preg_match( '/^[0-9]{1,2}[ihdwmy]{1}$/', $duri ) ) { + $durq = substr($duri, -1); + $durn = substr($duri, 0, -1); + $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'), + (':'.$durq)) + )); + return array( 'durn' => $durn, 'durq' => $durq, 'due' => $due); + } + return false; + } } + diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index def3f76dd..ff52babf5 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -840,7 +840,7 @@ class Item extends Controller { if($results) { // Set permissions based on tag replacements - set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private); + set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item); foreach($results as $result) { $success = $result['success']; diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 8a1b51a18..a21095940 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -20,8 +20,10 @@ class Network extends \Zotlabs\Web\Controller { return; } - if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']) || strpos($_GET['search'], 'https://') === 0) - goaway(z_root() . '/search?f=&search=' . $_GET['search']); + $search = $_GET['search'] ?? ''; + + if(in_array(substr($search, 0, 1),[ '@', '!', '?']) || strpos($search, 'https://') === 0) + goaway(z_root() . '/search?f=&search=' . $search); if(count($_GET) < 2) { $network_options = get_pconfig(local_channel(),'system','network_page_default'); @@ -80,7 +82,7 @@ class Network extends \Zotlabs\Web\Controller { break; } - $search = (($_GET['search']) ? $_GET['search'] : ''); + $search = $_GET['search'] ?? ''; if($search) { if(strpos($search,'#') === 0) { $hashtags = substr($search,1); @@ -128,17 +130,19 @@ class Network extends \Zotlabs\Web\Controller { $pf = ((x($_GET,'pf')) ? $_GET['pf'] : ''); $unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : ''); - if (Apps::system_app_installed(local_channel(),'Affinity Tool')) { + if (Apps::system_app_installed(local_channel(),'Affinity Tool')) { $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); if ($affinity_locked) { - set_pconfig(local_channel(),'affinity','cmin',$cmin); - set_pconfig(local_channel(),'affinity','cmax',$cmax); + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); } - } + } if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen) $nouveau = true; + $cid_r = []; + if($cid) { $cid_r = q("SELECT abook.abook_xchan, xchan.xchan_addr, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s, xchan.xchan_pubforum from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1", intval($cid), @@ -453,6 +457,8 @@ class Network extends \Zotlabs\Web\Controller { if($update && $_SESSION['loadtime']) $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; + $items = []; + if($nouveau && $load) { // "New Item View" - show all items unthreaded in reverse created date order $items = q("SELECT item.*, item.id AS item_id, created FROM item diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 98aa480fe..84d492f8f 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -11,7 +11,7 @@ class New_channel extends \Zotlabs\Web\Controller { function init() { $cmd = ((argc() > 1) ? argv(1) : ''); - + if($cmd === 'autofill.json') { require_once('library/urlify/URLify.php'); $result = array('error' => false, 'message' => ''); @@ -20,14 +20,14 @@ class New_channel extends \Zotlabs\Web\Controller { $x = false; if(get_config('system','unicode_usernames')) { - $x = punify(mb_strtolower($n)); + $x = punify(mb_strtolower($n)); } if((! $x) || strlen($x) > 64) $x = strtolower(\URLify::transliterate($n)); - + $test = array(); - + // first name if(strpos($x,' ')) $test[] = legal_webbie(substr($x,0,strpos($x,' '))); @@ -44,19 +44,19 @@ class New_channel extends \Zotlabs\Web\Controller { json_return_and_die(check_webbie($test)); } - + if($cmd === 'checkaddr.json') { require_once('library/urlify/URLify.php'); $result = array('error' => false, 'message' => ''); $n = trim($_REQUEST['nick']); if(! $n) { - $n = trim($_REQUEST['name']); + $n = trim($_REQUEST['name']); } $x = false; if(get_config('system','unicode_usernames')) { - $x = punify(mb_strtolower($n)); + $x = punify(mb_strtolower($n)); } if((! $x) || strlen($x) > 64) @@ -64,7 +64,7 @@ class New_channel extends \Zotlabs\Web\Controller { $test = array(); - + // first name if(strpos($x,' ')) $test[] = legal_webbie(substr($x,0,strpos($x,' '))); @@ -80,57 +80,57 @@ class New_channel extends \Zotlabs\Web\Controller { $test[] = $n; $test[] = $n . mt_rand(1000,9999); } - + for($y = 0; $y < 100; $y ++) $test[] = 'id' . mt_rand(1000,9999); - + json_return_and_die(check_webbie($test)); } - - + + } - + function post() { - + $arr = $_POST; - + $acc = \App::get_account(); $arr['account_id'] = get_account_id(); - - // prevent execution by delegated channels as well as those not logged in. + + // prevent execution by delegated channels as well as those not logged in. // get_account_id() returns the account_id from the session. But \App::$account - // may point to the original authenticated account. - + // may point to the original authenticated account. + if((! $acc) || ($acc['account_id'] != $arr['account_id'])) { notice( t('Permission denied.') . EOL ); return; } - + $result = create_identity($arr); - + if(! $result['success']) { notice($result['message']); return; } - + $newuid = $result['channel']['channel_id']; - + change_channel($result['channel']['channel_id']); - - $next_page = get_config('system', 'workflow_channel_next', 'profiles'); + + $next_page = get_config('system', 'workflow_channel_next', 'profiles'); goaway(z_root() . '/' . $next_page); - + } - + function get() { - + $acc = \App::get_account(); - + if((! $acc) || $acc['account_id'] != get_account_id()) { notice( t('Permission denied.') . EOL); return; } - + $default_role = ''; $aid = get_account_id(); if($aid) { @@ -140,7 +140,7 @@ class New_channel extends \Zotlabs\Web\Controller { if($r && (! intval($r[0]['total']))) { $default_role = get_config('system','default_permissions_role','social'); } - + $limit = account_service_class_fetch(get_account_id(),'total_identities'); $canadd = true; if($r && ($limit !== false)) { @@ -155,7 +155,7 @@ class New_channel extends \Zotlabs\Web\Controller { } $name_help = '<span id="name_help_loading" style="display:none">' . t('Loading') . '</span><span id="name_help_text">'; - $name_help .= (($default_role) + $name_help .= (($default_role) ? t('Your real name is recommended.') : t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"') ); @@ -176,10 +176,10 @@ class New_channel extends \Zotlabs\Web\Controller { $nickhub = '@' . \App::get_hostname(); $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*"); $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles); - + $o = replace_macros(get_markup_template('new_channel.tpl'), array( '$title' => t('Create a Channel'), - '$desc' => t('A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things.') , + '$desc' => t('A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things.') , '$label_import' => t('or <a href="import">import an existing channel</a> from another location.'), '$name' => $name, '$role' => $role, @@ -190,10 +190,10 @@ class New_channel extends \Zotlabs\Web\Controller { '$channel_usage_message' => $channel_usage_message, '$canadd' => $canadd )); - + return $o; - + } - - + + } diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index 75304161b..faad2fc52 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -11,24 +11,24 @@ require_once('include/security.php'); class Oep extends \Zotlabs\Web\Controller { function init() { - + logger('oep: ' . print_r($_REQUEST,true), LOGGER_DEBUG, LOG_INFO); - + $html = ((argc() > 1 && argv(1) === 'html') ? true : false); if($_REQUEST['url']) { $_REQUEST['url'] = strip_zids($_REQUEST['url']); $url = $_REQUEST['url']; } - + if(! $url) http_status_exit(404, 'Not found'); - + $maxwidth = $_REQUEST['maxwidth']; $maxheight = $_REQUEST['maxheight']; $format = $_REQUEST['format']; if($format && $format !== 'json') http_status_exit(501, 'Not implemented'); - + if(fnmatch('*/photos/*/album/*',$url)) $arr = $this->oep_album_reply($_REQUEST); elseif(fnmatch('*/photos/*/image/*',$url)) @@ -47,7 +47,7 @@ class Oep extends \Zotlabs\Web\Controller { $arr = $this->oep_cards_reply($_REQUEST); elseif(fnmatch('*/articles/*',$url)) $arr = $this->oep_articles_reply($_REQUEST); - + if($arr) { if($html) { if($arr['type'] === 'rich') { @@ -61,13 +61,13 @@ class Oep extends \Zotlabs\Web\Controller { } killme(); } - + http_status_exit(404,'Not found'); - + } - + function oep_display_reply($args) { - + $ret = array(); $url = $args['url']; $maxwidth = intval($args['maxwidth']); @@ -83,8 +83,8 @@ class Oep extends \Zotlabs\Web\Controller { $item_normal = item_normal(); - $p = q("select * from item where mid like '%s' limit 1", - dbesc($res . '%') + $p = q("select * from item where mid = '%s' limit 1", + dbesc($res) ); if(! $p) @@ -92,7 +92,7 @@ class Oep extends \Zotlabs\Web\Controller { $c = channelx_by_n($p[0]['uid']); - + if(! ($c && $res)) return; @@ -100,27 +100,27 @@ class Oep extends \Zotlabs\Web\Controller { return; $sql_extra = item_permissions_sql($c['channel_id']); - - $p = q("select * from item where mid like '%s' and uid = %d $sql_extra $item_normal limit 1", - dbesc($res . '%'), + + $p = q("select * from item where mid = '%s' and uid = %d $sql_extra $item_normal limit 1", + dbesc($res), intval($c['channel_id']) ); if(! $p) return; - + xchan_query($p,true); $p = fetch_post_tags($p,true); // This function can get tripped up if the item is already a reshare - // (the multiple share declarations do not parse cleanly if nested) + // (the multiple share declarations do not parse cleanly if nested) // So build a template with a known nonsense string as the content, and then // replace that known string with the actual rendered content, sending // each content layer through bbcode() separately. $x = '2eGriplW^*Jmf4'; - + $o = "[share author='".urlencode($p[0]['author']['xchan_name']). "' profile='".$p[0]['author']['xchan_url'] . "' avatar='".$p[0]['author']['xchan_photo_s']. @@ -131,29 +131,29 @@ class Oep extends \Zotlabs\Web\Controller { if($p[0]['title']) $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; - $o .= $x; + $o .= $x; $o .= "[/share]"; $o = bbcode($o); - + $o = str_replace($x,bbcode($p[0]['body']),$o); - + $ret['type'] = 'rich'; - + $w = (($maxwidth) ? $maxwidth : 640); $h = (($maxheight) ? $maxheight : intval($w * 2 / 3)); - + $ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>'; - + $ret['width'] = $w; $ret['height'] = $h; - + return $ret; - + } function oep_cards_reply($args) { - + $ret = []; $url = $args['url']; $maxwidth = intval($args['maxwidth']); @@ -164,7 +164,7 @@ class Oep extends \Zotlabs\Web\Controller { $res = $matches[3]; } if(! ($nick && $res)) - return $ret; + return $ret; $channel = channelx_by_nick($nick); @@ -187,8 +187,8 @@ class Oep extends \Zotlabs\Web\Controller { return $ret; } - $r = q("select * from item - where item.uid = %d and item_type = %d + $r = q("select * from item + where item.uid = %d and item_type = %d $sql_extra order by item.created desc", intval($channel['channel_id']), intval(ITEM_TYPE_CARD) @@ -208,7 +208,7 @@ class Oep extends \Zotlabs\Web\Controller { $x = '2eGriplW^*Jmf4'; - + $o = "[share author='".urlencode($p[0]['author']['xchan_name']). "' profile='".$p[0]['author']['xchan_url'] . "' avatar='".$p[0]['author']['xchan_photo_s']. @@ -219,28 +219,28 @@ class Oep extends \Zotlabs\Web\Controller { if($p[0]['title']) $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; - $o .= $x; + $o .= $x; $o .= "[/share]"; $o = bbcode($o); - + $o = str_replace($x,bbcode($p[0]['body']),$o); - + $ret['type'] = 'rich'; - + $w = (($maxwidth) ? $maxwidth : 640); $h = (($maxheight) ? $maxheight : intval($w * 2 / 3)); - + $ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>'; - + $ret['width'] = $w; $ret['height'] = $h; - + return $ret; - + } function oep_articles_reply($args) { - + $ret = []; $url = $args['url']; $maxwidth = intval($args['maxwidth']); @@ -251,7 +251,7 @@ class Oep extends \Zotlabs\Web\Controller { $res = $matches[3]; } if(! ($nick && $res)) - return $ret; + return $ret; $channel = channelx_by_nick($nick); @@ -273,8 +273,8 @@ class Oep extends \Zotlabs\Web\Controller { return $ret; } - $r = q("select * from item - where item.uid = %d and item_type = %d + $r = q("select * from item + where item.uid = %d and item_type = %d $sql_extra order by item.created desc", intval($channel['channel_id']), intval(ITEM_TYPE_ARTICLE) @@ -294,7 +294,7 @@ class Oep extends \Zotlabs\Web\Controller { $x = '2eGriplW^*Jmf4'; - + $o = "[share author='".urlencode($p[0]['author']['xchan_name']). "' profile='".$p[0]['author']['xchan_url'] . "' avatar='".$p[0]['author']['xchan_photo_s']. @@ -305,71 +305,71 @@ class Oep extends \Zotlabs\Web\Controller { if($p[0]['title']) $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; - $o .= $x; + $o .= $x; $o .= "[/share]"; $o = bbcode($o); - + $o = str_replace($x,bbcode($p[0]['body']),$o); - + $ret['type'] = 'rich'; - + $w = (($maxwidth) ? $maxwidth : 640); $h = (($maxheight) ? $maxheight : intval($w * 2 / 3)); - + $ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>'; - + $ret['width'] = $w; $ret['height'] = $h; - + return $ret; - + } - + function oep_mid_reply($args) { - + $ret = array(); $url = $args['url']; $maxwidth = intval($args['maxwidth']); $maxheight = intval($args['maxheight']); - + if(preg_match('#//(.*?)/(.*?)/(.*?)/(.*?)mid\=(.*?)(&|$)#',$url,$matches)) { $chn = $matches[3]; $res = $matches[5]; } - + if(! ($chn && $res)) return; $c = q("select * from channel where channel_address = '%s' limit 1", dbesc($chn) ); - + if(! $c) return; if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream')) return; - + $sql_extra = item_permissions_sql($c[0]['channel_id']); - + $p = q("select * from item where mid = '%s' and uid = %d $sql_extra limit 1", dbesc($res), intval($c[0]['channel_id']) ); if(! $p) return; - + xchan_query($p,true); $p = fetch_post_tags($p,true); // This function can get tripped up if the item is already a reshare - // (the multiple share declarations do not parse cleanly if nested) + // (the multiple share declarations do not parse cleanly if nested) // So build a template with a known nonsense string as the content, and then // replace that known string with the actual rendered content, sending // each content layer through bbcode() separately. $x = '2eGriplW^*Jmf4'; - + $o = "[share author='".urlencode($p[0]['author']['xchan_name']). "' profile='".$p[0]['author']['xchan_url'] . "' avatar='".$p[0]['author']['xchan_photo_s']. @@ -379,52 +379,52 @@ class Oep extends \Zotlabs\Web\Controller { "' message_id='".$p[0]['mid']."']"; if($p[0]['title']) $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; - $o .= $x; + $o .= $x; $o .= "[/share]"; $o = bbcode($o); - + $o = str_replace($x,bbcode($p[0]['body']),$o); $ret['type'] = 'rich'; - + $w = (($maxwidth) ? $maxwidth : 640); $h = (($maxheight) ? $maxheight : intval($w * 2 / 3)); - + $ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>'; - + $ret['width'] = $w; $ret['height'] = $h; - + return $ret; - + } - + function oep_profile_reply($args) { - - + + require_once('include/channel.php'); $url = $args['url']; - + if(preg_match('#//(.*?)/(.*?)/(.*?)(/|\?|&|$)#',$url,$matches)) { $chn = $matches[3]; } - + if(! $chn) return; - + $c = channelx_by_nick($chn); - + if(! $c) return; - - + + $maxwidth = intval($args['maxwidth']); $maxheight = intval($args['maxheight']); - + $width = 800; $height = 375; - + if($maxwidth) { $width = $maxwidth; $height = (375 / 800) * $width; @@ -434,59 +434,59 @@ class Oep extends \Zotlabs\Web\Controller { $width = (800 / 375) * $maxheight; $height = $maxheight; } - } + } $ret = array(); - + $ret['type'] = 'rich'; $ret['width'] = intval($width); $ret['height'] = intval($height); - + $ret['html'] = get_zcard_embed($c,get_observer_hash(),array('width' => $width, 'height' => $height)); - + return $ret; - + } - + function oep_album_reply($args) { - + $ret = array(); $url = $args['url']; $maxwidth = intval($args['maxwidth']); $maxheight = intval($args['maxheight']); - + if(preg_match('|//(.*?)/(.*?)/(.*?)/album/|',$url,$matches)) { $chn = $matches[3]; $res = basename($url); } - + if(! ($chn && $res)) return; $c = q("select * from channel where channel_address = '%s' limit 1", dbesc($chn) ); - + if(! $c) return; - + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files')) return; $sql_extra = permissions_sql($c[0]['channel_id']); - + $p = q("select resource_id from photo where album = '%s' and uid = %d and imgscale = 0 $sql_extra order by created desc limit 1", dbesc($res), intval($c[0]['channel_id']) ); if(! $p) return; - + $res = $p[0]['resource_id']; - + $r = q("select height, width, imgscale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by imgscale asc", intval($c[0]['channel_id']), dbesc($res) ); - + if($r) { foreach($r as $rr) { $foundres = false; @@ -494,62 +494,62 @@ class Oep extends \Zotlabs\Web\Controller { continue; if($maxwidth && $rr['width'] > $maxwidth) continue; - $foundres = true; + $foundres = true; break; } - + if($foundres) { $ret['type'] = 'link'; $ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['imgscale']; $ret['thumbnail_width'] = $rr['width']; $ret['thumbnail_height'] = $rr['height']; } - - + + } return $ret; - + } - - + + function oep_phototop_reply($args) { - + $ret = array(); $url = $args['url']; $maxwidth = intval($args['maxwidth']); $maxheight = intval($args['maxheight']); - + if(preg_match('|//(.*?)/(.*?)/(.*?)$|',$url,$matches)) { $chn = $matches[3]; } - + if(! $chn) return; $c = q("select * from channel where channel_address = '%s' limit 1", dbesc($chn) ); - + if(! $c) return; - + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files')) return; $sql_extra = permissions_sql($c[0]['channel_id']); - + $p = q("select resource_id from photo where uid = %d and imgscale = 0 $sql_extra order by created desc limit 1", intval($c[0]['channel_id']) ); if(! $p) return; - + $res = $p[0]['resource_id']; - + $r = q("select height, width, imgscale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by imgscale asc", intval($c[0]['channel_id']), dbesc($res) ); - + if($r) { foreach($r as $rr) { $foundres = false; @@ -557,42 +557,42 @@ class Oep extends \Zotlabs\Web\Controller { continue; if($maxwidth && $rr['width'] > $maxwidth) continue; - $foundres = true; + $foundres = true; break; } - + if($foundres) { $ret['type'] = 'link'; $ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['imgscale']; $ret['thumbnail_width'] = $rr['width']; $ret['thumbnail_height'] = $rr['height']; } - - + + } return $ret; - + } - - + + function oep_photo_reply($args) { - + $ret = array(); $url = $args['url']; $maxwidth = intval($args['maxwidth']); $maxheight = intval($args['maxheight']); - + if(preg_match('|//(.*?)/(.*?)/(.*?)/image/|',$url,$matches)) { $chn = $matches[3]; $res = basename($url); } - + if(! ($chn && $res)) return; $c = q("select * from channel where channel_address = '%s' limit 1", dbesc($chn) ); - + if(! $c) return; @@ -600,13 +600,13 @@ class Oep extends \Zotlabs\Web\Controller { return; $sql_extra = permissions_sql($c[0]['channel_id']); - - + + $r = q("select height, width, imgscale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by imgscale asc", intval($c[0]['channel_id']), dbesc($res) ); - + if($r) { foreach($r as $rr) { $foundres = false; @@ -614,20 +614,20 @@ class Oep extends \Zotlabs\Web\Controller { continue; if($maxwidth && $rr['width'] > $maxwidth) continue; - $foundres = true; + $foundres = true; break; } - + if($foundres) { $ret['type'] = 'link'; $ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['imgscale']; $ret['thumbnail_width'] = $rr['width']; $ret['thumbnail_height'] = $rr['height']; } - - + + } return $ret; - + } } diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index ee360dac5..87697f5a7 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -180,7 +180,7 @@ class Photo extends \Zotlabs\Web\Controller { $channel = channelx_by_n($r[0]['uid']); // Now we'll see if we can access the photo - $e = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1", + $e = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution) ); diff --git a/Zotlabs/Module/Regate.php b/Zotlabs/Module/Regate.php new file mode 100644 index 000000000..379195461 --- /dev/null +++ b/Zotlabs/Module/Regate.php @@ -0,0 +1,447 @@ +<?php + +namespace Zotlabs\Module; + +require_once('include/security.php'); + +/** + * + * @version 2.0.0 + * @author hilmar runge + * @since 2020-03-03 + * Check verification pin + * input field email address + * input field pin (told during register) + * check duty + * check startup and expire + * compare email address + * check pin + * limited tries to enter the correct pin/pass 2 handle via f2b + * on success create account and update register + * + */ + + define ( 'REGISTER_AGREED', 0x0020 ); + define ( 'REGISTER_DENIED', 0x0040 ); + +class Regate extends \Zotlabs\Web\Controller { + + const MYP = 'ZAR'; //ZAR1x + const VERSION = '2.0.0'; + + + function post() { + + check_form_security_token_redirectOnErr('/', 'regate'); + + if ( argc() > 1 ) { + $did2 = hex2bin( substr( argv(1), 0, -1) ); + $didx = substr( argv(1), -1 ); + } + + $msg = ''; + $nextpage = ''; + + if ($did2) { + + $nowhhmm = date('Hi'); + $day = date('N'); + $now = datetime_convert(); + $ip = $_SERVER['REMOTE_ADDR']; + + $isduty = zar_register_dutystate(); + + if (!$_SESSION['zar']['invite_in_progress'] && ($isduty['isduty'] !== false && $isduty['isduty'] != 1)) { + // normally, that should never happen here + // log suitable for fail2ban also + $logmsg = 'ZAR1230S Unexpected registration verification request for ' + . get_config('system','sitename') . ' arrived from § ' . $ip . ' §'; + zar_log($logmsg); + goaway(z_root()); + } + + // do we have a valid dId2 ? + if (($didx == 'a' && substr( $did2 , -2) == substr( base_convert( md5( substr( $did2, 1, -2) ),16 ,10), -2)) || ($didx == 'e') || ($didx == 'i')) { + // check startup and expiration via [=[register + $r = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_did2 = '%s' ORDER BY reg_created DESC ", + dbesc($did2) + ); + if ($r && count($r)) { + $r = $r[0]; + // check timeframe + if ($r['reg_startup'] <= $now && $r['reg_expires'] >= $now) { + if (isset($_POST['resend']) && $didx == 'e') { + $re = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_didx = 'e' AND reg_did2 = '%s' ORDER BY reg_created DESC ", dbesc($r['reg_did2']) ); + if ($re) { + $re = $re[0]; + $reonar = json_decode($re['reg_stuff'], true); + if ($reonar) { + $reonar['subject'] = 'Re,Fwd,' . $reonar['subject']; + $zm = zar_reg_mail($reonar); + $msg = (($zm) ? t('Email resent') : t('Email resend failed')); + zar_log((($zm) ? 'ZAR1238I' : 'ZAR1238E') . ' ' . $msg . ' ' . $r['reg_did2']); + info($msg); + return; + } + } + } + + // check hash + if ( $didx == 'a' ) + $acpin = (preg_match('/^[0-9]{6,6}$/', $_POST['acpin']) ? $_POST['acpin'] : false); + elseif ( $didx == 'e' ) + $acpin = (preg_match('/^[0-9a-f]{24,24}$/', $_POST['acpin']) ? $_POST['acpin'] : false); + elseif ( $didx == 'i' ) + $acpin = $r['reg_hash']; + else + $acpin = false; + + if ( $acpin && ($r['reg_hash'] == $acpin )) { + + $flags = $r['reg_flags']; + if (($flags & ACCOUNT_UNVERIFIED) == ACCOUNT_UNVERIFIED) { + + // verification success + $msg_code = 'ZAR1237I'; + $msg = t('Verification successful'); + $reonar = json_decode( $r['reg_stuff'], true); + $reonar['valid'] = $now . ',' . $ip . ' ' . $did2 . ' ' . $msg_code . ' ' . $msg; + + // clear flag + $flags &= $flags ^ ACCOUNT_UNVERIFIED; + + // are we invited by the admin? + $isa = get_account_by_id($r['reg_uid']); + $isa = ($isa && ($isa['account_roles'] && ACCOUNT_ROLE_ADMIN)); + + // approve contra invite by admin + if ($isa && get_config('system','register_policy') == REGISTER_APPROVE) { + $flags &= $flags ^ ACCOUNT_PENDING; + } + + // sth todo? + $vital = $flags == 0 ? 0 : 1; + + // set flag + $flags |= REGISTER_AGREED; + zar_log($msg . ' ' . $did2 . ':flags' . $flags . ',rid' . $r['reg_id']); + + q("START TRANSACTION"); + + $qu = q("UPDATE register SET reg_stuff = '%s', reg_vital = %d, reg_flags = %d " + ." WHERE reg_id = %d ", + dbesc(json_encode($reonar)), + intval($vital), + intval($flags), + intval($r['reg_id']) + ); + + if (($flags & ACCOUNT_PENDING ) == ACCOUNT_PENDING) { + $nextpage = 'regate/' . bin2hex($did2) . $didx; + q("COMMIT"); + } + elseif (($flags ^ REGISTER_AGREED) == 0) { + + $cra = create_account_from_register([ 'reg_id' => $r['reg_id'] ]); + + if ($cra['success']) { + + q("COMMIT"); + $msg = t('Account successfull created'); + // zar_log($msg . ':' . print_r($cra, true)); + zar_log('ZAR1238I ' . $msg . ' ' . $cra['account']['account_email'] + . ' ' . $cra['account']['account_language']); + + authenticate_success($cra['account'],null,true,false,true); + + $nextpage = 'new_channel'; + + $auto_create = get_config('system', 'auto_channel_create', 1); + + if($auto_create) { + + $new_channel = ['success' => false]; + + // We do not reserve a channel_address before the registration is verified + // and possibly approved by the admin. + // If the provided channel_address has been claimed meanwhile, + // we will proceed to /new_channel. + + if(isset($reonar['chan.did1']) && check_webbie([$reonar['chan.did1']])) { + + // prepare channel creation + if($reonar['chan.name']) + set_aconfig($cra['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']); + + if($reonar['chan.did1']) + set_aconfig($cra['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']); + + $permissions_role = get_config('system','default_permissions_role'); + if($permissions_role) + set_aconfig($cra['account']['account_id'], 'register', 'permissions_role', $permissions_role); + + // create channel + $new_channel = auto_channel_create($cra['account']['account_id']); + + if($new_channel['success']) { + $channel_id = $new_channel['channel']['channel_id']; + change_channel($channel_id); + $nextpage = 'profiles/' . $channel_id; + $msg_code = 'ZAR1239I'; + $msg = t('Channel successfull created') . ' ' . $did2; + } + } + + if(!$new_channel['success']) { + $msg_code = 'ZAR1239E'; + $msg = t('Automatic channel creation failed. Please create a channel.') . ' ' . $did2; + $nextpage = 'new_channel?name=' . $reonar['chan.name']; + } + + zar_log($msg_code . ' ' . $msg . ' ' . $reonar['chan.did1'] . ' (' . $reonar['chan.name'] . ')'); + + } + unset($_SESSION['login_return_url']); + } + else { + q("ROLLBACK"); + $msg_code = 'ZAR1238E'; + $msg = t('Account creation error'); + zar_log($msg_code . ' ' . $msg . ': ' . print_r($cra, true)); + } + } + else { + // new flags implemented and not recognized or sth like + zar_log('ZAR1237D unexpected,' . $flags); + } + } + else { + // nothing to confirm + $msg_code = 'ZAR1236E'; + $msg = t('Verify failed'); + } + } + else { + $msg_code = 'ZAR1235E'; + $msg = t('Token verification failed'); + } + } + else { + $msg_code = 'ZAR1234W'; + $msg = t('Request not inside time frame'); + //info($r[0]['reg_startup'] . EOL . $r[0]['reg_expire'] ); + } + } + else { + $msg_code = 'ZAR1232E'; + $msg = t('Identity unknown'); + zar_log($msg_code . ' ' . $msg . ':' . $did2 . $didx); + } + } + else { + $msg_code = 'ZAR1231E'; + $msg = t('dId2 mistaken'); + zar_log($msg_code . ' ' . $msg); + + } + + } + + if ($msg > '') info($msg); + goaway( z_root() . '/' . $nextpage ); + } + + + function get() { + + if (argc() == 1) { + if(isset($_GET['reg_id'])) { + if ( preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $_GET['reg_id'] ) ) { + // dId2 E email + goaway(z_root() . '/regate/' . bin2hex($_GET['reg_id']) . 'e' ); + } + if ( preg_match('/^d{1,1}[0-9]{5,10}$/', $_GET['reg_id'] ) ) { + // dId2 A artifical & anonymous + goaway(z_root() . '/regate/' . bin2hex($_GET['reg_id']) . 'a' ); + } + notice(t('Identity unknown') . EOL); + } + + $o = replace_macros(get_markup_template('plain.tpl'), [ + '$title' => t('Your Registration ID'), + '$now' => '<form action="regate" method="get"><input type="text" name="reg_id" class="form-control form-group"><button class="btn btn-primary float-right">Submit</button></form>' + ]); + + return $o; + } + + $isduty = zar_register_dutystate(); + $nowfmt = $isduty['nowfmt']; + $atform = $isduty['atform']; + + if ($_SESSION['zar']['delayed']) { + $o = replace_macros(get_markup_template('regate_pre.tpl'), [ + '$title' => t('Registration verification'), + '$now' => $nowfmt, + '$id' => $_SESSION['zar']['id'], + '$pin' => $_SESSION['zar']['pin'], + '$regdelay' => $_SESSION['zar']['regdelay'], + '$regexpire' => $_SESSION['zar']['regexpire'], + '$strings' => [ + t('Hold on, you can start verification in'), + t('Please remember your verification token for ID'), + '', + t('Token validity') + ] + ]); + unset($_SESSION['zar']['delayed']); + return $o; + } + + if (argc() < 2) + return; + + $did2 = hex2bin( substr( argv(1), 0, -1) ); + $didx = substr( argv(1), -1 ); + $deny = argc() > 2 ? argv(2) : ''; + $deny = preg_match('/^[0-9a-f]{8,8}$/', $deny) ? hex2bin($deny) : false; + $now = datetime_convert(); + $ip = $_SERVER['REMOTE_ADDR']; + + $pin = ''; + + if(isset($_SESSION['zar']['pin'])) { + $pin = $_SESSION['zar']['pin']; + unset($_SESSION['zar']['pin']); + } + + // do we have a valid dId2 ? + if (($didx == 'a' && substr( $did2 , -2) == substr( base_convert( md5( substr( $did2, 1, -2) ),16 ,10), -2)) || ($didx == 'e') || ($didx == 'i')) { + + $r = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_didx = '%s' AND reg_did2 = '%s' ORDER BY reg_created DESC", + dbesc($didx), + dbesc($did2) + ); + + if ($r && count($r) && $r[0]['reg_flags'] &= (ACCOUNT_UNVERIFIED | ACCOUNT_PENDING)) { + $r = $r[0]; + + // provide a button in case + $resend = (($r['reg_didx'] == 'e') ? t('Resend email') : ''); + + // is still only instance admins intervention required? + if ($r['reg_flags'] == ACCOUNT_PENDING) { + $o = replace_macros(get_markup_template('regate_post.tpl'), [ + '$title' => t('Registration status'), + '$id' => $did2, + '$strings' => [ + t('Verification successful!'), + t('Your login ID is'), + t('After your account has been approved by our administrator you will be able to login with your login ID and your provided password.') + ] + ]); + } + else { + + if ($deny) { + + if (substr($r['reg_hash'],0,4) == $deny) { + zar_log('ZAR1134S email verfication denied ' . $did2); + + $o = replace_macros(get_markup_template('plain.tpl'), [ + '$title' => t('Registration request revoked'), + '$infos' => t('Sorry for any inconvience. Thank you for your response.') + ]); + + $reonar = json_decode( $r['reg_stuff'], true); + $reonar['deny'] = $now . ',' . $ip . ' ' . $did2 . ' ' . $msg; + $flags = ( $r['reg_flags'] &= ( $r['reg_flags'] ^ ACCOUNT_UNVERIFIED) ) + | ( $r['reg_flags'] |= REGISTER_DENIED); + $rd = q("UPDATE register SET reg_stuff='%s', reg_vital=0, reg_flags=%d WHERE reg_id = %d ", + dbesc(json_encode($reonar)), + intval($flags), + intval($r['reg_id']) + ); + } + else { + zar_log('ZAR1135E not awaited url parameter received'); + goaway(z_root); + } + } + else { + + if ( $r['reg_startup'] <= $now && $r['reg_expires'] >= $now) { + $o = replace_macros(get_markup_template('regate.tpl'), [ + '$form_security_token' => get_form_security_token("regate"), + '$title' => t('Registration verification'), + '$desc' => t('Please enter your verification token for ID'), + '$email_extra' => (($didx === 'e') ? t('Please check your email!') : ''), + '$id' => $did2, + // we might consider to not provide $pin if a registration delay is configured + // and the pin turns out to be readable by bots + '$pin' => $pin, + '$did2' => bin2hex($did2) . $didx, + '$now' => $nowfmt, + '$atform' => $atform, + '$resend' => $resend, + '$submit' => t('Submit'), + '$acpin' => [ 'acpin', t('Verification token'),'','' ] + ]); + } + else { + // expired ? + if ( $now > $r['reg_expires'] ) { + $rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d ", + intval($r['reg_id']) + ); + + $o = replace_macros(get_markup_template('plain.tpl'), [ + '$infos' => t('ID expired'), + ]); + + return $o; + } + + $email_extra = (($didx === 'e') ? t('Please check your email!') : ''); + + $o = replace_macros(get_markup_template('regate_pre.tpl'), [ + '$title' => t('Registration verification'), + '$now' => $nowfmt, + '$id' => $did2, + '$countdown' => datetime_convert('UTC', 'UTC', $r['reg_startup'], 'c'), + '$strings' => [ + t('Hold on, you can start verification in'), + t('You will require the verification token for ID'), + $email_extra + ] + ]); + } + } + } + } + else { + $msg = t('Unknown or expired ID'); + zar_log('ZAR1132E ' . $msg . ':' . $did2 . ',' . $didx); + $o = replace_macros(get_markup_template('plain.tpl'), [ + '$title' => $title, + '$now' => $nowfmt, + '$infos' => $msg + ]); + } + + } + else { + $msg = 'ZAR1131E ' . t('dId2 malformed'); + // $log = ' from § ' . $ip . ' §' . ' (' . dbesc($did2) . ')'; + zar_log($msg); + $o = replace_macros(get_markup_template('plain.tpl'), [ + '$title' => $title, + '$now' => $nowfmt, + '$infos' => $msg + ]); + } + + return $o; + } +} + diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php index 278cf15ca..683fcdc36 100644 --- a/Zotlabs/Module/Register.php +++ b/Zotlabs/Module/Register.php @@ -1,25 +1,34 @@ <?php + namespace Zotlabs\Module; +use App; use Zotlabs\Web\Controller; require_once('include/security.php'); +require_once('include/channel.php'); + class Register extends Controller { + const MYP = 'ZAR'; // ZAR0x + const VERSION = '2.0.0'; + function init() { - + + // ZAR0 + $result = null; $cmd = ((argc() > 1) ? argv(1) : ''); - + // Provide a stored request for somebody desiring a connection // when they first need to register someplace. Once they've - // created a channel, we'll try to revive the connection request + // created a channel, we'll try to revive the connection request // and process it. - + if($_REQUEST['connect']) $_SESSION['connect'] = $_REQUEST['connect']; - + switch($cmd) { case 'invite_check.json': $result = check_account_invite($_REQUEST['invite_code']); @@ -30,50 +39,161 @@ class Register extends Controller { case 'password_check.json': $result = check_account_password($_REQUEST['password1']); break; - default: + default: break; } if($result) { json_return_and_die($result); } } - - + function post() { check_form_security_token_redirectOnErr('/register', 'register'); - $max_dailies = intval(get_config('system','max_daily_registrations')); - if($max_dailies) { - $r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s", - db_utcnow(), db_quoteinterval('1 day') + /** + * [hilmar:] + * It may happen, the posted form arrives in a strange fashion. With the control of the duty hours + * for registration, the input form was disabled at html. While receiving posted data, checks are + * required if all is on the right road (most posts are not accepted during off duty). + * + */ + + + $act = q("SELECT COUNT(*) AS act FROM account")[0]['act']; + $is247 = false; + $ip = $_SERVER['REMOTE_ADDR']; + $sameip = intval(get_config('system','register_sameip', 3)); + $arr = $_POST; + $invite_code = ((x($arr,'invite_code')) ? notags(trim($arr['invite_code'])) : ''); + $name = ''; + $nick = ''; + $email = ((x($arr,'email')) ? notags(punify(trim($arr['email']))) : ''); + $password = ((x($arr,'password')) ? trim($arr['password']) : ''); + $password2 = ((x($arr,'password2')) ? trim($arr['password2']) : ''); + $register_msg = ((x($arr,'register_msg')) ? notags(trim($arr['register_msg'])) : ''); + $reonar = []; + $auto_create = get_config('system','auto_channel_create', 1); + $duty = zar_register_dutystate(); + + if (!get_config('system', 'register_duty_jso')) { + // if not yet configured default to true + $duty = array( 'isduty' => true, 'atfrm' => '', 'nowfmt' => ''); + } + + if($auto_create) { + $name = escape_tags(trim($arr['name'])); + + $name_error = validate_channelname($name); + if($name_error) { + notice($name_error . EOL); + return $ret; + } + + $nick = mb_strtolower(escape_tags(trim($arr['nickname']))); + if(!$nick) { + notice(t('Nickname is required.')); + return; + } + + if($nick === 'sys') { + notice(t('Reserved nickname. Please choose another.') . EOL); + return; + } + + if(check_webbie([$nick]) !== $nick) { + notice(t('Nickname has unsupported characters or is already being used on this site.') . EOL); + return; + } + } + + $email_verify = get_config('system', 'verify_email'); + if ($email_verify && !$email) { + notice(t('Email address required') . EOL); + return; + } + + if ($email) { + $email_result = check_account_email($email); + if ($email_result['error']) { + if ($email_result['email_unverified']) { + goaway(z_root() . '/regate/' . bin2hex($email) . 'e'); + } + return; + } + + } + + // case when an invited prepares the own account by supply own pw, accept tos, prepage channel (if auto) + if ($email && $invite_code) { + if ( preg_match('/^[a-z0-9]{12,12}$/', $invite_code ) ) { + $is247 = true; + } + } + + if ($act > 0 && !$is247 && !$duty['isduty']) { + // normally (except very 1st timr after install), that should never arrive here (ie js hack or sth like) + // log suitable for f2b also + $logmsg = 'Unexpected registration request off duty'; + notice($logmsg); + zar_log('ZAR0230S ' . $logmsg); + return; + } + + if ($sameip) { + $f = q("SELECT COUNT(reg_atip) AS atip FROM register WHERE reg_vital = 1 AND reg_atip = '%s' ", + dbesc($ip) ); - if($r && $r[0]['total'] >= $max_dailies) { - notice( t('Maximum daily site registrations exceeded. Please try again tomorrow.') . EOL); + if ($f && $f[0]['atip'] >= $sameip) { + $logmsg = 'ZAR0239S Exceeding same ip register request of ' . $sameip; + notice('Registrations from same IP exceeded.'); + zar_log($logmsg); return; } } - + + if (!$password) { + notice(t('No password provided') . EOL); + return; + } + + if ($password !== $password2) { + notice(t('Passwords do not match') . EOL); + return; + } + + $password_result = check_account_password($password); + if(!empty($password_result['error'])) { + $msg = $password_result['message']; + notice($msg); + zar_log($msg . ' ' . $did2); + return; + } + + $salt = random_string(32); + $password = $salt . ',' . hash('whirlpool', $salt . $password); + + // accept tos if(! x($_POST,'tos')) { - notice( t('Please indicate acceptance of the Terms of Service. Registration failed.') . EOL); + // msg! + notice(t('Terms of Service not accepted') . EOL); return; } - - $policy = get_config('system','register_policy'); - - $email_verify = get_config('system','verify_email'); - - + + $policy = get_config('system','register_policy'); + $invonly = get_config('system','invitation_only'); + $invalso = get_config('system','invitation_also'); + switch($policy) { - + case REGISTER_OPEN: $flags = ACCOUNT_OK; break; - + case REGISTER_APPROVE: - $flags = ACCOUNT_BLOCKED | ACCOUNT_PENDING; + $flags = ACCOUNT_PENDING; break; - + default: case REGISTER_CLOSED: if(! is_site_admin()) { @@ -83,164 +203,278 @@ class Register extends Controller { $flags = ACCOUNT_BLOCKED; break; } - - if($email_verify && $policy == REGISTER_OPEN) - $flags = $flags | ACCOUNT_UNVERIFIED; - - - if((! $_POST['password']) || ($_POST['password'] !== $_POST['password2'])) { - notice( t('Passwords do not match.') . EOL); - return; - } - - $arr = $_POST; + + if($email_verify && ($policy == REGISTER_OPEN || $policy == REGISTER_APPROVE)) + $flags = ($flags | ACCOUNT_UNVERIFIED); + + // $arr has $_POST; $arr['account_flags'] = $flags; - - $result = create_account($arr); - - if(! $result['success']) { - notice($result['message']); - return; - } - require_once('include/security.php'); - - - if($_REQUEST['name']) - set_aconfig($result['account']['account_id'],'register','channel_name',$_REQUEST['name']); - if($_REQUEST['nickname']) - set_aconfig($result['account']['account_id'],'register','channel_address',$_REQUEST['nickname']); - if($_REQUEST['permissions_role']) - set_aconfig($result['account']['account_id'],'register','permissions_role',$_REQUEST['permissions_role']); - - - $using_invites = intval(get_config('system','invitation_only')); - $num_invites = intval(get_config('system','number_invites')); - $invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : ''); - - if($using_invites && $invite_code) { - q("delete from register where hash = '%s'", dbesc($invite_code)); - // @FIXME - this also needs to be considered when using 'invites_remaining' in mod/invite.php - set_aconfig($result['account']['account_id'],'system','invites_remaining',$num_invites); - } - - if($policy == REGISTER_OPEN ) { - if($email_verify) { - $res = verify_email_address($result); - } - else { - $res = send_register_success_email($result['email'],$result['password']); - } - if($res) { - if($invite_code) { - info( t('Registration successful. Continue to create your first channel...') . EOL ) ; - } - else { - info( t('Registration successful. Please check your email for validation instructions.') . EOL ) ; + $now = datetime_convert(); + $well = false; + + // s3 + if ($invite_code) { + + if ($invonly || $invalso) { + + $reg = q("SELECT * from register WHERE reg_vital = 1 AND reg_didx = 'i' AND reg_hash = '%s'", + dbesc($invite_code) + ); + + if ($reg && count($reg) == 1) { + $reg = $reg[0]; + if ($reg['reg_email'] == ($email)) { + + if ($reg['reg_startup'] <= $now && $reg['reg_expires'] >= $now) { + + if ($auto_create) { + $reonar['chan.name'] = $name; + $reonar['chan.did1'] = $nick; + } + + q("UPDATE register set reg_pass = '%s', reg_stuff = '%s' WHERE reg_id = '%s'", + dbesc($password), + dbesc(json_encode($reonar)), + intval($reg['reg_id']) + ); + + $msg = t('Invitation code succesfully applied'); + zar_log('ZAR0237I ' . $msg) . ', ' . $email; + // msg! + info($msg . EOL); + + + // the invitecode has verified us and we have all the info we need + // take the shortcut. + + $_SESSION['zar']['invite_in_progress'] = true; + + $mod = new Regate(); + $_REQUEST['form_security_token'] = get_form_security_token("regate"); + App::$argc = 2; + App::$argv[0] = 'regate'; + App::$argv[1] = bin2hex($reg['reg_did2']) . 'i'; + return $mod->post(); + + } else { + // msg! + notice(t('Invitation not in time or too late') . EOL); + return; + } + + } else { + // no match email adr + $msg = t('Invitation email failed'); + zar_log('ZAR0235S ' . $msg); + notice($msg . EOL); + return; + } + + } else { + // no match invitecode + $msg = t('Invitation code failed') ; + zar_log('ZAR0234S ' . $msg); + notice( $msg . EOL); + return; } + + } else { + notice(t('Invitations are not available') . EOL); + return; } + } - elseif($policy == REGISTER_APPROVE) { - $res = send_reg_approval_email($result); - if($res) { - info( t('Your registration is pending approval by the site owner.') . EOL ) ; + else { + if (!$invonly) { + $well = true; } else { - notice( t('Your registration can not be processed.') . EOL); + $msg = t('Registration on this hub is by invitation only') . EOL; + notice($msg); + zar_log('ZAR0233E ' . $msg); + return; } - goaway(z_root()); } - - if($email_verify) { - goaway(z_root() . '/email_validation/' . bin2hex($result['email'])); + + // check max daily registrations after we have dealt with the invitecode + if (self::check_reg_limits()['is']) { + notice('Max registrations per day exceeded.'); + return; } - // fall through and authenticate if no approvals or verifications were required. - - authenticate_success($result['account'],null,true,false,true); - - $new_channel = false; - $next_page = 'new_channel'; - - if(get_config('system','auto_channel_create')) { - $new_channel = auto_channel_create($result['account']['account_id']); - if($new_channel['success']) { - $channel_id = $new_channel['channel']['channel_id']; - change_channel($channel_id); - $next_page = '~'; + if ($well) { + + if($policy == REGISTER_OPEN || $policy == REGISTER_APPROVE ) { + + $cfgdelay = get_config('system', 'register_delay', '0i'); + $reg_delayed = calculate_adue( $cfgdelay ); + $regdelay = (($reg_delayed) ? datetime_convert(date_default_timezone_get(), 'UTC', $reg_delayed['due']) : $now); + + $cfgexpire = get_config('system', 'register_expire', '3d'); + $reg_expires = calculate_adue( $cfgexpire ); + $regexpire = (($reg_expires) ? datetime_convert(date_default_timezone_get(), 'UTC', $reg_expires['due']) : datetime_convert('UTC', 'UTC', 'now + 99 years')); + + // handle an email request that will be verified or an ivitation associated with an email address + if ($email > '' && $email_verify) { + // enforce in case of icdone + $flags |= ACCOUNT_UNVERIFIED; + $empin = $pass2 = random_string(24); + $did2 = $email; + $didx = 'e'; + + push_lang(($reg['lang']) ? $reg['lang'] : App::$language); + $reonar['from'] = get_config('system', 'from_email'); + $reonar['to'] = $email; + $reonar['subject'] = sprintf( t('Registration confirmation for %s'), get_config('system','sitename')); + $reonar['txttemplate']= replace_macros(get_intltext_template('register_verify_member.tpl'), + [ + '$sitename' => get_config('system','sitename'), + '$siteurl' => z_root(), + '$email' => $email, + '$timeframe' => [$regdelay, $regexpire], + '$mail' => bin2hex($email) . 'e', + '$ko' => bin2hex(substr($empin,0,4)), + '$hash' => $empin + ] + ); + pop_lang(); + zar_reg_mail($reonar); + + } else { + // that is an anonymous request without email or with email not to verify + $acpin = $pass2 = rand(100000,999999); + $did2 = rand(10,99); + $didx = 'a'; + // enforce delayed verify + $flags = ($flags | ACCOUNT_UNVERIFIED); + if ($email) { + $reonar['email.untrust'] = $email; + $reonar['email.comment'] = 'received, but no need for'; + } + } + + if ($auto_create) { + $reonar['chan.name'] = $name; + $reonar['chan.did1'] = $nick; + } + + if ($policy == REGISTER_APPROVE) { + $reonar['msg'] = $register_msg; + } + + $reg = q("INSERT INTO register (" + . "reg_flags,reg_didx,reg_did2,reg_hash,reg_created,reg_startup,reg_expires," + . "reg_email,reg_pass,reg_lang,reg_atip,reg_stuff)" + . " VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", + intval($flags), + dbesc($didx), + dbesc($did2), + dbesc($pass2), + dbesc($now), + dbesc($regdelay), + dbesc($regexpire), + dbesc($email), + dbesc($password), + dbesc(App::$language), + dbesc($ip), + dbesc(json_encode($reonar)) + ); + + if ($didx == 'a') { + + $lid = q("SELECT reg_id FROM register WHERE reg_vital = 1 AND reg_did2 = '%s' AND reg_pass = '%s' ", + dbesc($did2), + dbesc($password) + ); + + if ($lid && count($lid) == 1 ) { + + $didnew = ( $lid[0]['reg_id'] . $did2 ) + . ( substr( base_convert( md5( $lid[0]['reg_id'] . $did2 ), 16, 10 ),-2 ) ); + + $reg = q("UPDATE register SET reg_did2 = CONCAT('d','%s') WHERE reg_id = %d ", + dbesc($didnew), intval($lid[0]['reg_id']) + ); + + zar_log( 'ZAR0239A ' . t('New register request') . ' d' . $didnew . ', ' + . $regdelay . ' - ' . $regexpire); + + if($reg_delayed) { + // this could be removed to make registration harder + $_SESSION['zar']['id'] = 'd' . $didnew; + $_SESSION['zar']['pin'] = $pass2; + $_SESSION['zar']['delayed'] = true; + $_SESSION['zar']['regdelay'] = datetime_convert('UTC', 'UTC', $regdelay, 'c'); + $_SESSION['zar']['regexpire'] = datetime_convert('UTC', 'UTC', $regexpire, 'c'); + } + else { + $_SESSION['zar']['pin'] = $pass2; + } + + goaway(z_root() . '/regate/' . bin2hex('d' . $didnew) . 'a' ); + } + else { + $msg = t('Error creating dId A'); + notice( $msg ); + zar_log( 'ZAR0239D,' . $msg . ' ' . $did2); + } + } + goaway(z_root() . '/regate/' . bin2hex($email) . $didx ); } - else - $new_channel = false; - } - - $x = get_config('system','workflow_register_next'); - if($x) { - $next_page = $x; - $_SESSION['workflow'] = true; } - - unset($_SESSION['login_return_url']); - goaway(z_root() . '/' . $next_page); - } - - - + + function get() { - + $registration_is = ''; $other_sites = ''; - + if(intval(get_config('system','register_policy')) === REGISTER_CLOSED) { if(intval(get_config('system','directory_mode')) === DIRECTORY_MODE_STANDALONE) { - notice( t('Registration on this hub is disabled.') . EOL); + notice(t('Registration on this hub is disabled.') . EOL); return; } - $mod = new Pubsites(); + $mod = new Pubsites(); return $mod->get(); } - + if(intval(get_config('system','register_policy')) == REGISTER_APPROVE) { $registration_is = t('Registration on this hub is by approval only.'); - $other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>'); + $other_sites = '<a href="pubsites">' . t('Register at another affiliated hub in case when prefered') . '</a>'; } + $duty = zar_register_dutystate(); - $invitations = false; + if (!get_config('system', 'register_duty_jso')) { + // if not yet configured default to true + $duty = array( 'isduty' => true, 'atfrm' => '', 'nowfmt' => ''); + } + $invitations = false; if(intval(get_config('system','invitation_only'))) { $invitations = true; $registration_is = t('Registration on this hub is by invitation only.'); - $other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>'); - } - - $max_dailies = intval(get_config('system','max_daily_registrations')); - if($max_dailies) { - $r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s", - db_utcnow(), db_quoteinterval('1 day') - ); - if($r && $r[0]['total'] >= $max_dailies) { - logger('max daily registrations exceeded.'); - notice( t('This site has exceeded the number of allowed daily account registrations. Please try again tomorrow.') . EOL); - return; - } + $other_sites = '<a href="pubsites">' . t('Register at another affiliated hub') . '</a>'; + } elseif (intval(get_config('system','invitation_also'))) { + $invitations = true; } - $privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : ""); - - $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); + $opal = self::check_reg_limits(); + if ( $opal['is']) + $duty['atform'] = 'disabled'; // Configurable terms of service link - $tosurl = get_config('system','tos_url'); if(! $tosurl) $tosurl = z_root() . '/help/TermsOfService'; - + $toslink = '<a href="' . $tosurl . '" target="_blank">' . t('Terms of Service') . '</a>'; - + // Configurable whether to restrict age or not - default is based on international legal requirements // This can be relaxed if you are on a restricted server that does not share with public servers - + if(get_config('system','no_age_restriction')) { $label_tos = sprintf( t('I accept the %s for this website'), $toslink); } @@ -253,50 +487,96 @@ class Register extends Controller { } $enable_tos = 1 - intval(get_config('system','no_termsofservice')); - - $email = array('email', t('Your email address'), ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : "")); - $password = array('password', t('Choose a password'), ''); - $password2 = array('password2', t('Please re-enter your password'), ''); + + $auto_create = get_config('system', 'auto_channel_create', 1); + $email_verify = get_config('system','verify_email'); + + $emailval = ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : ""); + $email = ['email', + t('Your email address'), + $emailval, + (($email_verify) ? t('Required') : t('Optional')), + (($email_verify) ? '*' : ''), + $duty['atform'] + ]; + + $password = array('password', t('Choose a password'), '', '', '', $duty['atform']); + $password2 = array('password2', t('Please re-enter your password'), '', '', '', $duty['atform']); + $invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : "")); - $name = array('name', t('Your Name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real names are preferred.')); + + $name = array('name', t('Your name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real name is preferred'), '', '', $duty['atform']); $nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl')); - $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub)); - $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role for your usage needs and privacy requirements.') . ' <a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles); - $tos = array('tos', $label_tos, '', '', array(t('no'),t('yes'))); + $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), t('Your nickname will be used to create an easy to remember channel address'), '', '', $duty['atform']); + $tos = array('tos', $label_tos, ((x($_REQUEST,'tos')) ? $_REQUEST['tos'] : ''), '', [t('No'),t('Yes')], $duty['atform']); + + $register_msg = ['register_msg', t('Why do you want to join this hub?'), ((x($_REQUEST,'register_msg')) ? $_REQUEST['register_msg'] : ''), t('This will help to review your registration')]; - $auto_create = (get_config('system','auto_channel_create') ? true : false); - $default_role = get_config('system','default_permissions_role'); - $email_verify = get_config('system','verify_email'); - require_once('include/bbcode.php'); - - $o = replace_macros(get_markup_template('register.tpl'), array( + $o = replace_macros(get_markup_template('register.tpl'), array( '$form_security_token' => get_form_security_token("register"), '$title' => t('Registration'), '$reg_is' => $registration_is, + '$register_msg' => $register_msg, '$registertext' => bbcode(get_config('system','register_text')), '$other_sites' => $other_sites, + '$msg' => $opal['msg'], '$invitations' => $invitations, '$invite_code' => $invite_code, + '$haveivc' => t('I have an invite code'), + '$now' => $duty['nowfmt'], + '$atform' => $duty['atform'], '$auto_create' => $auto_create, '$name' => $name, - '$role' => $role, - '$default_role' => $default_role, '$nickname' => $nickname, '$enable_tos' => $enable_tos, '$tos' => $tos, '$email' => $email, + '$validate' => $validate, + '$validate_link'=> $validate_link, + '$validate_here'=> $validate_here, '$pass1' => $password, '$pass2' => $password2, '$submit' => t('Register'), - '$verify_note' => (($email_verify) ? t('This site requires email verification. After completing this form, please check your email for further instructions.') : ''), + '$nickhub' => $nickhub + )); - + return $o; - } - - + + function check_reg_limits() { + // check against register, account + $rear = array( 'is' => false, 'rn' => 0, 'an' => 0, 'msg' => '' ); + + $max_dailies = intval(get_config('system', 'max_daily_registrations', 50)); + + if ($max_dailies) { + + $r = q("SELECT COUNT(reg_id) AS nr FROM register WHERE reg_vital = 1 AND reg_created > %s - INTERVAL %s", + db_utcnow(), db_quoteinterval('1 day') + ); + + $rear['is'] = ( $r && $r[0]['nr'] >= $max_dailies ) ? true : false; + $rear['rn'] = $r[0]['nr']; + + if (!$rear['is']) { + $r = q("SELECT COUNT(account_id) AS nr FROM account WHERE account_created > %s - INTERVAL %s", + db_utcnow(), db_quoteinterval('1 day') + ); + + $rear['is'] = ( $r && ($r[0]['nr'] + $rear['rn']) >= $max_dailies ) ? true : false; + $rear['ra'] = $r[0]['nr']; + } + + if ( $rear['is']) { + $rear['msg'] = t('This site has exceeded the number of allowed daily account registrations.'); + zar_log('ZAR0333W ' . $rear['msg']); + $rear['is'] = true; + } + } + return $rear; + } } diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php index 8a87d98f7..2ad79e3f6 100644 --- a/Zotlabs/Module/Search.php +++ b/Zotlabs/Module/Search.php @@ -58,7 +58,7 @@ class Search extends Controller { $o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false)); if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) { - $j = Activity::fetch($search, App::get_channel()); + $j = Activity::fetch(punify($search), App::get_channel()); if ($j) { $AS = new ActivityStreams($j); if ($AS->is_valid()) { @@ -101,7 +101,7 @@ class Search extends Controller { } // look for a naked webbie - if (strpos($search, '@') !== false) { + if (strpos($search,'@') !== false && strpos($search,'http') !== 0) { goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search); } diff --git a/Zotlabs/Module/Settings/Account.php b/Zotlabs/Module/Settings/Account.php index b40f516ca..97cc9389a 100644 --- a/Zotlabs/Module/Settings/Account.php +++ b/Zotlabs/Module/Settings/Account.php @@ -15,20 +15,23 @@ class Account { $account = \App::get_account(); if($email != $account['account_email']) { - if(! validate_email($email)) - $errs[] = t('Not valid email.'); - $adm = trim(get_config('system','admin_email')); - if(($adm) && (strcasecmp($email,$adm) == 0)) { - $errs[] = t('Protected email address. Cannot change to that email.'); - $email = \App::$account['account_email']; - } - if(! $errs) { - $r = q("update account set account_email = '%s' where account_id = %d", - dbesc($email), - intval($account['account_id']) - ); - if(! $r) - $errs[] = t('System failure storing new email. Please try again.'); + // a DId2 not an email addr does not allow to change to email addr + if (strpos($email, '@') > 0) { + if(! validate_email($email)) + $errs[] = t('Not valid email.'); + $adm = trim(get_config('system','admin_email')); + if(($adm) && (strcasecmp($email,$adm) == 0)) { + $errs[] = t('Protected email address. Cannot change to that email.'); + $email = \App::$account['account_email']; + } + if(! $errs) { + $r = q("update account set account_email = '%s' where account_id = %d", + dbesc($email), + intval($account['account_id']) + ); + if(! $r) + $errs[] = t('System failure storing new email. Please try again.'); + } } } @@ -92,6 +95,7 @@ class Account { call_hooks('account_settings', $account_settings); $email = \App::$account['account_email']; + $attremail = (!strpos($email, '@')) ? 'disabled="disabled"' : ''; $tpl = get_markup_template("settings_account.tpl"); $o .= replace_macros($tpl, array( @@ -101,7 +105,7 @@ class Account { '$password1'=> array('npassword', t('Enter New Password'), '', ''), '$password2'=> array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')), '$submit' => t('Submit'), - '$email' => array('email', t('Email Address:'), $email, ''), + '$email' => array('email', t('DId2 or Email Address:'), $email, '', '', $attremail), '$removeme' => t('Remove Account'), '$removeaccount' => t('Remove this account including all its channels'), '$account_settings' => $account_settings diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php index 46b4a8d87..8bea65207 100644 --- a/Zotlabs/Module/Sse.php +++ b/Zotlabs/Module/Sse.php @@ -47,7 +47,6 @@ class Sse extends Controller { self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify'); - $sys = get_sys_channel(); $sleep_seconds = 3; self::$sse_enabled = get_config('system', 'sse_enabled', 0); diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php index 3b39d5b49..cc67c8eb7 100644 --- a/Zotlabs/Module/Sse_bs.php +++ b/Zotlabs/Module/Sse_bs.php @@ -6,6 +6,7 @@ use App; use Zotlabs\Lib\Apps; use Zotlabs\Web\Controller; use Zotlabs\Lib\Enotify; +use Zotlabs\Lib\XConfig; class Sse_bs extends Controller { @@ -101,12 +102,13 @@ class Sse_bs extends Controller { self::bs_files(), self::bs_mail(), self::bs_all_events(), - self::bs_register() + self::bs_register(), + self::bs_info_notice() ); - set_xconfig(self::$ob_hash, 'sse', 'timestamp', datetime_convert()); - set_xconfig(self::$ob_hash, 'sse', 'notifications', []); // reset the cache - set_xconfig(self::$ob_hash, 'sse', 'language', App::$language); + XConfig::Set(self::$ob_hash, 'sse', 'notifications', []); + XConfig::Set(self::$ob_hash, 'sse', 'timestamp', datetime_convert()); + XConfig::Set(self::$ob_hash, 'sse', 'language', App::$language); json_return_and_die($result); } @@ -686,12 +688,15 @@ class Sse_bs extends Controller { if(! self::$uid && ! is_site_admin()) return $result; + $policy = intval(get_config('system','register_policy')); + if(($policy & REGISTER_APPROVE) != REGISTER_APPROVE) + return $result; + if(! (self::$vnotify & VNOTIFY_REGISTER)) return $result; - $r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0", - intval(ACCOUNT_PENDING) - ); + $r = get_pending_accounts(); + if($r) { foreach($r as $rr) { $result['register']['notifications'][] = Enotify::format_register($rr); @@ -703,4 +708,22 @@ class Sse_bs extends Controller { } + function bs_info_notice() { + + $result['notice']['notifications'] = []; + $result['info']['notifications'] = []; + + $r = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []); + + if(isset($r['notice'])) + $result['notice']['notifications'] = $r['notice']['notifications']; + + if(isset($r['info'])) + $result['info']['notifications'] = $r['info']['notifications']; + + return $result; + + } + + } diff --git a/Zotlabs/Module/Suggest.php b/Zotlabs/Module/Suggest.php index 18961214e..0ed6ea8d7 100644 --- a/Zotlabs/Module/Suggest.php +++ b/Zotlabs/Module/Suggest.php @@ -15,17 +15,17 @@ class Suggest extends \Zotlabs\Web\Controller { if(! Apps::system_app_installed(local_channel(), 'Suggest Channels')) return; - + if(x($_GET,'ignore')) { q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ", intval(local_channel()), dbesc($_GET['ignore']) ); } - + } - - + + function get() { if(! local_channel()) { @@ -45,22 +45,22 @@ class Suggest extends \Zotlabs\Web\Controller { $o = ''; nav_set_selected('Suggest Channels'); - + $_SESSION['return_url'] = z_root() . '/' . \App::$cmd; - + $r = suggestion_query(local_channel(),get_observer_hash()); - + if(! $r) { info( t('No suggestions available. If this is a new site, please try again in 24 hours.')); return; } - + $arr = array(); - + foreach($r as $rr) { - - $connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr']; - + + $connlnk = z_root() . '/follow?f=&url=' . $rr['xchan_addr']; + $arr[] = array( 'url' => chanlink_url($rr['xchan_url']), 'common' => $rr['total'], @@ -73,15 +73,15 @@ class Suggest extends \Zotlabs\Web\Controller { 'ignore' => t('Ignore/Hide') ); } - - + + $o = replace_macros(get_markup_template('suggest_page.tpl'),array( '$title' => t('Channel Suggestions'), '$entries' => $arr )); - + return $o; - + } - + } diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 169dc6de1..04c1dbeaa 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -127,7 +127,6 @@ class Wiki extends Controller { $resource_id = argv(4); $w = NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id); - // $w = NativeWiki::get_wiki($owner,$observer_hash,$resource_id); if(! $w['htmlName']) { notice(t('Error retrieving wiki') . EOL); @@ -218,12 +217,12 @@ class Wiki extends Controller { '$name' => t('Name'), '$type' => t('Type'), '$unlocked' => t('Any type'), - '$lockstate' => $x['lockstate'], - '$acl' => $x['acl'], - '$allow_cid' => $x['allow_cid'], - '$allow_gid' => $x['allow_gid'], - '$deny_cid' => $x['deny_cid'], - '$deny_gid' => $x['deny_gid'], + '$lockstate' => (x($x,'lockstate') ? $x['lockstate'] : ''), + '$acl' => (x($x,'acl') ? $x['acl'] : ''), + '$allow_cid' => (x($x,'allow_cid') ? $x['allow_cid'] : ''), + '$allow_gid' => (x($x,'allow_gid') ? $x['allow_gid'] : ''), + '$deny_cid' => (x($x,'deny_cid') ? $x['deny_cid'] : ''), + '$deny_gid' => (x($x,'deny_gid') ? $x['deny_gid'] : ''), '$typelock' => array('typelock', t('Lock content type'), '', '', array(t('No'), t('Yes'))), '$notify' => array('postVisible', t('Create a status post for this wiki'), '', '', array(t('No'), t('Yes'))), '$edit_wiki_name' => t('Edit Wiki Name') @@ -508,7 +507,7 @@ class Wiki extends Controller { notice( t('Wiki created, but error creating Home page.')); goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName'])); } - NativeWiki::sync_a_wiki_item($owner['channel_id'],$homePage['item_id'],$r['item']['resource_id']); + NativeWiki::sync_a_wiki_item($owner['channel_id'], $homePage['item_id'], $r['item']['resource_id']); goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']) . '/' . NativeWiki::name_encode($homePage['page']['urlName'])); } else { @@ -542,7 +541,6 @@ class Wiki extends Controller { } $wiki = NativeWiki::exists_by_name($owner['channel_id'], $arr['urlName']); - if($wiki['resource_id']) { $arr['resource_id'] = $wiki['resource_id']; @@ -552,7 +550,7 @@ class Wiki extends Controller { $r = NativeWiki::update_wiki($owner['channel_id'], $observer_hash, $arr, $acl); if($r['success']) { - NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']); + NativeWiki::sync_a_wiki_item($owner['channel_id'], $r['item_id'], $r['item']['resource_id']); goaway(z_root() . '/wiki/' . $nick); } else { @@ -576,7 +574,7 @@ class Wiki extends Controller { $resource_id = $_POST['resource_id']; $deleted = NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id); if ($deleted['success']) { - NativeWiki::sync_a_wiki_item($owner['channel_id'],$deleted['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id); json_return_and_die(array('message' => '', 'success' => true)); } else { @@ -611,18 +609,17 @@ class Wiki extends Controller { } $page = NativeWikiPage::create_page($owner['channel_id'],$observer_hash, $name, $resource_id, $mimetype); - if($page['item_id']) { - $commit = NativeWikiPage::commit(array( + + $commit = NativeWikiPage::commit([ 'commit_msg' => t('New page created'), 'resource_id' => $resource_id, 'channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'pageUrlName' => $name - )); - + ]); if($commit['success']) { - NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id); //json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true)); json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . $page['page']['urlName'], 'success' => true)); } @@ -680,20 +677,25 @@ class Wiki extends Controller { json_return_and_die(array('success' => false)); } - $saved = NativeWikiPage::save_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'content' => $content)); - + $saved = NativeWikiPage::save_page([ + 'channel_id' => $owner['channel_id'], + 'observer_hash' => $observer_hash, + 'resource_id' => $resource_id, + 'pageUrlName' => $pageUrlName, + 'content' => $content + ]); if($saved['success']) { - $commit = NativeWikiPage::commit(array( + + $commit = NativeWikiPage::commit([ 'commit_msg' => $commitMsg, 'pageUrlName' => $pageUrlName, 'resource_id' => $resource_id, 'channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'revision' => (-1) - )); - + ]); if($commit['success']) { - NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id); json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true , 'content' => $content)); } else { @@ -738,9 +740,9 @@ class Wiki extends Controller { if ($pageUrlName === 'Home') { json_return_and_die(array('message' => t('Cannot delete Home'),'success' => false)); } + // Determine if observer has permission to delete pages // currently just allow page owner - if((! local_channel()) || (local_channel() != $owner['channel_id'])) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); @@ -752,9 +754,14 @@ class Wiki extends Controller { json_return_and_die(array('success' => false)); } - $deleted = NativeWikiPage::delete_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); + $deleted = NativeWikiPage::delete_page([ + 'channel_id' => $owner['channel_id'], + 'observer_hash' => $observer_hash, + 'resource_id' => $resource_id, + 'pageUrlName' => $pageUrlName + ]); if($deleted['success']) { - NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id); json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); } else { @@ -768,18 +775,25 @@ class Wiki extends Controller { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $commitHash = $_POST['commitHash']; - // Determine if observer has permission to revert pages + // Determine if observer has permission to revert pages $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied.' . EOL); json_return_and_die(array('success' => false)); } - $reverted = NativeWikiPage::revert_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'commitHash' => $commitHash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); + $reverted = NativeWikiPage::revert_page([ + 'channel_id' => $owner['channel_id'], + 'observer_hash' => $observer_hash, + 'commitHash' => $commitHash, + 'resource_id' => $resource_id, + 'pageUrlName' => $pageUrlName + ]); if($reverted['success']) { json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true)); - } else { + } + else { json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false)); } } @@ -826,18 +840,23 @@ class Wiki extends Controller { json_return_and_die(array('success' => false)); } - $renamed = NativeWikiPage::rename_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'pageNewName' => $pageNewName)); - + $renamed = NativeWikiPage::rename_page([ + 'channel_id' => $owner['channel_id'], + 'observer_hash' => $observer_hash, + 'resource_id' => $resource_id, + 'pageUrlName' => $pageUrlName, + 'pageNewName' => $pageNewName + ]); if($renamed['success']) { - $commit = NativeWikiPage::commit(array( + $commit = NativeWikiPage::commit([ 'channel_id' => $owner['channel_id'], 'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], 'resource_id' => $resource_id, 'observer_hash' => $observer_hash, 'pageUrlName' => $pageNewName - )); + ]); if($commit['success']) { - NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id); json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true)); } else { |