diff options
Diffstat (limited to 'mod')
96 files changed, 4351 insertions, 2377 deletions
diff --git a/mod/achievements.php b/mod/achievements.php index 1910def73..1d0018b08 100644 --- a/mod/achievements.php +++ b/mod/achievements.php @@ -1,6 +1,9 @@ <?php function achievements_content(&$a) { + // This doesn't work, so + if (! is_developer()) + return; if(argc() > 1) $which = argv(1); @@ -28,6 +31,9 @@ function achievements_content(&$a) { return; } + $newmembertext = t('Some blurb about what to do when you\'re new here'); + + // By default, all badges are false $contactbadge = false; $profilebadge = false; @@ -70,15 +76,12 @@ function achievements_content(&$a) { if($r) $keywordsbadge = 1; -// FIXME - stick ths in a template, and make it look pretty. - $o .= "Template not implemented"; - $o .= "If this is one, you get the profile badge" . $profilebadge . "<br>"; - $o .= "If this is one, you get the contact badge" . $contactbadge . "<br>"; - $o .= "If this is one you get the keywords badge" . $keywordsbadge . "<br>"; - $o .= "I haven't done the top level posts badge yet" . $toplevelpostsbadge . "<br>"; - $o .= "I haven't done the number of channels badge yet" . $channelsbadge; - - -return $o; + return replace_macros(get_markup_template("achievements.tpl"), array( + '$newmembertext' => $newmembertext, + '$profilebadge' => $profilebadge, + '$contactbadge' => $contactbadge, + '$keywordsbadge' => $keywordsbadge, + '$channelsbadge' => $channelsbadge +)); } diff --git a/mod/acl.php b/mod/acl.php index fa399a9b5..e6733351b 100644 --- a/mod/acl.php +++ b/mod/acl.php @@ -11,7 +11,10 @@ function acl_init(&$a){ $count = (x($_REQUEST,'count')?$_REQUEST['count']:100); $search = (x($_REQUEST,'search')?$_REQUEST['search']:""); $type = (x($_REQUEST,'type')?$_REQUEST['type']:""); - + $noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false); + + // List of channels whose connections to also suggest, e.g. currently viewed channel or channels mentioned in a post + $extra_channels = (x($_REQUEST,'extra_channels') ? $_REQUEST['extra_channels'] : array()); // For use with jquery.autocomplete for private mail completion @@ -21,15 +24,17 @@ function acl_init(&$a){ $search = $_REQUEST['query']; } - if(!(local_user())) - if($type != 'x') + if(!($type == 'x' || $type == 'c')) killme(); if ($search != "") { $sql_extra = " AND `name` LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " "; - $sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . ") "; + $sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc($search) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") "; + // This horrible mess is needed because position also returns 0 if nothing is found. W/ould be MUCH easier if it instead returned a very large value + // Otherwise we could just order by LEAST(POSTION($search IN xchan_name),POSITION($search IN xchan_addr)). + $order_extra2 = "CASE WHEN xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) ." then POSITION('".dbesc($search)."' IN xchan_name) else position('".dbesc($search)."' IN xchan_addr) end, "; $col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' ); $sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " "; @@ -37,72 +42,6 @@ function acl_init(&$a){ $sql_extra = $sql_extra2 = $sql_extra3 = ""; } - // count groups and contacts - if ($type=='' || $type=='g'){ - $r = q("SELECT COUNT(`id`) AS g FROM `groups` WHERE `deleted` = 0 AND `uid` = %d $sql_extra", - intval(local_user()) - ); - $group_count = (int)$r[0]['g']; - } else { - $group_count = 0; - } - - if ($type=='' || $type=='c'){ - $r = q("SELECT COUNT(abook_id) AS c FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d AND not ( abook_flags & %d ) and not (xchan_flags & %d ) $sql_extra2" , - intval(local_user()), - intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED), - intval(XCHAN_FLAGS_DELETED) - ); - $contact_count = (int)$r[0]['c']; - - if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_user(),'system','taganyone'))) { - if(((! $r) || (! $r[0]['total'])) && $type == 'c') { - $r = q("SELECT COUNT(xchan_hash) AS c FROM xchan - WHERE not (xchan_flags & %d ) $sql_extra2" , - intval(XCHAN_FLAGS_DELETED) - ); - $contact_count = (int)$r[0]['c']; - } - } - - } - - elseif ($type == 'm') { - - // autocomplete for Private Messages - - - $r = q("SELECT count(xchan_hash) as c - FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and ( (abook_their_perms = null) or (abook_their_perms & %d )) - and not ( xchan_flags & %d ) - $sql_extra2 ", - intval(local_user()), - intval(PERMS_W_MAIL), - intval(XCHAN_FLAGS_DELETED) - ); - - if($r) - $contact_count = (int)$r[0]['c']; - - } - elseif ($type == 'a') { - - // autocomplete for Contacts - - $r = q("SELECT COUNT(abook_id) AS c FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and not ( xchan_flags & %d ) $sql_extra2" , - intval(local_user()), - intval(XCHAN_FLAGS_DELETED) - ); - $contact_count = (int)$r[0]['c']; - - } else { - $contact_count = 0; - } - - $tot = $group_count+$contact_count; $groups = array(); $contacts = array(); @@ -110,17 +49,18 @@ function acl_init(&$a){ if ($type=='' || $type=='g'){ $r = q("SELECT `groups`.`id`, `groups`.`hash`, `groups`.`name`, - GROUP_CONCAT(DISTINCT `group_member`.`xchan` SEPARATOR ',') as uids + %s as uids FROM `groups`,`group_member` WHERE `groups`.`deleted` = 0 AND `groups`.`uid` = %d AND `group_member`.`gid`=`groups`.`id` $sql_extra GROUP BY `groups`.`id` ORDER BY `groups`.`name` - LIMIT %d,%d", + LIMIT %d OFFSET %d", + db_concat('group_member.xchan', ','), intval(local_user()), - intval($start), - intval($count) + intval($count), + intval($start) ); foreach($r as $g){ @@ -138,18 +78,80 @@ function acl_init(&$a){ } if ($type=='' || $type=='c') { - $r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags + $extra_channels_sql = ''; + // Only include channels who allow the observer to view their permissions + foreach($extra_channels as $channel) { + if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) + $extra_channels_sql .= "," . intval($channel); + } + + $extra_channels_sql = substr($extra_channels_sql,1); // Remove initial comma + + // Getting info from the abook is better for local users because it contains info about permissions + if(local_user()) { + if($extra_channels_sql != '') + $extra_channels_sql = " OR (abook_channel IN ($extra_channels_sql)) and not (abook_flags & ". intval(ABOOK_FLAG_HIDDEN) . ') > 0'; + + $r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d AND not ( abook_flags & %d ) and not (xchan_flags & %d ) $sql_extra2 order by xchan_name asc" , - intval(local_user()), - intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED), - intval(XCHAN_FLAGS_DELETED) - ); + WHERE (abook_channel = %d $extra_channels_sql) AND not ( abook_flags & %d )>0 and not (xchan_flags & %d )>0 $sql_extra2 order by $order_extra2 xchan_name asc" , + intval(local_user()), + intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED), + intval(XCHAN_FLAGS_DELETED) + ); + } + else { // Visitors + $r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags + FROM xchan left join xlink on xlink_link = xchan_hash + WHERE xlink_xchan = '%s' AND NOT (xchan_flags & %d) > 0 $sql_extra2 order by $order_extra2 xchan_name asc" , + dbesc(get_observer_hash()), + intval(XCHAN_FLAGS_DELETED)); + + // Find contacts of extra channels + // This is probably more complicated than it needs to be + if($extra_channels_sql) { + // Build a list of hashes that we got previously so we don't get them again + $known_hashes = array("'".get_observer_hash()."'"); + if($r) + foreach($r as $rr) + $known_hashes[] = "'".$rr['hash']."'"; + $known_hashes_sql = 'AND xchan_hash not in ('.join(',',$known_hashes).')'; + + $r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags + FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel IN ($extra_channels_sql) $known_hashes_sql AND not ( abook_flags & %d )>0 and not (xchan_flags & %d )>0 $sql_extra2 order by $order_extra2 xchan_name asc" , + intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED|ABOOK_FLAG_HIDDEN), + intval(XCHAN_FLAGS_DELETED) + ); + if($r2) + $r = array_merge($r,$r2); + + // Sort accoring to match position, then alphabetically. This could be avoided if the above two SQL queries could be combined into one, and the sorting could be done on the SQl server (like in the case of a local user) + $matchpos = function($x) use($search) { + $namepos = strpos($x['name'],$search); + $nickpos = strpos($x['nick'],$search); + // Use a large position if not found + return min($namepos === false ? 9999 : $namepos, $nickpos === false ? 9999 : $nickpos); + }; + // This could be made simpler if PHP supported stable sorting + usort($r,function($a,$b) use($matchpos) { + $pos1 = $matchpos($a); + $pos2 = $matchpos($b); + if($pos1 == $pos2) { // Order alphabetically if match position is the same + if($a['name'] == $b['name']) + return 0; + else + return ($a['name'] < $b['name']) ? -1 : 1; + } + return ($pos1 < $pos2) ? -1 : 1; + }); + } + } if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_user(),'system','taganyone'))) { if((! $r) && $type == 'c') { $r = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags FROM xchan - WHERE not (xchan_flags & %d ) $sql_extra2 order by xchan_name asc" , + WHERE not (xchan_flags & %d )>0 $sql_extra2 order by $order_extra2 xchan_name asc" , intval(XCHAN_FLAGS_DELETED) ); } @@ -159,8 +161,8 @@ function acl_init(&$a){ $r = q("SELECT xchan_hash as id, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and ( (abook_their_perms = null) or (abook_their_perms & %d )) - and not (xchan_flags & %d) + WHERE abook_channel = %d and ( (abook_their_perms = null) or (abook_their_perms & %d )>0) + and not (xchan_flags & %d)>0 $sql_extra3 ORDER BY `xchan_name` ASC ", intval(local_user()), @@ -168,10 +170,10 @@ function acl_init(&$a){ intval(XCHAN_FLAGS_DELETED) ); } - elseif($type == 'a') { + elseif(($type == 'a') || ($type == 'p')) { $r = q("SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d - and not (xchan_flags & %d) + and not (xchan_flags & %d)>0 $sql_extra3 ORDER BY xchan_name ASC ", intval(local_user()), @@ -204,7 +206,7 @@ function acl_init(&$a){ $r = array(); - if($type == 'm' || $type == 'a') { + if($type == 'm' || $type == 'a' || $type == 'p') { $x = array(); $x['query'] = $search; $x['photos'] = array(); @@ -216,7 +218,7 @@ function acl_init(&$a){ $x['photos'][] = $g['micro']; $x['links'][] = $g['url']; $x['suggestions'][] = $g['name']; - $x['data'][] = $g['id']; + $x['data'][] = (($type === 'p') ? '@' . str_replace(' ','_',$g['name']) : $g['id']); } } echo json_encode($x); @@ -225,7 +227,12 @@ function acl_init(&$a){ if(count($r)) { foreach($r as $g){ - if(($g['abook_their_perms'] & PERMS_W_TAGWALL) && $type == 'c') { + + // remove RSS feeds from ACLs - they are inaccessible + if(strpos($g['hash'],'/')) + continue; + + if(($g['abook_their_perms'] & PERMS_W_TAGWALL) && $type == 'c' && (! $noforums)) { $contacts[] = array( "type" => "c", "photo" => "images/twopeople.png", @@ -257,7 +264,6 @@ function acl_init(&$a){ $items = array_merge($groups, $contacts); $o = array( - 'tot' => $tot, 'start' => $start, 'count' => $count, 'items' => $items, diff --git a/mod/admin.php b/mod/admin.php index 464edddd4..0e580960a 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -65,6 +65,11 @@ function admin_post(&$a){ case 'dbsync': admin_page_dbsync_post($a); break; + + case 'profs': + admin_page_profs_post($a); + break; + } } @@ -95,6 +100,7 @@ function admin_content(&$a) { 'plugins' => Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"), 'themes' => Array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"), 'hubloc' => Array($a->get_baseurl(true)."/admin/hubloc/", t("Server") , "server"), + 'profs' => array(z_root() . '/admin/profs', t('Profile Config'), 'profs'), 'dbsync' => Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync") ); @@ -155,6 +161,9 @@ function admin_content(&$a) { case 'dbsync': $o = admin_page_dbsync($a); break; + case 'profs': + $o = admin_page_profs($a); + break; default: notice( t("Item not found.") ); } @@ -229,8 +238,7 @@ function admin_page_site_post(&$a){ $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'])) : ''); - $theme_accessibility = ((x($_POST,'theme_accessibility')) ? notags(trim($_POST['theme_accessibility'])) : ''); - $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : ''); +// $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : ''); $maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0); @@ -256,55 +264,18 @@ function admin_page_site_post(&$a){ $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0); $poll_interval = ((x($_POST,'poll_interval'))? intval(trim($_POST['poll_interval'])) : 0); $maxloadavg = ((x($_POST,'maxloadavg'))? intval(trim($_POST['maxloadavg'])) : 50); -// $ssl_policy = ((x($_POST,'ssl_policy')) ? intval($_POST['ssl_policy']) : 0); -/* - if($ssl_policy != intval(get_config('system','ssl_policy'))) { - if($ssl_policy == SSL_POLICY_FULL) { - q("update `contact` set - `url` = replace(`url` , 'http:' , 'https:'), - `photo` = replace(`photo` , 'http:' , 'https:'), - `thumb` = replace(`thumb` , 'http:' , 'https:'), - `micro` = replace(`micro` , 'http:' , 'https:'), - `request` = replace(`request`, 'http:' , 'https:'), - `notify` = replace(`notify` , 'http:' , 'https:'), - `poll` = replace(`poll` , 'http:' , 'https:'), - `confirm` = replace(`confirm`, 'http:' , 'https:'), - `poco` = replace(`poco` , 'http:' , 'https:') - where `self` = 1" - ); - q("update `profile` set - `photo` = replace(`photo` , 'http:' , 'https:'), - `thumb` = replace(`thumb` , 'http:' , 'https:') - where 1 " - ); - } - elseif($ssl_policy == SSL_POLICY_SELFSIGN) { - q("update `contact` set - `url` = replace(`url` , 'https:' , 'http:'), - `photo` = replace(`photo` , 'https:' , 'http:'), - `thumb` = replace(`thumb` , 'https:' , 'http:'), - `micro` = replace(`micro` , 'https:' , 'http:'), - `request` = replace(`request`, 'https:' , 'http:'), - `notify` = replace(`notify` , 'https:' , 'http:'), - `poll` = replace(`poll` , 'https:' , 'http:'), - `confirm` = replace(`confirm`, 'https:' , 'http:'), - `poco` = replace(`poco` , 'https:' , 'http:') - where `self` = 1" - ); - q("update `profile` set - `photo` = replace(`photo` , 'https:' , 'http:'), - `thumb` = replace(`thumb` , 'https:' , 'http:') - where 1 " - ); - } - } -*/ -// set_config('system','ssl_policy',$ssl_policy); + $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); + $diaspora_enabled = ((x($_POST,'diaspora_enabled')) ? intval($_POST['diaspora_enabled']) : 0); + $verify_email = ((x($_POST,'verify_email')) ? 1 : 0); + + set_config('system','feed_contacts',$feed_contacts); + set_config('system','diaspora_enabled',$diaspora_enabled); set_config('system','delivery_interval',$delivery_interval); set_config('system','poll_interval',$poll_interval); set_config('system','maxloadavg',$maxloadavg); set_config('system','sitename',$sitename); set_config('system','no_login_on_homepage',$no_login_on_homepage); + set_config('system','verify_email',$verify_email); if ($banner=="") { del_config('system','banner'); @@ -326,13 +297,7 @@ function admin_page_site_post(&$a){ } else { set_config('system','mobile_theme', $theme_mobile); } - if ( $theme_accessibility === '---' ) { - del_config('system','accessibility_theme'); - } else { - set_config('system','accessibility_theme', $theme_accessibility); - } - - set_config('system','site_channel', $site_channel); +// set_config('system','site_channel', $site_channel); set_config('system','maximagesize', $maximagesize); set_config('system','register_policy', $register_policy); @@ -385,27 +350,32 @@ function admin_page_site(&$a) { } /* Installed themes */ - $theme_choices = array(); - $theme_choices_mobile = array(); - $theme_choices_mobile["---"] = t("No special theme for mobile devices"); - $theme_choices_accessibility = array(); - $theme_choices_accessibility["---"] =t("No special theme for accessibility"); - $files = glob('view/theme/*'); - if($files) { - foreach($files as $file) { - $f = basename($file); - $theme_name = ((file_exists($file . '/experimental')) ? sprintf("%s - Experimental", $f) : $f); - if (file_exists($file . '/mobile')) { - $theme_choices_mobile[$f] = $theme_name; - } - if (file_exists($file . '/accessibility')) { - $theme_choices_accessibility[$f] = $theme_name; + $theme_choices_mobile["---"] = t("Default"); + $theme_choices = array(); + $files = glob('view/theme/*'); + if($files) { + foreach($files as $file) { + $vars = ''; + $f = basename($file); + if (file_exists($file . '/library')) + continue; + if (file_exists($file . '/mobile')) + $vars = t('mobile'); + if (file_exists($file . '/experimental')) + $vars .= t('experimental'); + if (file_exists($file . '/unsupported')) + $vars .= t('unsupported'); + if ($vars) { + $theme_choices[$f] = $f . ' (' . $vars . ')'; + $theme_choices_mobile[$f] = $f . ' (' . $vars . ')'; } - $theme_choices[$f] = $theme_name; - } - } - - + else { + $theme_choices[$f] = $f; + $theme_choices_mobile[$f] = $f; + } + } + } + /* Banner */ $banner = get_config('system','banner'); if($banner == false) @@ -453,9 +423,9 @@ function admin_page_site(&$a) { '$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), - '$theme_accessibility' => array('theme_accessibility', t("Accessibility system theme"), get_config('system','accessibility_theme'), t("Accessibility theme"), $theme_choices_accessibility), - '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")), -// '$ssl_policy' => array('ssl_policy', t("SSL link policy"), (string) intval(get_config('system','ssl_policy')), t("Determines whether generated links should be forced to use SSL"), $ssl_choices), +// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")), + '$diaspora_enabled' => array('diaspora_enabled',t('Enable Diaspora Protocol'), get_config('system','diaspora_enabled'), t('Communicate with Diaspora and Friendica - experimental')), + '$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), '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices), @@ -464,6 +434,7 @@ function admin_page_site(&$a) { '$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")), '$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")), '$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")), + '$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("Disable discovery tab"), get_config('system','disable_discover_tab'), t("Remove the tab in the network view with public content pulled from sources chosen for this site.")), '$no_login_on_homepage' => array('no_login_on_homepage', t("No login on Homepage"), get_config('system','no_login_on_homepage'), t("Check to hide the login form from your sites homepage when visitors arrive who are not logged in (e.g. when you put the content of the homepage in via the site channel).")), @@ -620,7 +591,7 @@ function admin_page_users_post(&$a){ if (x($_POST,'page_users_block')){ foreach($users as $uid){ - q("UPDATE account SET account_flags = (account_flags & %d) where account_id = %d limit 1", + q("UPDATE account SET account_flags = (account_flags & %d) where account_id = %d", intval(ACCOUNT_BLOCKED), intval( $uid ) ); @@ -630,19 +601,17 @@ function admin_page_users_post(&$a){ if (x($_POST,'page_users_delete')){ require_once("include/Contact.php"); foreach($users as $uid){ - account_remove($uid,true); + account_remove($uid,true,false); } notice( sprintf( tt("%s user deleted", "%s users deleted", count($users)), count($users)) ); } if (x($_POST,'page_users_approve')){ - require_once('include/account.php'); foreach($pending as $hash){ user_allow($hash); } } if (x($_POST,'page_users_deny')){ - require_once('include/account.php'); foreach($pending as $hash){ user_deny($hash); } @@ -672,13 +641,13 @@ function admin_page_users(&$a){ check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); // delete user require_once("include/Contact.php"); - account_remove($uid,true); + account_remove($uid,true,false); notice( sprintf(t("User '%s' deleted"), $account[0]['account_email']) . EOL); }; break; case "block":{ check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); - q("UPDATE account SET account_flags = ( account_flags ^ %d ) where account_id = %d", + q("UPDATE account SET account_flags = ( account_flags & ~%d ) where account_id = %d", intval(ACCOUNT_BLOCKED), intval( $uid ) ); @@ -692,13 +661,13 @@ function admin_page_users(&$a){ } /* get pending */ - $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) ", + $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ", intval(ACCOUNT_PENDING) ); /* get users */ - $total = q("SELECT count(*) as total FROM account where 1"); + $total = q("SELECT count(*) as total FROM account"); if(count($total)) { $a->set_pager_total($total[0]['total']); $a->set_pager_itemspage(100); @@ -715,15 +684,18 @@ function admin_page_users(&$a){ $order = " order by account_email asc "; if($_REQUEST['order'] === 'expires') $order = " order by account_expires desc "; - - $users =q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d ) > 0 as `blocked`, " . - "(SELECT GROUP_CONCAT( ch.channel_address SEPARATOR ' ') FROM channel as ch " . - "WHERE ch.channel_account_id = ac.account_id and not (ch.channel_pageflags & %d )) as `channels` " . - "FROM account as ac where true $serviceclass $order limit %d , %d ", + if($_REQUEST['order'] === 'created') + $order = " order by account_created desc "; + + $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 not (ch.channel_pageflags & %d )>0) as `channels` " . + "FROM account as ac where true $serviceclass $order limit %d offset %d ", intval(ACCOUNT_BLOCKED), + db_concat('ch.channel_address', ' '), intval(PAGE_REMOVED), - intval($a->pager['start']), - intval($a->pager['itemspage']) + intval($a->pager['itemspage']), + intval($a->pager['start']) ); // function _setup_users($e){ @@ -790,13 +762,13 @@ function admin_page_channels_post(&$a){ if (x($_POST,'page_channels_block')){ foreach($channels as $uid){ - q("UPDATE channel SET channel_pageflags = ( channel_pageflags ^ %d ) where channel_id = %d", + q("UPDATE channel SET channel_pageflags = ( channel_pageflags & ~%d ) where channel_id = %d", intval(PAGE_CENSORED), intval( $uid ) ); proc_run('php','include/directory.php',$uid,'nopush'); } - notice( sprintf( tt("%s channel censored/uncensored", "%s channelss censored/uncensored", count($channels)), count($channels)) ); + notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) ); } if (x($_POST,'page_channels_delete')){ require_once("include/Contact.php"); @@ -838,10 +810,11 @@ function admin_page_channels(&$a){ case "block":{ check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't'); - q("UPDATE channel SET channel_pageflags = ( channel_pageflags ^ %d ) where channel_id = %d", + q("UPDATE channel SET channel_pageflags = ( channel_pageflags & ~%d ) where channel_id = %d", intval(PAGE_CENSORED), intval( $uid ) ); + proc_run('php','include/directory.php',$uid,'nopush'); notice( sprintf( (($channel[0]['channel_pageflags'] & PAGE_CENSORED) ? t("Channel '%s' uncensored"): t("Channel '%s' censored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL); }; break; @@ -853,7 +826,7 @@ function admin_page_channels(&$a){ /* get channels */ - $total = q("SELECT count(*) as total FROM channel where not (channel_pageflags & %d)", + $total = q("SELECT count(*) as total FROM channel where not (channel_pageflags & %d)>0", intval(PAGE_REMOVED) ); if($total) { @@ -863,10 +836,10 @@ function admin_page_channels(&$a){ $order = " order by channel_name asc "; - $channels = q("SELECT * from channel where not ( channel_pageflags & %d ) $order limit %d , %d ", + $channels = q("SELECT * from channel where not ( channel_pageflags & %d )>0 $order limit %d offset %d ", intval(PAGE_REMOVED), - intval($a->pager['start']), - intval($a->pager['itemspage']) + intval($a->pager['itemspage']), + intval($a->pager['start']) ); if($channels) { @@ -1317,3 +1290,80 @@ readable."); )); } +function admin_page_profs_post(&$a) { + + if($_REQUEST['id']) { + $r = q("update profdef set field_name = '%s', field_type = '%s', field_desc = '%s' field_help = '%s', field_inputs = '%s' where id = %d", + dbesc($_REQUEST['field_name']), + dbesc($_REQUEST['field_type']), + dbesc($_REQUEST['field_desc']), + dbesc($_REQUEST['field_help']), + dbesc($_REQUEST['field_inputs']), + intval($_REQUEST['id']) + ); + } + else { + $r = q("insert into profdef ( field_name, field_type, field_desc, field_help, field_inputs ) values ( '%s' , '%s', '%s', '%s', '%s' )", + dbesc($_REQUEST['field_name']), + dbesc($_REQUEST['field_type']), + dbesc($_REQUEST['field_desc']), + dbesc($_REQUEST['field_help']), + dbesc($_REQUEST['field_inputs']) + ); + } + + // add to chosen array basic or advanced + + goaway(z_root() . '/admin/profs'); + +} + +function admin_page_profs(&$a) { + + if((argc() > 3) && argv(2) == 'drop' && intval(argv(3))) { + $r = q("delete from profdef where id = %d", + intval(argv(3)) + ); + // remove from allowed fields + + goaway(z_root() . '/admin/profs'); + } + + if((argc() > 2) && argv(2) === 'new') { + return replace_macros(get_markup_template('profdef_edit.tpl'),array( + '$header' => t('New Profile Field'), + '$field_name' => array('field_name',t('Field nickname'),$_REQUEST['field_name'],t('System name of field')), + '$field_type' => array('field_type',t('Input type'),(($_REQUEST['field_type']) ? $_REQUEST['field_type'] : 'text'),''), + '$field_desc' => array('field_desc',t('Field Name'),$_REQUEST['field_desc'],t('Label on profile pages')), + '$field_help' => array('field_help',t('Help text'),$_REQUEST['field_help'],t('Additional info (optional)')), + '$submit' => t('Save') + )); + + } + + if((argc() > 2) && intval(argv(2))) { + $r = q("select * from profdef where id = %d limit 1", + intval(argv(2)) + ); + if(! $r) { + notice( t('Field definition not found') . EOL); + goaway(z_root() . '/admin/profs'); + } + + return replace_macros(get_markup_template('profdef_edit.tpl'),array( + '$id' => intval($r[0]['id']), + '$header' => t('Edit Profile Field'), + '$field_name' => array('field_name',t('Field nickname'),$r[0]['field_name'],t('System name of field')), + '$field_type' => array('field_type',t('Input type'),$r[0]['field_type'],''), + '$field_desc' => array('field_desc',t('Field Name'),$r[0]['field_desc'],t('Label on profile pages')), + '$field_help' => array('field_help',t('Help text'),$r[0]['field_help'],t('Additional info (optional)')), + '$submit' => t('Save') + )); + } + +} + + + + + diff --git a/mod/apps.php b/mod/apps.php index 07d1968d2..8c9706d2f 100644 --- a/mod/apps.php +++ b/mod/apps.php @@ -30,6 +30,7 @@ function apps_content(&$a) { } return replace_macros(get_markup_template('myapps.tpl'), array( + '$sitename' => get_config('system','sitename'), '$title' => t('Apps'), '$apps' => $apps, )); diff --git a/mod/blocks.php b/mod/blocks.php index 74a980c25..6237a645b 100644 --- a/mod/blocks.php +++ b/mod/blocks.php @@ -1,103 +1,140 @@ <?php -function blocks_content(&$a) { +require_once('include/identity.php'); +require_once('include/conversation.php'); +require_once('include/acl_selectors.php'); +function blocks_init(&$a) { + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } if(argc() > 1) $which = argv(1); - else { + else + return; + + profile_load($a,$which); + +} + + +function blocks_content(&$a) { + + if(! $a->profile) { notice( t('Requested profile is not available.') . EOL ); $a->error = 404; return; } - profile_load($a,$which,0); + $which = argv(1); + $uid = local_user(); + $owner = 0; + $channel = null; + $observer = $a->get_observer(); - // Figure out who the page owner is. - $r = q("select channel_id from channel where channel_address = '%s'", - dbesc($which) - ); - if($r) { - $owner = intval($r[0]['channel_id']); + $channel = $a->get_channel(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } } - // Block design features from visitors + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) + ); + if($r) { + $owner = intval($r[0]['channel_id']); + } + } + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + $perms = get_all_perms($owner,$ob_hash); - if((! local_user()) || (local_user() != $owner)) { + if(! $perms['write_pages']) { notice( t('Permission denied.') . EOL); return; } + // Block design features from visitors + if((! $uid) || ($uid != $owner)) { + notice( t('Permission denied.') . EOL); + return; + } -// Get the observer, check their permissions - - $observer = $a->get_observer(); - $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - - $perms = get_all_perms($owner,$ob_hash); - if(! $perms['write_pages']) { - notice( t('Permission denied.') . EOL); - return; - } + if(feature_enabled($owner,'expert')) { + $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); + if(! $mimetype) + $mimetype = 'choose'; + } + else { + $mimetype = 'text/bbcode'; + } -// if(local_user() && local_user() == $owner) { - // $a->set_widget('design',design_tools()); - // } + $x = array( + 'webpage' => ITEM_BUILDBLOCK, + 'is_owner' => true, + 'nickname' => $a->profile['channel_address'], + 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'bang' => '', + 'showacl' => false, + 'visitor' => true, + 'mimetype' => $mimetype, + 'ptlabel' => t('Block Name'), + 'profile_uid' => intval($owner), + ); + if($_REQUEST['title']) + $x['title'] = $_REQUEST['title']; + if($_REQUEST['body']) + $x['body'] = $_REQUEST['body']; + if($_REQUEST['pagetitle']) + $x['pagetitle'] = $_REQUEST['pagetitle']; -// Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages -// Nickname is set to the observers xchan, and profile_uid to the owners. This lets you post pages at other people's channels. -require_once ('include/conversation.php'); - $x = array( - 'webpage' => ITEM_BUILDBLOCK, - 'is_owner' => true, - 'nickname' => $a->profile['channel_address'], - 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'bang' => (($group || $cid) ? '!' : ''), - 'showacl' => false, - 'visitor' => true, - 'mimetype' => 'choose', - 'ptlabel' => t('Block Name'), - 'profile_uid' => intval($owner), - ); - $o .= status_editor($a,$x); - //Get a list of blocks. We can't display all them because endless scroll makes that unusable, so just list titles and an edit link. -//TODO - this should be replaced with pagelist_widget + $o .= status_editor($a,$x); -$r = q("select * from item_id where uid = %d and service = 'BUILDBLOCK' order by sid asc", - intval($owner) -); + $r = q("select * from item_id where uid = %d and service = 'BUILDBLOCK' order by sid asc", + intval($owner) + ); - $pages = null; + $pages = null; - if($r) { - $pages = array(); - foreach($r as $rr) { - $pages[$rr['iid']][] = array('url' => $rr['iid'],'title' => $rr['sid']); - } - } + if($r) { + $pages = array(); + foreach($r as $rr) { + $pages[$rr['iid']][] = array('url' => $rr['iid'],'title' => $rr['sid']); + } + } + //Build the base URL for edit links + $url = z_root() . '/editblock/' . $which; -//Build the base URL for edit links - $url = z_root() . "/editblock/" . $which; -// This isn't pretty, but it works. Until I figure out what to do with the UI, it's Good Enough(TM). - return $o . replace_macros(get_markup_template("blocklist.tpl"), array( + $o .= replace_macros(get_markup_template('blocklist.tpl'), array( '$baseurl' => $url, '$edit' => t('Edit'), '$pages' => $pages, '$channel' => $which, '$view' => t('View'), '$preview' => '1', - - )); + )); - + return $o; } diff --git a/mod/bookmarks.php b/mod/bookmarks.php index 9ccc171fe..6b2476a8e 100644 --- a/mod/bookmarks.php +++ b/mod/bookmarks.php @@ -55,6 +55,8 @@ function bookmarks_content(&$a) { $o = profile_tabs($a,true,$channel['channel_address']); + $o .= '<div class="generic-content-wrapper-styled">'; + $o .= '<h3>' . t('My Bookmarks') . '</h3>'; $x = menu_list(local_user(),'',MENU_BOOKMARK); @@ -78,7 +80,7 @@ function bookmarks_content(&$a) { } } - + $o .= '</div>'; return $o; diff --git a/mod/chanman.php b/mod/chanman.php deleted file mode 100644 index 7a89708d7..000000000 --- a/mod/chanman.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php /** @file */ - - -/** - Placeholder file at present. This is going to involve a bit of work. - - This file will deal with the deletion of channels and management of hublocs. - - We need to provide the following functionality: - - - Delete my account and all channels from the entire network - - - Delete my account and all channels from this server - - - Delete a channel from the entire network - - - Delete a channel from this server - - - List all hub locations for this channel - - - Remove this/some hub location from this channel - - - promote this/some hub location to primary - - - Remove hub location 'xyz' from this channel, (this should possibly only be allowed if that hub has been down for a period of time) - - - Some of these actions should probably require email verification - -*/ - - diff --git a/mod/channel.php b/mod/channel.php index 395160d2c..e819de0e0 100644 --- a/mod/channel.php +++ b/mod/channel.php @@ -47,7 +47,7 @@ function channel_content(&$a, $update = 0, $load = false) { $category = $datequery = $datequery2 = ''; - $mid = $_GET['mid']; + $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : ''); $datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); $datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : ''); @@ -57,6 +57,7 @@ function channel_content(&$a, $update = 0, $load = false) { } $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : ''); + $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); $groups = array(); @@ -64,7 +65,7 @@ function channel_content(&$a, $update = 0, $load = false) { if($update) { // Ensure we've got a profile owner if updating. - $a->profile['profile_uid'] = $update; + $a->profile['profile_uid'] = $a->profile_uid = $update; } else { if($a->profile['profile_uid'] == local_user()) { @@ -137,21 +138,26 @@ function channel_content(&$a, $update = 0, $load = false) { $sql_extra = item_permissions_sql($a->profile['profile_uid'],$remote_contact,$groups); + if(get_pconfig($a->profile['profile_uid'],'system','channel_list_mode') && (! $mid)) + $page_mode = 'list'; + else + $page_mode = 'client'; + if(($update) && (! $load)) { if ($mid) { $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d AND item_restrict = 0 - AND (item_flags & %d) AND (item_flags & %d) $sql_extra limit 1", + AND (item_flags & %d) > 0 AND (item_flags & %d) > 0 $sql_extra limit 1", dbesc($mid), intval($a->profile['profile_uid']), intval(ITEM_WALL), intval(ITEM_UNSEEN) ); } else { - $r = q("SELECT distinct parent AS `item_id` from item + $r = q("SELECT distinct parent AS `item_id`, created from item left join abook on item.author_xchan = abook.abook_xchan WHERE uid = %d AND item_restrict = 0 - AND (item_flags & %d) AND ( item_flags & %d ) + AND (item_flags & %d) > 0 AND ( item_flags & %d ) > 0 AND ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) $sql_extra ORDER BY created DESC", @@ -165,10 +171,12 @@ function channel_content(&$a, $update = 0, $load = false) { } else { - if(x($category)) { $sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY)); } + if(x($hashtags)) { + $sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG)); + } if($datequery) { $sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery)))); @@ -179,12 +187,12 @@ function channel_content(&$a, $update = 0, $load = false) { $itemspage = get_pconfig(local_user(),'system','itemspage'); $a->set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage'])); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($a->pager['itemspage']), intval($a->pager['start'])); if($load || ($_COOKIE['jsAvailable'] != 1)) { if ($mid) { $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d AND item_restrict = 0 - AND (item_flags & %d) $sql_extra limit 1", + AND (item_flags & %d)>0 $sql_extra limit 1", dbesc($mid), intval($a->profile['profile_uid']), intval(ITEM_WALL) @@ -194,10 +202,10 @@ function channel_content(&$a, $update = 0, $load = false) { } } else { - $r = q("SELECT distinct id AS item_id FROM item + $r = q("SELECT distinct id AS item_id, created FROM item left join abook on item.author_xchan = abook.abook_xchan WHERE uid = %d AND item_restrict = 0 - AND (item_flags & %d) and (item_flags & %d) + AND (item_flags & %d)>0 and (item_flags & %d)>0 AND ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) $sql_extra $sql_extra2 ORDER BY created DESC $pager_sql ", @@ -246,9 +254,14 @@ function channel_content(&$a, $update = 0, $load = false) { // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. + $maxheight = get_pconfig($a->profile['profile_uid'],'system','channel_divmore_height'); + if(! $maxheight) + $maxheight = 400; + $o .= '<div id="live-channel"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . $a->profile['profile_uid'] - . "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n"; + . "; var netargs = '?f='; var profile_page = " . $a->pager['page'] + . "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; $a->page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( '$baseurl' => z_root(), @@ -271,6 +284,7 @@ function channel_content(&$a, $update = 0, $load = false) { '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$file' => '', '$cats' => (($category) ? $category : ''), + '$tags' => (($hashtags) ? $hashtags : ''), '$mid' => $mid, '$dend' => $datequery, '$dbegin' => $datequery2 @@ -279,12 +293,31 @@ function channel_content(&$a, $update = 0, $load = false) { } + $update_unseen = ''; + + if($page_mode === 'list') { + /** + * in "list mode", only mark the parent item and any like activities as "seen". + * We won't distinguish between comment likes and post likes. The important thing + * is that the number of unseen comments will be accurate. The SQL to separate the + * comment likes could also get somewhat hairy. + */ - if($is_owner) { + if($parents_str) { + $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; + $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; + } + } + else { + if($parents_str) { + $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; + } + } - $r = q("UPDATE item SET item_flags = (item_flags ^ %d) - WHERE (item_flags & %d) AND (item_flags & %d) AND uid = %d ", + if($is_owner && $update_unseen) { + $r = q("UPDATE item SET item_flags = (item_flags & ~%d) + WHERE (item_flags & %d) > 0 AND (item_flags & %d) > 0 AND uid = %d $update_unseen", intval(ITEM_UNSEEN), intval(ITEM_UNSEEN), intval(ITEM_WALL), @@ -294,7 +327,7 @@ function channel_content(&$a, $update = 0, $load = false) { if($_COOKIE['jsAvailable'] == 1) { - $o .= conversation($a,$items,'channel',$update,'client'); + $o .= conversation($a,$items,'channel',$update,$page_mode); } else { $o .= conversation($a,$items,'channel',$update,'traditional'); } diff --git a/mod/chanview.php b/mod/chanview.php index 449a98bb1..3bf0f3268 100644 --- a/mod/chanview.php +++ b/mod/chanview.php @@ -74,15 +74,19 @@ function chanview_content(&$a) { } if(! $a->poi) { - notice( t('Channel not found.') . EOL); - return; +// We don't know who this is, and we can't figure it out from the URL +// On the plus side, there's a good chance we know somebody else at that +// hub so sending them there with a Zid will probably work anyway. + $url = ($_REQUEST['url']); + if($observer) + $url = zid($url); } - + if ($a->poi) { $url = $a->poi['xchan_url']; if($observer) $url = zid($url); - + } // let somebody over-ride the iframed viewport presentation // or let's just declare this a failed experiment. @@ -97,4 +101,4 @@ function chanview_content(&$a) { // return $o; -}
\ No newline at end of file +} diff --git a/mod/chatsvc.php b/mod/chatsvc.php index 43aa3d3c0..44225e6dd 100644 --- a/mod/chatsvc.php +++ b/mod/chatsvc.php @@ -73,7 +73,7 @@ function chatsvc_content(&$a) { intval($a->data['chat']['uid']) ); - $r = q("update chatpresence set cp_status = '%s', cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s' limit 1", + $r = q("update chatpresence set cp_status = '%s', cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'", dbesc($status), dbesc(datetime_convert()), intval($room_id), @@ -141,7 +141,7 @@ function chatsvc_content(&$a) { } } - $r = q("update chatpresence set cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s' limit 1", + $r = q("update chatpresence set cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'", dbesc(datetime_convert()), intval($a->data['chat']['room_id']), dbesc(get_observer_hash()), diff --git a/mod/cloud.php b/mod/cloud.php index 3734f769a..27724f6b0 100644 --- a/mod/cloud.php +++ b/mod/cloud.php @@ -1,31 +1,35 @@ <?php /** * @file mod/cloud.php - * @brief Initialize Red Matrix's cloud (SabreDAV) + * @brief Initialize RedMatrix's cloud (SabreDAV). * + * Module for accessing the DAV storage area. */ - use Sabre\DAV; - require_once('vendor/autoload.php'); +use Sabre\DAV; +use RedMatrix\RedDAV; - // workaround for HTTP-auth in CGI mode - if(x($_SERVER,'REDIRECT_REMOTE_USER')) { - $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; - if(strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } - } +// composer autoloader for SabreDAV +require_once('vendor/autoload.php'); - if(x($_SERVER,'HTTP_AUTHORIZATION')) { - $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; - if(strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } +// workaround for HTTP-auth in CGI mode +if (x($_SERVER, 'REDIRECT_REMOTE_USER')) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; } +} + +if (x($_SERVER, 'HTTP_AUTHORIZATION')) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } +} /** * @brief Fires up the SabreDAV server. @@ -33,54 +37,61 @@ * @param App &$a */ function cloud_init(&$a) { + // call ($currenttheme)_init since we're operating outside of index.php + $theme_info_file = "view/theme/" . current_theme() . "/php/theme.php"; + if (file_exists($theme_info_file)){ + require_once($theme_info_file); + if (function_exists(str_replace('-', '_', current_theme()) . '_init')) { + $func = str_replace('-', '_', current_theme()) . '_init'; + $func($a); + } + } require_once('include/reddav.php'); - if(! is_dir('store')) - os_mkdir('store',STORAGE_DEFAULT_PERMISSIONS,false); + if (! is_dir('store')) + os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false); $which = null; - if(argc() > 1) + if (argc() > 1) $which = argv(1); $profile = 0; - $channel = $a->get_channel(); - $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/feed/' . $which . '" />' . "\r\n" ; + $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/feed/' . $which . '" />' . "\r\n"; - if($which) + if ($which) profile_load($a, $which, $profile); - $auth = new RedBasicAuth(); + $auth = new RedDAV\RedBasicAuth(); $ob_hash = get_observer_hash(); - if($ob_hash) { - if(local_user()) { + if ($ob_hash) { + if (local_user()) { $channel = $a->get_channel(); $auth->setCurrentUser($channel['channel_address']); - $auth->channel_name = $channel['channel_address']; $auth->channel_id = $channel['channel_id']; $auth->channel_hash = $channel['channel_hash']; $auth->channel_account_id = $channel['channel_account_id']; if($channel['channel_timezone']) - $auth->timezone = $channel['channel_timezone']; + $auth->setTimezone($channel['channel_timezone']); } $auth->observer = $ob_hash; } - if($_GET['davguest']) + if ($_GET['davguest']) $_SESSION['davguest'] = true; - $_SERVER['QUERY_STRING'] = str_replace(array('?f=','&f='),array('',''),$_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']); $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']); - $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism','',$_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']); - $_SERVER['REQUEST_URI'] = str_replace(array('?f=','&f='),array('',''),$_SERVER['REQUEST_URI']); + $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']); $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']); - $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism','',$_SERVER['REQUEST_URI']); + $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']); - $rootDirectory = new RedDirectory('/', $auth); + $rootDirectory = new RedDAV\RedDirectory('/', $auth); // A SabreDAV server-object $server = new DAV\Server($rootDirectory); @@ -90,46 +101,53 @@ function cloud_init(&$a) { $server->addPlugin($lockPlugin); - // The next section of code allows us to bypass prompting for http-auth if a FILE is being accessed anonymously and permissions - // allow this. This way one can create hotlinks to public media files in their cloud and anonymous viewers won't get asked to login. - // If a DIRECTORY is accessed or there are permission issues accessing the file and we aren't previously authenticated via zot, - // prompt for HTTP-auth. This will be the default case for mounting a DAV directory. - // In order to avoid prompting for passwords for viewing a DIRECTORY, add the URL query parameter 'davguest=1' + // The next section of code allows us to bypass prompting for http-auth if a + // FILE is being accessed anonymously and permissions allow this. This way + // one can create hotlinks to public media files in their cloud and anonymous + // viewers won't get asked to login. + // If a DIRECTORY is accessed or there are permission issues accessing the + // file and we aren't previously authenticated via zot, prompt for HTTP-auth. + // This will be the default case for mounting a DAV directory. + // In order to avoid prompting for passwords for viewing a DIRECTORY, add + // the URL query parameter 'davguest=1'. $isapublic_file = false; $davguest = ((x($_SESSION, 'davguest')) ? true : false); - if((! $auth->observer) && ($_SERVER['REQUEST_METHOD'] === 'GET')) { + if ((! $auth->observer) && ($_SERVER['REQUEST_METHOD'] === 'GET')) { try { $x = RedFileData('/' . $a->cmd, $auth); - if($x instanceof RedFile) + if($x instanceof RedDAV\RedFile) $isapublic_file = true; } - catch ( Exception $e ) { + catch (Exception $e) { $isapublic_file = false; } } - if((! $auth->observer) && (! $isapublic_file) && (! $davguest)) { + if ((! $auth->observer) && (! $isapublic_file) && (! $davguest)) { try { - $auth->Authenticate($server, t('Red Matrix - Guests: Username: {your email address}, Password: +++')); + $auth->Authenticate($server, t('RedMatrix - Guests: Username: {your email address}, Password: +++')); } - catch ( Exception $e) { + catch (Exception $e) { logger('mod_cloud: auth exception' . $e->getMessage()); http_status_exit($e->getHTTPCode(), $e->getMessage()); } } - + require_once('include/RedDAV/RedBrowser.php'); // provide a directory view for the cloud in Red Matrix - $browser = new RedBrowser($auth); - + $browser = new RedDAV\RedBrowser($auth); $auth->setBrowserPlugin($browser); $server->addPlugin($browser); + // Experimental QuotaPlugin +// require_once('include/RedDAV/QuotaPlugin.php'); +// $server->addPlugin(new RedDAV\QuotaPlugin($auth)); + // All we need to do now, is to fire up the server $server->exec(); killme(); -}
\ No newline at end of file +} diff --git a/mod/connect.php b/mod/connect.php index f7748bcaf..396fca645 100644 --- a/mod/connect.php +++ b/mod/connect.php @@ -38,7 +38,8 @@ function connect_post(&$a) { $text = escape_tags($_POST['text']); if($has_premium != $premium) { - $r = q("update channel set channel_pageflags = ( channel_pageflags ^ %d ) where channel_id = %d limit 1", + $r = q("update channel set channel_pageflags = ( channel_pageflags %s %d ) where channel_id = %d", + db_getfunc('^'), intval(PAGE_PREMIUM), intval(local_user()) ); diff --git a/mod/connections.php b/mod/connections.php index 1875ed908..70e28913a 100644 --- a/mod/connections.php +++ b/mod/connections.php @@ -81,7 +81,7 @@ function connections_post(&$a) { } $r = q("UPDATE abook SET abook_profile = '%s', abook_my_perms = %d , abook_closeness = %d, abook_flags = %d - where abook_id = %d AND abook_channel = %d LIMIT 1", + where abook_id = %d AND abook_channel = %d", dbesc($profile_id), intval($abook_my_perms), intval($closeness), @@ -213,7 +213,7 @@ function connections_content(&$a) { nav_set_selected('intros'); break; case 'ifpending': - $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) and not ((abook_flags & %d) or (xchan_flags & %d))", + $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d)>0 and not ((abook_flags & %d)>0 or (xchan_flags & %d)>0)", intval(local_user()), intval(ABOOK_FLAG_PENDING), intval(ABOOK_FLAG_SELF|ABOOK_FLAG_IGNORED), @@ -250,13 +250,13 @@ function connections_content(&$a) { } - $sql_extra = (($search_flags) ? " and ( abook_flags & " . $search_flags . " ) " : ""); + $sql_extra = (($search_flags) ? " and ( abook_flags & " . $search_flags . " )>0 " : ""); if(argv(1) === 'pending') - $sql_extra .= " and not ( abook_flags & " . ABOOK_FLAG_IGNORED . " ) "; + $sql_extra .= " and not ( abook_flags & " . ABOOK_FLAG_IGNORED . " )>0 "; } else { - $sql_extra = " and not ( abook_flags & " . ABOOK_FLAG_BLOCKED . " ) "; + $sql_extra = " and not ( abook_flags & " . ABOOK_FLAG_BLOCKED . " )>0 "; $unblocked = true; } @@ -337,9 +337,12 @@ function connections_content(&$a) { } $sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : ""); + if($_REQUEST['gid']) { + $sql_extra .= " and xchan_hash in ( select xchan from group_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_user()) . " ) "; + } $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash - where abook_channel = %d and not (abook_flags & %d) and not (xchan_flags & %d ) $sql_extra $sql_extra2 ", + where abook_channel = %d and not (abook_flags & %d)>0 and not (xchan_flags & %d )>0 $sql_extra $sql_extra2 ", intval(local_user()), intval(ABOOK_FLAG_SELF), intval(XCHAN_FLAGS_DELETED|XCHAN_FLAGS_ORPHAN) @@ -350,12 +353,12 @@ function connections_content(&$a) { } $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash - WHERE abook_channel = %d and not (abook_flags & %d) and not ( xchan_flags & %d) $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d , %d ", + WHERE abook_channel = %d and not (abook_flags & %d)>0 and not ( xchan_flags & %d)>0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ", intval(local_user()), intval(ABOOK_FLAG_SELF), intval(XCHAN_FLAGS_DELETED|XCHAN_FLAGS_ORPHAN), - intval($a->pager['start']), - intval($a->pager['itemspage']) + intval($a->pager['itemspage']), + intval($a->pager['start']) ); $contacts = array(); @@ -366,7 +369,7 @@ function connections_content(&$a) { if($rr['xchan_url']) { $contacts[] = array( 'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']), - 'edit_hover' => t('Edit contact'), + 'edit_hover' => t('Edit connection'), 'id' => $rr['abook_id'], 'alt_text' => $alt_text, 'dir_icon' => $dir_icon, @@ -375,6 +378,7 @@ function connections_content(&$a) { 'username' => $rr['xchan_name'], 'classes' => (($rr['abook_flags'] & ABOOK_FLAG_ARCHIVED) ? 'archived' : ''), 'link' => z_root() . '/connedit/' . $rr['abook_id'], + 'edit' => t('Edit'), 'url' => chanlink_url($rr['xchan_url']), 'network' => network_to_name($rr['network']), ); @@ -382,20 +386,40 @@ function connections_content(&$a) { } } - $o .= replace_macros(get_markup_template('connections.tpl'),array( - '$header' => t('Connections') . (($head) ? ' - ' . $head : ''), - '$tabs' => $t, - '$total' => $total, - '$search' => $search_hdr, - '$desc' => t('Search your connections'), - '$finding' => (($searching) ? t('Finding: ') . "'" . $search . "'" : ""), - '$submit' => t('Find'), - '$edit' => t('Edit'), - '$cmd' => $a->cmd, - '$contacts' => $contacts, - '$paginate' => paginate($a), - - )); - + + if($_REQUEST['aj']) { + if($contacts) { + $o = replace_macros(get_markup_template('contactsajax.tpl'),array( + '$contacts' => $contacts, + '$edit' => t('Edit'), + )); + } + else { + $o = '<div id="content-complete"></div>'; + } + echo $o; + killme(); + } + else { + $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>"; + $o .= replace_macros(get_markup_template('connections.tpl'),array( + '$header' => t('Connections') . (($head) ? ' - ' . $head : ''), + '$tabs' => $t, + '$total' => $total, + '$search' => $search_hdr, + '$desc' => t('Search your connections'), + '$finding' => (($searching) ? t('Finding: ') . "'" . $search . "'" : ""), + '$submit' => t('Find'), + '$edit' => t('Edit'), + '$cmd' => $a->cmd, + '$contacts' => $contacts, + '$paginate' => paginate($a), + + )); + } + + if(! $contacts) + $o .= '<div id="content-complete"></div>'; + return $o; } diff --git a/mod/connedit.php b/mod/connedit.php index b9f0299e2..6729029ac 100644 --- a/mod/connedit.php +++ b/mod/connedit.php @@ -68,6 +68,14 @@ function connedit_post(&$a) { call_hooks('contact_edit_post', $_POST); + if($orig_record[0]['abook_flags'] & ABOOK_FLAG_SELF) { + $autoperms = intval($_POST['autoperms']); + } + else { + $autoperms = null; + } + + $profile_id = $_POST['profile_assign']; if($profile_id) { $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND `uid` = %d LIMIT 1", @@ -109,7 +117,7 @@ function connedit_post(&$a) { } $r = q("UPDATE abook SET abook_profile = '%s', abook_my_perms = %d , abook_closeness = %d, abook_flags = %d - where abook_id = %d AND abook_channel = %d LIMIT 1", + where abook_id = %d AND abook_channel = %d", dbesc($profile_id), intval($abook_my_perms), intval($closeness), @@ -118,13 +126,14 @@ function connedit_post(&$a) { intval(local_user()) ); - if($orig_record[0]['abook_profile'] != $profile_id) { //Update profile photo permissions + if($orig_record[0]['abook_profile'] != $profile_id) { + //Update profile photo permissions - logger('As a new profile was assigned updateing profile photos'); - require_once('mod/profile_photo.php'); - profile_photo_set_profile_perms($profile_id); + logger('A new profile was assigned - updating profile photos'); + require_once('mod/profile_photo.php'); + profile_photo_set_profile_perms($profile_id); - } + } if($r) @@ -147,12 +156,44 @@ function connedit_post(&$a) { group_add_member(local_user(),'',$a->poi['abook_xchan'],$g['id']); } - - // Check if settings permit ("post new friend activity" is allowed, and // friends in general or this friend in particular aren't hidden) // and send out a new friend activity - // TODO + + $pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0", + intval($channel['channel_id']) + ); + if(($pr) && (! ($abook_flags & ABOOK_FLAG_HIDDEN)) + && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) { + $xarr = array(); + $xarr['verb'] = ACTIVITY_FRIEND; + $xarr['item_flags'] = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP; + $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash']; + $xarr['allow_cid'] = $channel['channel_allow_cid']; + $xarr['allow_gid'] = $channel['channel_allow_gid']; + $xarr['deny_cid'] = $channel['channel_deny_cid']; + $xarr['deny_gid'] = $channel['channel_deny_gid']; + $xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0); + $obj = array( + 'type' => ACTIVITY_OBJ_PERSON, + 'title' => $a->poi['xchan_name'], + 'id' => $a->poi['xchan_hash'], + 'link' => array( + array('rel' => 'alternate', 'type' => 'text/html', 'href' => $a->poi['xchan_url']), + array('rel' => 'photo', 'type' => $a->poi['xchan_photo_mimetype'], 'href' => $a->poi['xchan_photo_l']) + ), + ); + $xarr['object'] = json_encode($obj); + $xarr['obj_type'] = ACTIVITY_OBJ_PERSON; + + $xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $a->poi['xchan_url'] . ']' . $a->poi['xchan_name'] . '[/zrl]'; + + $xarr['body'] .= "\n\n\n" . '[zrl=' . $a->poi['xchan_url'] . '][zmg=80x80]' . $a->poi['xchan_photo_m'] . '[/zmg][/zrl]'; + + post_activity_item($xarr); + + } + // pull in a bit of content if there is any to pull in proc_run('php','include/onepoll.php',$contact_id); @@ -175,6 +216,10 @@ function connedit_post(&$a) { $arr = array('channel_id' => local_user(), 'abook' => $a->poi); call_hooks('accept_follow', $arr); } +dbg(1); + if(! is_null($autoperms)) + set_pconfig(local_user(),'system','autoperms',(($autoperms) ? $abook_my_perms : 0)); +dbg(0); connedit_clone($a); @@ -222,6 +267,30 @@ function connedit_content(&$a) { return login(); } + $my_perms = 0; + $role = get_pconfig(local_user(),'system','permissions_role'); + if($role) { + $x = get_role_perms($role); + if($x['perms_accept']) + $my_perms = $x['perms_accept']; + else + $my_perms = get_channel_default_perms(local_user()); + } + if($my_perms) { + $o .= "<script>function connectDefaultShare() { + \$('.abook-edit-me').each(function() { + if(! $(this).is(':disabled')) + $(this).removeAttr('checked'); + });\n\n"; + $perms = get_perms(); + foreach($perms as $p => $v) { + if($my_perms & $v[1]) { + $o .= "\$('#me_id_perms_" . $p . "').attr('checked','checked'); \n"; + } + } + $o .= "abook_perms_msg(); }\n</script>\n"; + } + if(argc() == 3) { $contact_id = intval(argv(1)); @@ -231,12 +300,10 @@ function connedit_content(&$a) { $cmd = argv(2); $orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_id = %d AND abook_channel = %d AND NOT ( abook_flags & %d ) and not ( abook_flags & %d ) LIMIT 1", + WHERE abook_id = %d AND abook_channel = %d AND NOT ( abook_flags & %d )>0 LIMIT 1", intval($contact_id), intval(local_user()), - intval(ABOOK_FLAG_SELF), - // allow drop even if pending, just duplicate the self query - intval(($cmd === 'drop') ? ABOOK_FLAG_SELF : ABOOK_FLAG_PENDING) + intval(ABOOK_FLAG_SELF) ); if(! count($orig_record)) { @@ -306,7 +373,8 @@ function connedit_content(&$a) { goaway($a->get_baseurl(true) . '/connedit/' . $contact_id); } - // We'll prevent somebody from unapproving a contact. + // We'll prevent somebody from unapproving an already approved contact. + // Though maybe somebody will want this eventually (??) if($cmd === 'approve') { if($orig_record[0]['abook_flags'] & ABOOK_FLAG_PENDING) { @@ -326,11 +394,21 @@ function connedit_content(&$a) { if($cmd === 'drop') { require_once('include/Contact.php'); + // FIXME -// terminate_friendship($a->get_channel(),$orig_record[0]); +// We need to send either a purge or a refresh packet to the other side (the channel being unfriended). +// The issue is that the abook DB record _may_ get destroyed when we call contact_remove. As the notifier runs +// in the background there could be a race condition preventing this packet from being sent in all cases. +// PLACEHOLDER contact_remove(local_user(), $orig_record[0]['abook_id']); -// FIXME - send to clones + build_sync_packet(0 /* use the current local_user */, + array('abook' => array( + 'abook_xchan' => $orig_record[0]['abook_xchan'], + 'entry_deleted' => true) + ) + ); + info( t('Connection has been removed.') . EOL ); if(x($_SESSION,'return_url')) goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']); @@ -366,32 +444,34 @@ function connedit_content(&$a) { 'url' => $a->get_baseurl(true) . '/network/?f=&cid=' . $contact['abook_id'], 'sel' => '', 'title' => t('View recent posts and comments'), - ), + ) + ); + $buttons = array( array( 'label' => (($contact['abook_flags'] & ABOOK_FLAG_BLOCKED) ? t('Unblock') : t('Block')), 'url' => $a->get_baseurl(true) . '/connedit/' . $contact['abook_id'] . '/block', 'sel' => (($contact['abook_flags'] & ABOOK_FLAG_BLOCKED) ? 'active' : ''), - 'title' => t('Block or Unblock this connection'), + 'title' => t('Block (or Unblock) all communications with this connection'), ), array( 'label' => (($contact['abook_flags'] & ABOOK_FLAG_IGNORED) ? t('Unignore') : t('Ignore')), 'url' => $a->get_baseurl(true) . '/connedit/' . $contact['abook_id'] . '/ignore', 'sel' => (($contact['abook_flags'] & ABOOK_FLAG_IGNORED) ? 'active' : ''), - 'title' => t('Ignore or Unignore this connection'), + 'title' => t('Ignore (or Unignore) all inbound communications from this connection'), ), array( 'label' => (($contact['abook_flags'] & ABOOK_FLAG_ARCHIVED) ? t('Unarchive') : t('Archive')), 'url' => $a->get_baseurl(true) . '/connedit/' . $contact['abook_id'] . '/archive', 'sel' => (($contact['abook_flags'] & ABOOK_FLAG_ARCHIVED) ? 'active' : ''), - 'title' => t('Archive or Unarchive this connection'), + 'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'), ), array( 'label' => (($contact['abook_flags'] & ABOOK_FLAG_HIDDEN) ? t('Unhide') : t('Hide')), 'url' => $a->get_baseurl(true) . '/connedit/' . $contact['abook_id'] . '/hide', 'sel' => (($contact['abook_flags'] & ABOOK_FLAG_HIDDEN) ? 'active' : ''), - 'title' => t('Hide or Unhide this connection'), + 'title' => t('Hide or Unhide this connection from your other connections'), ), array( @@ -426,6 +506,7 @@ function connedit_content(&$a) { $slider_tpl = get_markup_template('contact_slider.tpl'); $slide = replace_macros($slider_tpl,array( '$me' => t('Me'), + '$min' => 1, '$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99), '$intimate' => t('Best Friends'), '$friends' => t('Friends'), @@ -452,21 +533,26 @@ function connedit_content(&$a) { if((! $self) && ($existing[$k])) $thisperm = "1"; - $perms[] = array('perms_' . $k, $v[3], (($contact['abook_their_perms'] & $v[1]) ? "1" : ""),$thisperm, $v[1], (($channel[$v[0]] == PERMS_SPECIFIC) ? '' : '1'), $v[4]); + $perms[] = array('perms_' . $k, $v[3], (($contact['abook_their_perms'] & $v[1]) ? "1" : ""),$thisperm, $v[1], (($channel[$v[0]] == PERMS_SPECIFIC || $self) ? '' : '1'), $v[4]); } $o .= replace_macros($tpl,array( - '$header' => (($self) ? t('Automatic Permissions Settings') : sprintf( t('Connections: settings for %s'),$contact['xchan_name'])), + '$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connections: settings for %s'),$contact['xchan_name'])), + '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_user(),'system','autoperms')) ? 1 : 0), ''), '$addr' => $contact['xchan_addr'], '$notself' => (($self) ? '' : '1'), '$self' => (($self) ? '1' : ''), - '$autolbl' => t('When receiving a channel introduction, any permissions provided here will be applied to the new connection automatically and the introduction approved. Leave this page if you do not wish to use this feature.'), + '$autolbl' => t('Apply the permissions indicated on this page to all new connections.'), + '$buttons' => (($self) ? '' : $buttons), '$viewprof' => t('View Profile'), '$lbl_slider' => t('Slide to adjust your degree of friendship'), '$slide' => $slide, '$tabs' => $t, '$tab_str' => $tab_str, + '$perms_step1' => t('<p>Step #1. (Completed).</p><p>Create connection with minimal or no permissions.</p>'), + '$perms_step2' => t('<p>Step #2. (Incomplete).</p><p>Review and/or edit the default individual permissions on this page, if desired.</p>'), + '$perms_step3' => t('<p>Step #3. (Incomplete).</p><p>Submit this page to apply the selected permissions.</p><p>Until this is complete, this connection may have insufficient permission to communicate with you.</p>'), '$is_pending' => (($contact['abook_flags'] & ABOOK_FLAG_PENDING) ? 1 : ''), '$unapproved' => $unapproved, '$inherited' => t('inherited'), @@ -518,12 +604,8 @@ function connedit_content(&$a) { '$ignored' => (($contact['readonly']) ? t('Currently ignored') : ''), '$archived' => (($contact['archive']) ? t('Currently archived') : ''), '$pending' => (($contact['archive']) ? t('Currently pending') : ''), - '$hidden' => array('hidden', t('Hide this contact from others'), ($contact['hidden'] == 1), t('Replies/likes to your public posts <strong>may</strong> still be visible')), - '$photo' => $contact['photo'], '$name' => $contact['name'], - '$dir_icon' => $dir_icon, '$alt_text' => $alt_text, - '$sparkle' => $sparkle, '$url' => $url )); diff --git a/mod/contactgroup.php b/mod/contactgroup.php index 8b23f9f10..4515c4c4c 100644 --- a/mod/contactgroup.php +++ b/mod/contactgroup.php @@ -9,8 +9,8 @@ function contactgroup_content(&$a) { } if((argc() > 2) && (intval(argv(1))) && (argv(2))) { - $r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and not ( abook_flags & %d ) limit 1", - dbesc(argv(2)), + $r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and not ( abook_flags & %d )>0 limit 1", + dbesc(base64url_decode(argv(2))), intval(local_user()), intval(ABOOK_FLAG_SELF) ); diff --git a/mod/delegate.php b/mod/delegate.php index e582b9387..c78898b7f 100644 --- a/mod/delegate.php +++ b/mod/delegate.php @@ -42,7 +42,7 @@ function delegate_content(&$a) { if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) goaway($a->get_baseurl() . '/delegate'); - q("delete from manage where uid = %d and mid = %d limit 1", + q("delete from manage where uid = %d and mid = %d", intval($a->argv[2]), intval(local_user()) ); diff --git a/mod/directory.php b/mod/directory.php index b11b0d410..4ceda293d 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -1,12 +1,19 @@ <?php +require_once('include/socgraph.php'); require_once('include/dir_fns.php'); require_once('include/widgets.php'); - +require_once('include/bbcode.php'); function directory_init(&$a) { - $a->set_pager_itemspage(80); + $a->set_pager_itemspage(60); + if(x($_GET,'ignore')) { + q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ", + intval(local_user()), + dbesc($_GET['ignore']) + ); + } } function directory_content(&$a) { @@ -31,8 +38,9 @@ function directory_content(&$a) { if(x($_REQUEST,'safe')) $safe_mode = (intval($_REQUEST['safe'])); - - + $pubforums = null; + if(array_key_exists('pubforums',$_REQUEST)) + $pubforums = intval($_REQUEST['pubforums']); $o = ''; nav_set_selected('directory'); @@ -42,13 +50,38 @@ function directory_content(&$a) { else $search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : ''); - $advanced = ((x($_REQUEST,'query')) ? notags(trim($_REQUEST['query'])) : ''); + + if(strpos($search,'=') && local_user() && get_pconfig(local_user(),'feature','expert')) + $advanced = $search; + $keywords = (($_GET['keywords']) ? $_GET['keywords'] : ''); + // Suggest channels if no search terms or keywords are given + $suggest = (local_user() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : ''; + + if($suggest) { + $r = suggestion_query(local_user(),get_observer_hash()); + + // Remember in which order the suggestions were + $addresses = array(); + $index = 0; + foreach($r as $rr) { + $addresses[$rr['xchan_addr']] = $index++; + } + + // Build query to get info about suggested people + $advanced = ''; + foreach(array_keys($addresses) as $address) { + $advanced .= "address=\"$address\" "; + } + // Remove last space in the advanced query + $advanced = rtrim($advanced); + + } + $tpl = get_markup_template('directory_header.tpl'); - $dirmode = intval(get_config('system','directory_mode')); if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) { @@ -91,11 +124,19 @@ function directory_content(&$a) { $query .= '&keywords=' . urlencode($keywords); if($advanced) $query .= '&query=' . urlencode($advanced); + if(! is_null($pubforums)) + $query .= '&pubforums=' . intval($pubforums); + + if(! is_null($pubforums)) + $query .= '&pubforums=' . intval($pubforums); + + $sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : 'normal'); - $sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : ''); if($sort_order) $query .= '&order=' . urlencode($sort_order); + + if($a->pager['page'] != 1) $query .= '&p=' . $a->pager['page']; @@ -122,6 +163,10 @@ function directory_content(&$a) { $pdesc = (($rr['description']) ? $rr['description'] . '<br />' : ''); $connect_link = ((local_user()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : ''); + // Checking status is disabled ATM until someone checks the performance impact more carefully + //$online = remote_online_status($rr['address']); + $online = ''; + if(in_array($rr['hash'],$contacts)) $connect_link = ''; @@ -142,8 +187,6 @@ function directory_content(&$a) { if(($years = age($rr['birthday'],'UTC','')) != 0) $details .= '<br />' . t('Age: ') . $years ; } - if(strlen($rr['gender'])) - $details .= '<br />' . t('Gender: ') . $rr['gender']; $page_type = ''; @@ -155,18 +198,53 @@ function directory_content(&$a) { || (x($profile,'country') == 1)) $location = t('Location:'); - $gender = ((x($profile,'gender') == 1) ? t('Gender:') : False); + $gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False); - $marital = ((x($profile,'marital') == 1) ? t('Status:') : False); + $marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False); - $homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False); - - $about = ((x($profile,'about') == 1) ? t('About:') : False); + $homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False); + $homepageurl = ((x($profile,'homepage') == 1) ? $profile['homepage'] : ''); + + $hometown = ((x($profile,'hometown') == 1) ? t('Hometown: ') . $profile['hometown'] : False); + + $about = ((x($profile,'about') == 1) ? t('About: ') . bbcode($profile['about']) : False); + + $keywords = ((x($profile,'keywords')) ? $profile['keywords'] : ''); + + $out = ''; + + if($keywords) { + $keywords = str_replace(',',' ', $keywords); + $keywords = str_replace(' ',' ', $keywords); + $karr = explode(' ', $keywords); + + if($karr) { + if(local_user()) { + $r = q("select keywords from profile where uid = %d and is_default = 1 limit 1", + intval(local_user()) + ); + if($r) { + $keywords = str_replace(',',' ', $r[0]['keywords']); + $keywords = str_replace(' ',' ', $keywords); + $marr = explode(' ', $keywords); + } + } + foreach($karr as $k) { + if(strlen($out)) + $out .= ', '; + if($marr && in_arrayi($k,$marr)) + $out .= '<strong>' . $k . '</strong>'; + else + $out .= $k; + } + } + } $entry = array( 'id' => ++$t, 'profile_link' => $profile_link, + 'public_forum' => $rr['public_forum'], 'photo' => $rr['photo'], 'hash' => $rr['hash'], 'alttext' => $rr['name'] . ' ' . $rr['address'], @@ -174,48 +252,88 @@ function directory_content(&$a) { 'details' => $pdesc . $details, 'profile' => $profile, 'address' => $rr['address'], + 'nickname' => substr($rr['address'],0,strpos($rr['address'],'@')), 'location' => $location, 'gender' => $gender, 'pdesc' => $pdesc, 'marital' => $marital, 'homepage' => $homepage, + 'homepageurl' => linkify($homepageurl), + 'hometown' => $hometown, 'about' => $about, 'conn_label' => t('Connect'), + 'forum_label' => t('Public Forum:'), 'connect' => $connect_link, + 'online' => $online, + 'kw' => (($out) ? t('Keywords: ') : ''), + 'keywords' => $out, + 'ignlink' => $suggest ? $a->get_baseurl() . '/directory?ignore=' . $rr['hash'] : '', + 'ignore_label' => "Don't suggest", ); $arr = array('contact' => $rr, 'entry' => $entry); call_hooks('directory_item', $arr); - $entries[] = $arr['entry']; + if($sort_order == '' && $suggest) { + $entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first + } + else { + $entries[] = $arr['entry']; + } unset($profile); unset($location); } + ksort($entries); // Sort array by key so that foreach-constructs work as expected + if($j['keywords']) { $a->data['directory_keywords'] = $j['keywords']; } -// logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA); + logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA); - $o .= replace_macros($tpl, array( - '$search' => $search, - '$desc' => t('Find'), - '$finddsc' => t('Finding:'), - '$safetxt' => htmlspecialchars($search,ENT_QUOTES,'UTF-8'), - '$entries' => $entries, - '$dirlbl' => t('Directory'), - '$submit' => t('Find') - )); + if($_REQUEST['aj']) { + if($entries) { + $o = replace_macros(get_markup_template('directajax.tpl'),array( + '$entries' => $entries + )); + } + else { + $o = '<div id="content-complete"></div>'; + } + echo $o; + killme(); + } + else { + $maxheight = 175; + + $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>"; + $o .= replace_macros($tpl, array( + '$search' => $search, + '$desc' => t('Find'), + '$finddsc' => t('Finding:'), + '$safetxt' => htmlspecialchars($search,ENT_QUOTES,'UTF-8'), + '$entries' => $entries, + '$dirlbl' => $suggest ? t('Channel Suggestions') : t('Directory'), + '$submit' => t('Find'), + '$next' => alt_pager($a,$j['records'], t('next page'), t('previous page')) - $o .= alt_pager($a,$j['records'], t('next page'), t('previous page')); + )); + + + } } else { + if($_REQUEST['aj']) { + $o = '<div id="content-complete"></div>'; + echo $o; + killme(); + } if($a->pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) { goaway(z_root() . '/chanview/?f=&address=' . $search); } diff --git a/mod/dirprofile.php b/mod/dirprofile.php deleted file mode 100644 index e9b12ada7..000000000 --- a/mod/dirprofile.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -require_once('include/dir_fns.php'); -require_once('include/bbcode.php'); - -function dirprofile_init(&$a) { - - if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) { - notice( t('Public access denied.') . EOL); - return; - } - - $hash = $_REQUEST['hash']; - if(! $hash) - return ''; - - $o = ''; - - $dirmode = intval(get_config('system','directory_mode')); - - if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) { - $url = z_root() . '/dirsearch'; - } - if(! $url) { - $directory = find_upstream_directory($dirmode); - $url = $directory['url'] . '/dirsearch'; - } - logger('mod_directory: URL = ' . $url, LOGGER_DEBUG); - - $contacts = array(); - - if(local_user()) { - $x = q("select abook_xchan from abook where abook_channel = %d", - intval(local_user()) - ); - if($x) { - foreach($x as $xx) - $contacts[] = $xx['abook_xchan']; - } - } - - - - if($url) { - - $query = $url . '?f=&hash=' . $hash; - - $x = z_fetch_url($query); - logger('dirprofile: return from upstream: ' . print_r($x,true), LOGGER_DATA); - - if($x['success']) { - $t = 0; - $j = json_decode($x['body'],true); - if($j) { - - if($j['results']) { - - $entries = array(); - - $photo = 'thumb'; - - foreach($j['results'] as $rr) { - - $profile_link = chanlink_url($rr['url']); - - $pdesc = (($rr['description']) ? $rr['description'] . '<br />' : ''); - - $qrlink = zid($rr['url']); - $connect_link = ((local_user()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : ''); - - $online = remote_online_status($rr['address']); - - - if(in_array($rr['hash'],$contacts)) - $connect_link = ''; - - $details = ''; - if(strlen($rr['locale'])) - $details .= $rr['locale']; - if(strlen($rr['region'])) { - if(strlen($rr['locale'])) - $details .= ', '; - $details .= $rr['region']; - } - if(strlen($rr['country'])) { - if(strlen($details)) - $details .= ', '; - $details .= $rr['country']; - } - if(strlen($rr['birthday'])) { - if(($years = age($rr['birthday'],'UTC','')) != 0) - $details .= '<br />' . t('Age: ') . $years ; - } - if(strlen($rr['gender'])) - $details .= '<br />' . t('Gender: ') . $rr['gender']; - - $page_type = ''; - - $profile = $rr; - - if ((x($profile,'locale') == 1) - || (x($profile,'region') == 1) - || (x($profile,'postcode') == 1) - || (x($profile,'country') == 1)) - $location = t('Location:'); - - - $marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital'] : False); - $sexual = ((x($profile,'sexual') == 1) ? t('Sexual Preference: ') . $profile['sexual'] : False); - - $homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') . linkify($profile['homepage']) : False); - $hometown = ((x($profile,'hometown') == 1) ? t('Hometown: ') . $profile['hometown'] : False); - - $about = ((x($profile,'about') == 1) ? t('About: ') . bbcode($profile['about']) : False); - - $keywords = ((x($profile,'keywords')) ? $profile['keywords'] : ''); - if($keywords) { - $keywords = str_replace(',',' ', $keywords); - $keywords = str_replace(' ',' ', $keywords); - $karr = explode(' ', $keywords); - $out = ''; - if($karr) { - if(local_user()) { - $r = q("select keywords from profile where uid = %d and is_default = 1 limit 1", - intval(local_user()) - ); - if($r) { - $keywords = str_replace(',',' ', $r[0]['keywords']); - $keywords = str_replace(' ',' ', $keywords); - $marr = explode(' ', $keywords); - } - } - foreach($karr as $k) { - if(strlen($out)) - $out .= ', '; - if($marr && in_arrayi($k,$marr)) - $out .= '<strong>' . $k . '</strong>'; - else - $out .= $k; - } - } - - } - $entry = replace_macros(get_markup_template('direntry_large.tpl'), array( - '$id' => ++$t, - '$profile_link' => $profile_link, - '$qrlink' => $qrlink, - '$photo' => $rr['photo_l'], - '$alttext' => $rr['name'] . ' ' . $rr['address'], - '$name' => $rr['name'], - '$online' => (($online) ? t('Online Now') : ''), - '$details' => $pdesc . $details, - '$profile' => $profile, - '$address' => $rr['address'], - '$location' => $location, - '$gender' => $gender, - '$pdesc' => $pdesc, - '$marital' => $marital, - '$homepage' => $homepage, - '$hometown' => $hometown, - '$about' => $about, - '$kw' => (($out) ? t('Keywords: ') : ''), - '$keywords' => $out, - '$conn_label' => t('Connect'), - '$connect' => $connect_link, - )); - - - echo $entry; - killme(); - - } - } - else { - info( t("Not found.") . EOL); - } - } - } - } - - - - -}
\ No newline at end of file diff --git a/mod/dirsearch.php b/mod/dirsearch.php index 0ace4ecae..a88db0a2c 100644 --- a/mod/dirsearch.php +++ b/mod/dirsearch.php @@ -4,7 +4,7 @@ require_once('include/dir_fns.php'); function dirsearch_init(&$a) { - $a->set_pager_itemspage(80); + $a->set_pager_itemspage(60); } @@ -29,6 +29,7 @@ function dirsearch_content(&$a) { $sql_extra = ''; + $tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords'); if($_REQUEST['query']) { @@ -63,6 +64,9 @@ function dirsearch_content(&$a) { $agege = ((x($_REQUEST,'agege')) ? intval($_REQUEST['agege']) : 0 ); $agele = ((x($_REQUEST,'agele')) ? intval($_REQUEST['agele']) : 0 ); $kw = ((x($_REQUEST,'kw')) ? intval($_REQUEST['kw']) : 0 ); + $forums = ((array_key_exists('pubforums',$_REQUEST)) ? intval($_REQUEST['pubforums']) : 0); + + // by default use a safe search $safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 ); @@ -107,6 +111,10 @@ function dirsearch_content(&$a) { if($keywords) $sql_extra .= dir_query_build($joiner,'xprof_keywords',$keywords); + if($forums) + $sql_extra .= dir_flag_build($joiner,'xprof_flags',XCHAN_FLAGS_PUBFORUM, $forums); + + // we only support an age range currently. You must set both agege // (greater than or equal) and agele (less than or equal) @@ -121,7 +129,7 @@ function dirsearch_content(&$a) { } - $perpage = (($_REQUEST['n']) ? $_REQUEST['n'] : 80); + $perpage = (($_REQUEST['n']) ? $_REQUEST['n'] : 60); $page = (($_REQUEST['p']) ? intval($_REQUEST['p'] - 1) : 0); $startrec = (($page+1) * $perpage) - $perpage; $limit = (($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 0); @@ -145,16 +153,21 @@ function dirsearch_content(&$a) { if($hash) $logic = 1; - $safesql = (($safe > 0) ? " and not ( xchan_flags & " . intval(XCHAN_FLAGS_CENSORED|XCHAN_FLAGS_SELFCENSORED) . " ) " : ''); + if($dirmode == DIRECTORY_MODE_STANDALONE) { + $sql_extra .= " and xchan_addr like '%%" . get_app()->get_hostname() . "' "; + } + + + $safesql = (($safe > 0) ? " and not ( xchan_flags & " . intval(XCHAN_FLAGS_CENSORED|XCHAN_FLAGS_SELFCENSORED) . " )>0 " : ''); if($safe < 0) - $safesql = " and ( xchan_flags & " . intval(XCHAN_FLAGS_CENSORED|XCHAN_FLAGS_SELFCENSORED) . " ) "; + $safesql = " and ( xchan_flags & " . intval(XCHAN_FLAGS_CENSORED|XCHAN_FLAGS_SELFCENSORED) . " )>0 "; if($limit) $qlimit = " LIMIT $limit "; else { $qlimit = " LIMIT " . intval($startrec) . " , " . intval($perpage); if($return_total) { - $r = q("SELECT COUNT(xchan_hash) AS `total` FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and not ( xchan_flags & %d) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) $safesql ", + $r = q("SELECT COUNT(xchan_hash) AS `total` FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot' and not ( xchan_flags & %d)>0 and not ( xchan_flags & %d )>0 and not ( xchan_flags & %d )>0 $safesql ", intval(XCHAN_FLAGS_HIDDEN), intval(XCHAN_FLAGS_ORPHAN), intval(XCHAN_FLAGS_DELETED) @@ -170,10 +183,11 @@ function dirsearch_content(&$a) { $order = " order by xchan_name asc "; elseif($sort_order == 'reverse') $order = " order by xchan_name desc "; + elseif($sort_order == 'reversedate') + $order = " order by xchan_name_date asc "; else $order = " order by xchan_name_date desc "; - if($sync) { $spkt = array('transactions' => array()); $r = q("select * from updates where ud_date >= '%s' and ud_guid != '' order by ud_date desc", @@ -199,7 +213,7 @@ function dirsearch_content(&$a) { json_return_and_die($spkt); } else { - $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash where ( $logic $sql_extra ) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) $safesql $order $qlimit ", + $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash where ( $logic $sql_extra ) and xchan_network = 'zot' and not ( xchan_flags & %d )>0 and not ( xchan_flags & %d )>0 and not ( xchan_flags & %d )>0 $safesql $order $qlimit ", intval(XCHAN_FLAGS_HIDDEN), intval(XCHAN_FLAGS_ORPHAN), intval(XCHAN_FLAGS_DELETED) @@ -220,6 +234,8 @@ function dirsearch_content(&$a) { $entry['name'] = $rr['xchan_name']; $entry['hash'] = $rr['xchan_hash']; + $entry['public_forum'] = (($rr['xchan_flags'] & XCHAN_FLAGS_PUBFORUM) ? true : false); + $entry['url'] = $rr['xchan_url']; $entry['photo_l'] = $rr['xchan_photo_l']; $entry['photo'] = $rr['xchan_photo_m']; @@ -254,8 +270,8 @@ function dirsearch_content(&$a) { } } } - json_return_and_die($ret); + json_return_and_die($ret); } function dir_query_build($joiner,$field,$s) { @@ -265,6 +281,11 @@ function dir_query_build($joiner,$field,$s) { return $ret; } +function dir_flag_build($joiner,$field,$bit,$s) { + return dbesc($joiner) . " ( " . dbesc('xchan_flags') . " & " . intval($bit) . " ) " . ((intval($s)) ? '>' : '=' ) . " 0 "; +} + + function dir_parse_query($s) { $ret = array(); @@ -274,35 +295,44 @@ function dir_parse_query($s) { if($all) { foreach($all as $q) { - if($q === 'and') { - $curr['logic'] = 'and'; - continue; - } - if($q === 'or') { - $curr['logic'] = 'or'; - continue; - } - if($q === 'not') { - $curr['logic'] .= ' not'; - continue; - } - if(strpos($q,'=')) { - if(! isset($curr['logic'])) + if($quoted_string === false) { + if($q === 'and') { + $curr['logic'] = 'and'; + continue; + } + if($q === 'or') { $curr['logic'] = 'or'; - $curr['field'] = trim(substr($q,0,strpos($q,'='))); - $curr['value'] = trim(substr($q,strpos($q,'=')+1)); - if(strpos($curr['value'],'"') !== false) { - $quoted_string = true; - $curr['value'] = substr($curr['value'],strpos($curr['value'],'"')+1); + continue; } - else { - $ret[] = $curr; - $curr = array(); - $continue; + if($q === 'not') { + $curr['logic'] .= ' not'; + continue; + } + if(strpos($q,'=')) { + if(! isset($curr['logic'])) + $curr['logic'] = 'or'; + $curr['field'] = trim(substr($q,0,strpos($q,'='))); + $curr['value'] = trim(substr($q,strpos($q,'=')+1)); + if($curr['value'][0] == '"' && $curr['value'][strlen($curr['value'])-1] != '"') { + $quoted_string = true; + $curr['value'] = substr($curr['value'],1); + continue; + } + elseif($curr['value'][0] == '"' && $curr['value'][strlen($curr['value'])-1] == '"') { + $curr['value'] = substr($curr['value'],1,strlen($curr['value'])-2); + $ret[] = $curr; + $curr = array(); + continue; + } + else { + $ret[] = $curr; + $curr = array(); + continue; + } } } - elseif($quoted_string) { - if(strpos($q,'"') !== false) { + else { + if($q[strlen($q)-1] == '"') { $curr['value'] .= ' ' . str_replace('"','',trim($q)); $ret[] = $curr; $curr = array(); @@ -325,8 +355,18 @@ function dir_parse_query($s) { function list_public_sites() { - - $r = q("select * from site where site_access != 0 and site_register !=0 order by rand()"); + $realm = get_directory_realm(); + if($realm == DIRECTORY_REALM) { + $r = q("select * from site where site_access != 0 and site_register !=0 and ( site_realm = '%s' or site_realm = '') order by rand()", + dbesc($realm) + ); + } + else { + $r = q("select * from site where site_access != 0 and site_register !=0 and site_realm = '%s' order by rand()", + dbesc($realm) + ); + } + $ret = array('success' => false); if($r) { diff --git a/mod/display.php b/mod/display.php index 31cce95d3..7d7f4ca13 100644 --- a/mod/display.php +++ b/mod/display.php @@ -85,6 +85,8 @@ function display_content(&$a, $update = 0, $load = false) { $target_item = $r[0]; } + $r = null; + if($target_item['item_restrict'] & ITEM_WEBPAGE) { $x = q("select * from channel where channel_id = %d limit 1", intval($target_item['uid']) @@ -131,6 +133,7 @@ function display_content(&$a, $update = 0, $load = false) { '$order' => '', '$file' => '', '$cats' => '', + '$tags' => '', '$dend' => '', '$dbegin' => '', '$mid' => $item_hash @@ -139,19 +142,22 @@ function display_content(&$a, $update = 0, $load = false) { } - $sql_extra = public_permissions_sql(get_observer_hash()); + $observer_hash = get_observer_hash(); + + $sql_extra = public_permissions_sql($observer_hash); if(($update && $load) || ($_COOKIE['jsAvailable'] != 1)) { $updateable = false; - $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage'])); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($a->pager['itemspage']),intval($a->pager['start'])); if($load || ($_COOKIE['jsAvailable'] != 1)) { $r = null; require_once('include/identity.php'); $sys = get_sys_channel(); + $sysid = $sys['channel_id']; if(local_user()) { $r = q("SELECT * from item @@ -170,17 +176,24 @@ function display_content(&$a, $update = 0, $load = false) { } 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; + + $r = q("SELECT * from item WHERE item_restrict = 0 and mid = '%s' AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND item_private = 0 ) - and owner_xchan in ( " . stream_perms_xchans(($observer) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) - OR owner_xchan = '%s') + and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) + OR uid = %d ) $sql_extra ) - group by mid limit 1", + limit 1", dbesc($target_item['parent_mid']), - dbesc($sys['xchan_hash']) + intval($sysid) ); } @@ -217,8 +230,8 @@ function display_content(&$a, $update = 0, $load = false) { } if($updateable) { - $x = q("UPDATE item SET item_flags = ( item_flags ^ %d ) - WHERE (item_flags & %d) AND uid = %d and parent = %d ", + $x = q("UPDATE item SET item_flags = ( item_flags & ~%d ) + WHERE (item_flags & %d)>0 AND uid = %d and parent = %d ", intval(ITEM_UNSEEN), intval(ITEM_UNSEEN), intval(local_user()), diff --git a/mod/editblock.php b/mod/editblock.php index 536ddd7d2..6ec840af7 100644 --- a/mod/editblock.php +++ b/mod/editblock.php @@ -1,50 +1,92 @@ <?php +require_once('include/identity.php'); +require_once('include/acl_selectors.php'); -function editblock_content(&$a) { +function editblock_init(&$a) { + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } - if(argc() < 2) { - notice( t('Item not found') . EOL); + if(argc() > 1) + $which = argv(1); + else return; - } - $channel = get_channel_by_nick(argv(1)); + profile_load($a,$which); - if($c) { - $owner = intval($channel['channel_id']); - } +} - $o = ''; +function editblock_content(&$a) { - // Figure out which post we're editing - $post_id = ((argc() > 2) ? intval(argv(2)) : 0); + if(! $a->profile) { + notice( t('Requested profile is not available.') . EOL ); + $a->error = 404; + return; + } + $which = argv(1); - if(! ($post_id && $channel)) { - notice( t('Item not found') . EOL); - return; + $uid = local_user(); + $owner = 0; + $channel = null; + $observer = $a->get_observer(); + + $channel = $a->get_channel(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } + } + + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) + ); + if($r) { + $owner = intval($r[0]['channel_id']); + } } - // Now we've got a post and an owner, let's find out if we're allowed to edit it + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - if(! perm_is_allowed($channel['channel_id'],get_observer_hash(),'write_pages')) { + if(! perm_is_allowed($owner,$ob_hash,'write_pages')) { notice( t('Permission denied.') . EOL); return; } + $is_owner = (($uid && $uid == $owner) ? true : false); + + $o = ''; + + + // Figure out which post we're editing + $post_id = ((argc() > 2) ? intval(argv(2)) : 0); - // We've already figured out which item we want and whose copy we need, so we don't need anything fancy here + if(! ($post_id && $owner)) { + notice( t('Item not found') . EOL); + return; + } + $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", intval($post_id), - intval($channel['channel_id']) + intval($owner) ); if($itm) { $item_id = q("select * from item_id where service = 'BUILDBLOCK' and iid = %d limit 1", - $itm[0]['id'] + intval($itm[0]['id']) ); if($item_id) $block_title = $item_id[0]['sid']; @@ -57,10 +99,6 @@ function editblock_content(&$a) { $plaintext = true; - // You may or may not be a local user. -// if(local_user() && feature_enabled(local_user(),'richtext')) -// $plaintext = false; - $mimeselect = ''; $mimetype = $itm[0]['mimetype']; @@ -79,11 +117,11 @@ function editblock_content(&$a) { $a->page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array( - '$baseurl' => $a->get_baseurl(), - '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), - '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), - '$geotag' => '', - '$nickname' => $channel['channel_address'], + '$baseurl' => $a->get_baseurl(), + '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), + '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), + '$geotag' => '', + '$nickname' => $channel['channel_address'], '$confirmdelete' => t('Delete block?') )); @@ -96,62 +134,70 @@ function editblock_content(&$a) { call_hooks('jot_tool', $jotplugins); call_hooks('jot_networks', $jotnets); - - //$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins)); - - // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD instead of loading a sensible page. - //So, send folk to the webpage list. - $rp = 'blocks/' . $channel['channel_address']; $o .= replace_macros($tpl,array( - '$return_path' => $rp, - '$action' => 'item', - '$webpage' => ITEM_BUILDBLOCK, - '$share' => t('Edit'), - '$upload' => t('Upload photo'), - '$attach' => t('Attach file'), - '$weblink' => t('Insert web link'), - '$youtube' => t('Insert YouTube video'), - '$video' => t('Insert Vorbis [.ogg] video'), - '$audio' => t('Insert Vorbis [.ogg] audio'), - '$setloc' => t('Set your location'), - '$noloc' => t('Clear browser location'), - '$wait' => t('Please wait'), - '$permset' => t('Permission settings'), - '$ptyp' => $itm[0]['type'], - '$mimeselect' => $mimeselect, - '$content' => undo_post_tagging($itm[0]['body']), - '$post_id' => $post_id, - '$baseurl' => $a->get_baseurl(), - '$defloc' => $channel['channel_location'], - '$visitor' => false, - '$public' => t('Public post'), - '$jotnets' => $jotnets, - '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), - '$placeholdertitle' => t('Set title'), - '$pagetitle' => $block_title, - '$category' => '', - '$placeholdercategory' => t('Categories (comma-separated list)'), - '$emtitle' => t('Example: bob@example.com, mary@example.com'), - '$lockstate' => $lockstate, - '$acl' => '', - '$bang' => '', - '$profile_uid' => (intval($channel['channel_id'])), - '$preview' => ((feature_enabled(local_user(),'preview')) ? t('Preview') : ''), - '$jotplugins' => $jotplugins, - '$sourceapp' => $itm[0]['app'], - '$defexpire' => '', - '$feature_expire' => false, - '$expires' => t('Set expiration date'), + '$return_path' => $rp, + '$action' => 'item', + '$webpage' => ITEM_BUILDBLOCK, + '$share' => t('Edit'), + '$upload' => t('Upload photo'), + '$attach' => t('Attach file'), + '$weblink' => t('Insert web link'), + '$youtube' => t('Insert YouTube video'), + '$video' => t('Insert Vorbis [.ogg] video'), + '$audio' => t('Insert Vorbis [.ogg] audio'), + '$setloc' => t('Set your location'), + '$noloc' => t('Clear browser location'), + '$wait' => t('Please wait'), + '$permset' => t('Permission settings'), + '$ptyp' => $itm[0]['type'], + '$mimeselect' => $mimeselect, + '$content' => undo_post_tagging($itm[0]['body']), + '$post_id' => $post_id, + '$baseurl' => $a->get_baseurl(), + '$defloc' => $channel['channel_location'], + '$visitor' => false, + '$public' => t('Public post'), + '$jotnets' => $jotnets, + '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), + '$placeholdertitle' => t('Title (optional)'), + '$pagetitle' => $block_title, + '$category' => '', + '$placeholdercategory' => t('Categories (optional, comma-separated list)'), + '$emtitle' => t('Example: bob@example.com, mary@example.com'), + '$lockstate' => $lockstate, + '$acl' => '', + '$bang' => '', + '$profile_uid' => (intval($channel['channel_id'])), + '$preview' => true, // ((feature_enabled($uid,'preview')) ? t('Preview') : ''), + '$jotplugins' => $jotplugins, + '$sourceapp' => $itm[0]['app'], + '$defexpire' => '', + '$feature_expire' => false, + '$expires' => t('Set expiration date'), )); - $ob = get_observer_hash(); - - if(($itm[0]['author_xchan'] === $ob) || ($itm[0]['owner_xchan'] === $ob)) + if(($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) $o .= '<br /><br /><a class="block-delete-link" href="item/drop/' . $itm[0]['id'] . '" >' . t('Delete Block') . '</a><br />'; + + $x = array( + 'type' => 'block', + 'title' => $itm[0]['title'], + 'body' => $itm[0]['body'], + 'term' => $itm[0]['term'], + 'created' => $itm[0]['created'], + 'edited' => $itm[0]['edited'], + 'mimetype' => $itm[0]['mimetype'], + 'pagetitle' => $page_title, + 'mid' => $itm[0]['mid'] + ); + + $o .= EOL . EOL . t('Share') . EOL . '<textarea onclick="this.select();" class="shareable_element_text" >[element]' . base64url_encode(json_encode($x)) . '[/element]</textarea>' . EOL . EOL; + + return $o; } diff --git a/mod/editlayout.php b/mod/editlayout.php index 1e8a6e990..d76aa484d 100644 --- a/mod/editlayout.php +++ b/mod/editlayout.php @@ -1,34 +1,76 @@ <?php -// What is this here for? I think it's cruft, but comment out for now in case it's here for a reason -// require_once('acl_selectors.php'); +require_once('include/identity.php'); +require_once('include/acl_selectors.php'); + +function editlayout_init(&$a) { + + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } + + if(argc() > 1) + $which = argv(1); + else + return; + + profile_load($a,$which); + +} function editlayout_content(&$a) { -// We first need to figure out who owns the webpage, grab it from an argument - $which = argv(1); -// $a->get_channel() and stuff don't work here, so we've got to find the owner for ourselves. - $r = q("select channel_id from channel where channel_address = '%s'", - dbesc($which) + if(! $a->profile) { + notice( t('Requested profile is not available.') . EOL ); + $a->error = 404; + return; + } + + $which = argv(1); + + $uid = local_user(); + $owner = 0; + $channel = null; + $observer = $a->get_observer(); + + $channel = $a->get_channel(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } + } + + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) ); - if($r) { - $owner = intval($r[0]['channel_id']); - //logger('owner: ' . print_r($owner,true)); - } + if($r) { + $owner = intval($r[0]['channel_id']); + } + } + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - - - if((local_user()) && (argc() > 2) && (argv(2) === 'view')) { - $which = $channel['channel_address']; - } + if(! perm_is_allowed($owner,$ob_hash,'write_pages')) { + notice( t('Permission denied.') . EOL); + return; + } + $is_owner = (($uid && $uid == $owner) ? true : false); $o = ''; -// Figure out which post we're editing + // Figure out which post we're editing $post_id = ((argc() > 2) ? intval(argv(2)) : 0); @@ -37,48 +79,41 @@ function editlayout_content(&$a) { return; } -// Now we've got a post and an owner, let's find out if we're allowed to edit it - - $observer = $a->get_observer(); - $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + // Now we've got a post and an owner, let's find out if we're allowed to edit it - $perms = get_all_perms($owner,$ob_hash); + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - if(! $perms['write_pages']) { - notice( t('Permission denied.') . EOL); - return; - } + $perms = get_all_perms($owner,$ob_hash); + if(! $perms['write_pages']) { + notice( t('Permission denied.') . EOL); + return; + } -// We've already figured out which item we want and whose copy we need, so we don't need anything fancy here - $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", - intval($post_id), - intval($owner) - ); + $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", + intval($post_id), + intval($owner) + ); $item_id = q("select * from item_id where service = 'PDL' and iid = %d limit 1", - $itm[0]['id'] + intval($itm[0]['id']) ); if($item_id) $layout_title = $item_id[0]['sid']; $plaintext = true; -// You may or may not be a local user. This won't work, -// if(feature_enabled(local_user(),'richtext')) -// $plaintext = false; $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Layout') )); - $a->page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array( - '$baseurl' => $a->get_baseurl(), - '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), - '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), - '$geotag' => $geotag, - '$nickname' => $a->user['nickname'], + '$baseurl' => $a->get_baseurl(), + '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), + '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), + '$geotag' => $geotag, + '$nickname' => $channel['channel_address'], '$confirmdelete' => t('Delete layout?') )); @@ -91,60 +126,74 @@ function editlayout_content(&$a) { call_hooks('jot_tool', $jotplugins); call_hooks('jot_networks', $jotnets); - $channel = $a->get_channel(); - - //$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins)); -//FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD instead of loading a sensible page. So, send folk to the webpage list. + // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD + // instead of loading a sensible page. So, send folk to the webpage list. $rp = '/layouts/' . $which; $o .= replace_macros($tpl,array( - '$return_path' => $rp, - '$action' => 'item', - '$webpage' => ITEM_PDL, - '$share' => t('Edit'), - '$upload' => t('Upload photo'), - '$attach' => t('Attach file'), - '$weblink' => t('Insert web link'), - '$youtube' => t('Insert YouTube video'), - '$video' => t('Insert Vorbis [.ogg] video'), - '$audio' => t('Insert Vorbis [.ogg] audio'), - '$setloc' => t('Set your location'), - '$noloc' => t('Clear browser location'), - '$wait' => t('Please wait'), - '$permset' => t('Permission settings'), - '$ptyp' => $itm[0]['type'], - '$content' => undo_post_tagging($itm[0]['body']), - '$post_id' => $post_id, - '$baseurl' => $a->get_baseurl(), - '$defloc' => $channel['channel_location'], - '$visitor' => false, - '$public' => t('Public post'), - '$jotnets' => $jotnets, - '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), - '$placeholdertitle' => t('Set title'), - '$pagetitle' => $layout_title, - '$category' => '', - '$placeholdercategory' => t('Categories (comma-separated list)'), - '$emtitle' => t('Example: bob@example.com, mary@example.com'), - '$lockstate' => $lockstate, - '$acl' => '', - '$bang' => '', - '$profile_uid' => (intval($owner)), - '$preview' => ((feature_enabled(local_user(),'preview')) ? t('Preview') : ''), - '$jotplugins' => $jotplugins, - '$sourceapp' => t($a->sourcename), - '$defexpire' => '', - '$feature_expire' => false, - '$expires' => t('Set expiration date'), + '$return_path' => $rp, + '$action' => 'item', + '$webpage' => ITEM_PDL, + '$share' => t('Edit'), + '$upload' => t('Upload photo'), + '$attach' => t('Attach file'), + '$weblink' => t('Insert web link'), + '$youtube' => t('Insert YouTube video'), + '$video' => t('Insert Vorbis [.ogg] video'), + '$audio' => t('Insert Vorbis [.ogg] audio'), + '$setloc' => t('Set your location'), + '$noloc' => t('Clear browser location'), + '$wait' => t('Please wait'), + '$permset' => t('Permission settings'), + '$ptyp' => $itm[0]['type'], + '$content' => undo_post_tagging($itm[0]['body']), + '$post_id' => $post_id, + '$baseurl' => $a->get_baseurl(), + '$defloc' => $channel['channel_location'], + '$visitor' => false, + '$public' => t('Public post'), + '$jotnets' => $jotnets, + '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), + '$placeholdertitle' => t('Title (optional)'), + '$pagetitle' => $layout_title, + '$category' => '', + '$placeholdercategory' => t('Categories (optional, comma-separated list)'), + '$emtitle' => t('Example: bob@example.com, mary@example.com'), + '$lockstate' => $lockstate, + '$acl' => '', + '$bang' => '', + '$profile_uid' => (intval($owner)), + '$preview' => true, // ((feature_enabled($uid,'preview')) ? t('Preview') : ''), + '$jotplugins' => $jotplugins, + '$sourceapp' => t($a->sourcename), + '$defexpire' => '', + '$feature_expire' => false, + '$expires' => t('Set expiration date'), )); - $ob = get_observer_hash(); - if(($itm[0]['author_xchan'] === $ob) || ($itm[0]['owner_xchan'] === $ob)) + if(($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) $o .= '<br /><br /><a class="layout-delete-link" href="item/drop/' . $itm[0]['id'] . '" >' . t('Delete Layout') . '</a><br />'; + + $x = array( + 'type' => 'layout', + 'title' => $itm[0]['title'], + 'body' => $itm[0]['body'], + 'term' => $itm[0]['term'], + 'created' => $itm[0]['created'], + 'edited' => $itm[0]['edited'], + 'mimetype' => $itm[0]['mimetype'], + 'pagetitle' => $page_title, + 'mid' => $itm[0]['mid'] + ); + + $o .= EOL . EOL . t('Share') . EOL . '<textarea onclick="this.select();" class="shareable_element_text" >[element]' . base64url_encode(json_encode($x)) . '[/element]</textarea>' . EOL . EOL; + + + return $o; } diff --git a/mod/editpost.php b/mod/editpost.php index ed7fcff8a..dfbc8766e 100644 --- a/mod/editpost.php +++ b/mod/editpost.php @@ -129,15 +129,15 @@ function editpost_content(&$a) { '$public' => t('Public post'), '$jotnets' => $jotnets, '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), - '$placeholdertitle' => t('Set title'), + '$placeholdertitle' => t('Title (optional)'), '$category' => $category, - '$placeholdercategory' => t('Categories (comma-separated list)'), + '$placeholdercategory' => t('Categories (optional, comma-separated list)'), '$emtitle' => t('Example: bob@example.com, mary@example.com'), '$lockstate' => $lockstate, '$acl' => '', '$bang' => '', '$profile_uid' => local_user(), - '$preview' => ((feature_enabled(local_user(),'preview')) ? t('Preview') : ''), + '$preview' => true, // ((feature_enabled(local_user(),'preview')) ? t('Preview') : ''), '$jotplugins' => $jotplugins, '$sourceapp' => t($a->sourcename), '$catsenabled' => $catsenabled, diff --git a/mod/editwebpage.php b/mod/editwebpage.php index 9fe76ba98..191c9a9ac 100644 --- a/mod/editwebpage.php +++ b/mod/editwebpage.php @@ -1,26 +1,71 @@ <?php -// Required for setting permissions. (FIXME) +require_once('include/identity.php'); +require_once('include/acl_selectors.php'); + +function editwebpage_init(&$a) { + + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } + + if(argc() > 1) + $which = argv(1); + else + return; + + profile_load($a,$which); + +} -require_once('acl_selectors.php'); function editwebpage_content(&$a) { - // We first need to figure out who owns the webpage, grab it from an argument + if(! $a->profile) { + notice( t('Requested profile is not available.') . EOL ); + $a->error = 404; + return; + } $which = argv(1); - // $a->get_channel() and stuff don't work here, so we've got to find the owner for ourselves. - - $r = q("select channel_id from channel where channel_address = '%s'", - dbesc($which) - ); - if($r) { - $owner = intval($r[0]['channel_id']); - //logger('owner: ' . print_r($owner,true)); + $uid = local_user(); + $owner = 0; + $channel = null; + $observer = $a->get_observer(); + + $channel = $a->get_channel(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } + } + + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) + ); + if($r) { + $owner = intval($r[0]['channel_id']); + } + } + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + if(! perm_is_allowed($owner,$ob_hash,'write_pages')) { + notice( t('Permission denied.') . EOL); + return; } - $is_owner = ((local_user() && local_user() == $owner) ? true : false); + $is_owner = (($uid && $uid == $owner) ? true : false); $o = ''; @@ -33,9 +78,6 @@ function editwebpage_content(&$a) { return; } - // Now we've got a post and an owner, let's find out if we're allowed to edit it - - $observer = $a->get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); $perms = get_all_perms($owner,$ob_hash); @@ -45,14 +87,13 @@ function editwebpage_content(&$a) { return; } + // We've already figured out which item we want and whose copy we need, + // so we don't need anything fancy here - - // We've already figured out which item we want and whose copy we need, so we don't need anything fancy here $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", intval($post_id), intval($owner) - ); - + ); if($itm[0]['item_flags'] & ITEM_OBSCURED) { $key = get_config('system','prvkey'); @@ -63,23 +104,17 @@ function editwebpage_content(&$a) { } $item_id = q("select * from item_id where service = 'WEBPAGE' and iid = %d limit 1", - $itm[0]['id'] + intval($itm[0]['id']) ); if($item_id) $page_title = $item_id[0]['sid']; - - - $plaintext = true; -// if(feature_enabled($itm[0]['uid'],'richtext')) -// $plaintext = false; - $mimetype = $itm[0]['mimetype']; if($mimetype === 'application/x-php') { - if((! local_user()) || (local_user() != $itm[0]['uid'])) { + if((! $uid) || ($uid != $itm[0]['uid'])) { notice( t('Permission denied.') . EOL); return; } @@ -101,7 +136,6 @@ function editwebpage_content(&$a) { else $layoutselect = layout_select($itm[0]['uid'],$itm[0]['layout_mid']); - $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Webpage') )); @@ -112,7 +146,7 @@ function editwebpage_content(&$a) { '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), '$geotag' => $geotag, - '$nickname' => $a->user['nickname'], + '$nickname' => $channel['channel_address'], '$confirmdelete' => t('Delete webpage?') )); @@ -124,12 +158,9 @@ function editwebpage_content(&$a) { call_hooks('jot_tool', $jotplugins); call_hooks('jot_networks', $jotnets); - - $channel = $a->get_channel(); - - //$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins)); -//FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD instead of loading a sensible page. So, send folk to the webpage list. + // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD + // instead of loading a sensible page. So, send folk to the webpage list. $rp = 'webpages/' . $which; @@ -164,27 +195,40 @@ function editwebpage_content(&$a) { '$mimeselect' => $mimeselect, '$layoutselect' => $layoutselect, '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), - '$placeholdertitle' => t('Set title'), + '$placeholdertitle' => t('Title (optional)'), '$category' => '', - '$placeholdercategory' => t('Categories (comma-separated list)'), + '$placeholdercategory' => t('Categories (optional, comma-separated list)'), '$emtitle' => t('Example: bob@example.com, mary@example.com'), 'lockstate' => (((strlen($itm[0]['allow_cid'])) || (strlen($itm[0]['allow_gid'])) || (strlen($itm[0]['deny_cid'])) || (strlen($itm[0]['deny_gid']))) ? 'lock' : 'unlock'), '$bang' => '', '$profile_uid' => (intval($owner)), - '$preview' => ((feature_enabled(local_user(),'preview')) ? t('Preview') : ''), + '$preview' => true, // ((feature_enabled($uid,'preview')) ? t('Preview') : ''), '$jotplugins' => $jotplugins, - '$sourceapp' => t($a->sourcename), + '$sourceapp' => $a->sourcename, '$defexpire' => '', '$feature_expire' => false, '$expires' => t('Set expiration date'), )); - $ob = get_observer_hash(); - - if(($itm[0]['author_xchan'] === $ob) || ($itm[0]['owner_xchan'] === $ob)) + if(($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) $o .= '<br /><br /><a class="page-delete-link" href="item/drop/' . $itm[0]['id'] . '" >' . t('Delete Webpage') . '</a><br />'; + + $x = array( + 'type' => 'webpage', + 'title' => $itm[0]['title'], + 'body' => $itm[0]['body'], + 'term' => $itm[0]['term'], + 'created' => $itm[0]['created'], + 'edited' => $itm[0]['edited'], + 'mimetype' => $itm[0]['mimetype'], + 'pagetitle' => $page_title, + 'mid' => $itm[0]['mid'] + ); + + $o .= EOL . EOL . t('Share') . EOL . '<textarea onclick="this.select();" class="shareable_element_text" >[element]' . base64url_encode(json_encode($x)) . '[/element]</textarea>' . EOL . EOL; + return $o; } diff --git a/mod/events.php b/mod/events.php index 02a9d1ed9..e016311d5 100755 --- a/mod/events.php +++ b/mod/events.php @@ -12,23 +12,21 @@ function events_post(&$a) { return; $event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0); + $event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : ''); + $xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : ''); $uid = local_user(); - $startyear = intval($_POST['startyear']); - $startmonth = intval($_POST['startmonth']); - $startday = intval($_POST['startday']); - $starthour = intval($_POST['starthour']); - $startminute = intval($_POST['startminute']); - - $finishyear = intval($_POST['finishyear']); - $finishmonth = intval($_POST['finishmonth']); - $finishday = intval($_POST['finishday']); - $finishhour = intval($_POST['finishhour']); - $finishminute = intval($_POST['finishminute']); + + $start_text = escape_tags($_REQUEST['start_text']); + $finish_text = escape_tags($_REQUEST['finish_text']); $adjust = intval($_POST['adjust']); $nofinish = intval($_POST['nofinish']); + $categories = escape_tags(trim($_POST['category'])); + + + // only allow editing your own events. if(($xchan) && ($xchan !== get_observer_hash())) @@ -37,12 +35,23 @@ function events_post(&$a) { // The default setting for the `private` field in event_store() is false, so mirror that $private_event = false; + if($start_text) { + $start = $start_text; + } + else { + $start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute); + } - $start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute); - if($nofinish) - $finish = '0000-00-00 00:00:00'; - else - $finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute); + if($nofinish) { + $finish = NULL_DATE; + } + + if($finish_text) { + $finish = $finish_text; + } + else { + $finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute); + } if($adjust) { $start = datetime_convert(date_default_timezone_get(),'UTC',$start); @@ -60,17 +69,22 @@ function events_post(&$a) { // and we'll waste a bunch of time responding to it. Time that // could've been spent doing something else. - if(strcmp($finish,$start) < 0) - $finish = $start; $summary = escape_tags(trim($_POST['summary'])); $desc = escape_tags(trim($_POST['desc'])); $location = escape_tags(trim($_POST['location'])); $type = 'event'; + $action = ($event_hash == '') ? 'new' : "event/" . $event_hash; + $onerror_url = $a->get_baseurl() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish"; + if(strcmp($finish,$start) < 0 && !$nofinish) { + notice( t('Event can not end before it has started.') . EOL); + goaway($onerror_url); + } + if((! $summary) || (! $start)) { notice( t('Event title and start time are required.') . EOL); - goaway($a->get_baseurl() . '/events/new'); + goaway($onerror_url); } $share = ((intval($_POST['share'])) ? intval($_POST['share']) : 0); @@ -123,6 +137,22 @@ function events_post(&$a) { } } + $post_tags = array(); + $channel = $a->get_channel(); + + if(strlen($categories)) { + $cats = explode(',',$categories); + foreach($cats as $cat) { + $post_tags[] = array( + 'uid' => $profile_uid, + 'type' => TERM_CATEGORY, + 'otype' => TERM_OBJ_POST, + 'term' => trim($cat), + 'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)) + ); + } + } + $datarray = array(); $datarray['start'] = $start; $datarray['finish'] = $finish; @@ -145,6 +175,11 @@ function events_post(&$a) { $datarray['edited'] = $edited; $event = event_store_event($datarray); + + + if($post_tags) + $datarray['term'] = $post_tags; + $item_id = event_store_item($datarray,$event); if($share) @@ -164,14 +199,14 @@ function events_content(&$a) { nav_set_selected('all_events'); if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) { - $r = q("update event set ignore = 1 where id = %d and uid = %d limit 1", + $r = q("update event set ignore = 1 where id = %d and uid = %d", intval(argv(2)), intval(local_user()) ); } if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) { - $r = q("update event set ignore = 0 where id = %d and uid = %d limit 1", + $r = q("update event set ignore = 0 where id = %d and uid = %d", intval(argv(2)), intval(local_user()) ); @@ -233,13 +268,18 @@ function events_content(&$a) { if($mode == 'view') { - $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); - $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); + $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); + $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); if(! $y) $y = intval($thisyear); if(! $m) $m = intval($thismonth); + $export = false; + if(argc() === 4 && argv(3) === 'export') + $export = true; + + // Put some limits on dates. The PHP date functions don't seem to do so well before 1900. // An upper limit was chosen to keep search engines from exploring links millions of years in the future. @@ -295,8 +335,8 @@ function events_content(&$a) { $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan from event left join item on event_hash = resource_id where resource_type = 'event' and event.uid = %d and event.ignore = %d - AND (( `adjust` = 0 AND ( `finish` >= '%s' or nofinish ) AND `start` <= '%s' ) - OR ( `adjust` = 1 AND ( `finish` >= '%s' or nofinish ) AND `start` <= '%s' )) ", + AND (( `adjust` = 0 AND ( `finish` >= '%s' or nofinish = 1 ) AND `start` <= '%s' ) + OR ( `adjust` = 1 AND ( `finish` >= '%s' or nofinish = 1 ) AND `start` <= '%s' )) ", intval(local_user()), intval($ignored), dbesc($start), @@ -378,6 +418,12 @@ function events_content(&$a) { } } + if($export) { + header('Content-type: text/calendar'); + echo ical_wrapper($r); + killme(); + } + if ($a->argv[1] === 'json'){ echo json_encode($events); killme(); } @@ -397,6 +443,7 @@ function events_content(&$a) { '$new_event'=> array($a->get_baseurl().'/events/new',t('Create New Event'),'',''), '$previus' => array($a->get_baseurl()."/events/$prevyear/$prevmonth",t('Previous'),'',''), '$next' => array($a->get_baseurl()."/events/$nextyear/$nextmonth",t('Next'),'',''), + '$export' => array($a->get_baseurl()."/events/$y/$m/export",t('Export'),'',''), '$calendar' => cal($y,$m,$links, ' eventcal'), '$events' => $events, @@ -420,6 +467,19 @@ function events_content(&$a) { $channel = $a->get_channel(); + // Passed parameters overrides anything found in the DB + if($mode === 'edit' || $mode === 'new') { + if(!x($orig_event)) $orig_event = array(); + // In case of an error the browser is redirected back here, with these parameters filled in with the previous values + if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish']; + if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust']; + if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary']; + if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description']; + if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location']; + if(x($_REQUEST,'start')) $orig_event['start'] = $_REQUEST['start']; + if(x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish']; + } + if($mode === 'edit' || $mode === 'new') { $n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : ''); @@ -451,8 +511,11 @@ function events_content(&$a) { $smonth = datetime_convert('UTC', $tz, $sdt, 'm'); $sday = datetime_convert('UTC', $tz, $sdt, 'd'); + $shour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $sdt, 'H') : 0); $sminute = ((x($orig_event)) ? datetime_convert('UTC', $tz, $sdt, 'i') : 0); + $stext = datetime_convert('UTC',$tz,$sdt); + $stext = substr($stext,0,14) . "00:00"; $fyear = datetime_convert('UTC', $tz, $fdt, 'Y'); $fmonth = datetime_convert('UTC', $tz, $fdt, 'm'); @@ -460,13 +523,32 @@ function events_content(&$a) { $fhour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'H') : 0); $fminute = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'i') : 0); + $ftext = datetime_convert('UTC',$tz,$fdt); + $ftext = substr($ftext,0,14) . "00:00"; $f = get_config('system','event_input_format'); if(! $f) $f = 'ymd'; - $dateformat = datesel_format($f); - $timeformat = t('hour:minute'); + $catsenabled = feature_enabled(local_user(),'categories'); + + $category = ''; + + if($catsenabled && x($orig_event)){ + $itm = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d limit 1", + dbesc($orig_event['event_hash']), + intval(local_user()) + ); + $itm = fetch_post_tags($itm); + if($itm) { + $cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY); + foreach ($cats as $cat) { + if(strlen($category)) + $category .= ', '; + $category .= $cat['term']; + } + } + } require_once('include/acl_selectors.php'); @@ -479,24 +561,28 @@ function events_content(&$a) { $tpl = get_markup_template('event_form.tpl'); - $o .= replace_macros($tpl,array( '$post' => $a->get_baseurl() . '/events', '$eid' => $eid, '$xchan' => $event_xchan, '$mid' => $mid, + '$event_hash' => $event_id, '$title' => t('Event details'), - '$desc' => sprintf( t('Format is %s %s. Starting date and Title are required.'),$dateformat,$timeformat), - + '$desc' => t('Starting date and Title are required.'), + '$catsenabled' => $catsenabled, + '$placeholdercategory' => t('Categories (comma-separated list)'), + '$category' => $category, '$s_text' => t('Event Starts:') . ' <span class="required" title="' . t('Required') . '">*</span>', - '$s_dsel' => datesel($f,'start',$syear+5,$syear,false,$syear,$smonth,$sday), - '$s_tsel' => timesel('start',$shour,$sminute), + '$stext' => $stext, + '$ftext' => $ftext, + '$ModalCANCEL' => t('Cancel'), + '$ModalOK' => t('OK'), + '$s_dsel' => datetimesel($f,new DateTime(),DateTime::createFromFormat('Y',$syear+5),DateTime::createFromFormat('Y-m-d H:i',"$syear-$smonth-$sday $shour:$sminute"),'start_text'), '$n_text' => t('Finish date/time is not known or not relevant'), '$n_checked' => $n_checked, '$f_text' => t('Event Finishes:'), - '$f_dsel' => datesel($f,'finish',$fyear+5,$fyear,false,$fyear,$fmonth,$fday), - '$f_tsel' => timesel('finish',$fhour,$fminute), + '$f_dsel' => datetimesel($f,new DateTime(),DateTime::createFromFormat('Y',$fyear+5),DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"),'finish_text',true,true,'start_text'), '$a_text' => t('Adjust for viewer timezone'), '$a_checked' => $a_checked, '$d_text' => t('Description:'), @@ -507,6 +593,7 @@ function events_content(&$a) { '$t_orig' => $t_orig, '$sh_text' => t('Share this event'), '$sh_checked' => $sh_checked, + '$permissions' => t('Permissions'), '$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults),false)), '$submit' => t('Submit') diff --git a/mod/feed.php b/mod/feed.php index 0f8296ed1..3b622fc17 100644 --- a/mod/feed.php +++ b/mod/feed.php @@ -7,10 +7,14 @@ function feed_init(&$a) { $params = array(); - $params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : '0000-00-00 00:00:00'); + $params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE); $params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : ''); $params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml'); $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); + $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); + $params['start'] = ((x($params,'start')) ? intval($params['start']) : 0); + $params['records'] = ((x($params,'records')) ? intval($params['records']) : 40); + $params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc'); $channel = ''; if(argc() > 1) { diff --git a/mod/filer.php b/mod/filer.php index 3340fc999..9a409177c 100644 --- a/mod/filer.php +++ b/mod/filer.php @@ -27,7 +27,7 @@ function filer_content(&$a) { intval(local_user()) ); if($r) { - $x = q("update item set item_flags = ( item_flags | %d ) where id = %d and uid = %d limit 1", + $x = q("update item set item_flags = ( item_flags | %d ) where id = %d and uid = %d", intval(ITEM_RETAINED), intval($r[0]['parent']), intval(local_user()) diff --git a/mod/filerm.php b/mod/filerm.php index a37e80b31..900cfe60b 100644 --- a/mod/filerm.php +++ b/mod/filerm.php @@ -18,7 +18,7 @@ function filerm_content(&$a) { logger('filerm: tag ' . $term . ' item ' . $item_id); if($item_id && strlen($term)) { - $r = q("delete from term where uid = %d and type = %d and oid = %d and term = '%s' limit 1", + $r = q("delete from term where uid = %d and type = %d and oid = %d and term = '%s'", intval(local_user()), intval(($category) ? TERM_CATEGORY : TERM_FILE), intval($item_id), diff --git a/mod/filestorage.php b/mod/filestorage.php index 383af84fc..0a25617f0 100644 --- a/mod/filestorage.php +++ b/mod/filestorage.php @@ -1,18 +1,26 @@ <?php +/** + * @file mod/filestorage.php + * + */ require_once('include/attach.php'); +/** + * + * @param object &$a + */ function filestorage_post(&$a) { - $channel_id = ((x($_POST,'uid')) ? intval($_POST['uid']) : 0); + $channel_id = ((x($_POST, 'uid')) ? intval($_POST['uid']) : 0); if((! $channel_id) || (! local_user()) || ($channel_id != local_user())) { notice( t('Permission denied.') . EOL); return; } - $recurse = ((x($_POST,'recurse')) ? intval($_POST['recurse']) : 0); - $resource = ((x($_POST,'filehash')) ? notags($_POST['filehash']) : ''); + $recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0); + $resource = ((x($_POST, 'filehash')) ? notags($_POST['filehash']) : ''); if(! $resource) { notice(t('Item not found.') . EOL); @@ -24,11 +32,11 @@ function filestorage_post(&$a) { $str_group_deny = perms2str($_REQUEST['group_deny']); $str_contact_deny = perms2str($_REQUEST['contact_deny']); - attach_change_permissions($channel_id,$resource,$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny,$recurse = false); + attach_change_permissions($channel_id, $resource, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $recurse); //Build directory tree and redirect $channel = $a->get_channel(); - $cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource) ; + $cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource); goaway($cloudPath); } @@ -53,15 +61,15 @@ function filestorage_content(&$a) { $observer = $a->get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - $perms = get_all_perms($owner,$ob_hash); + $perms = get_all_perms($owner, $ob_hash); if(! $perms['view_storage']) { notice( t('Permission denied.') . EOL); return; } - // Since we have ACL'd files in the wild, but don't have ACL here yet, we - // need to return for anyone other than the owner, despite the perms check for now. + // Since we have ACL'd files in the wild, but don't have ACL here yet, we + // need to return for anyone other than the owner, despite the perms check for now. $is_owner = (((local_user()) && ($owner == local_user())) ? true : false); if(! $is_owner) { @@ -69,7 +77,6 @@ function filestorage_content(&$a) { return; } - if(argc() > 3 && argv(3) === 'delete') { if(! $perms['write_storage']) { notice( t('Permission denied.') . EOL); @@ -77,7 +84,7 @@ function filestorage_content(&$a) { } $file = intval(argv(2)); - $r = q("select hash from attach where id = %d and uid = %d limit 1", + $r = q("SELECT hash FROM attach WHERE id = %d AND uid = %d LIMIT 1", dbesc($file), intval($owner) ); @@ -86,11 +93,15 @@ function filestorage_content(&$a) { goaway(z_root() . '/cloud/' . $which); } - attach_delete($owner,$r[0]['hash']); - - goaway(z_root() . '/cloud/' . $which); - } + $f = $r[0]; + $channel = $a->get_channel(); + + $parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']); + + attach_delete($owner, $f['hash']); + goaway($parentpath); + } if(argc() > 3 && argv(3) === 'edit') { require_once('include/acl_selectors.php'); @@ -106,22 +117,24 @@ function filestorage_content(&$a) { ); $f = $r[0]; - $channel = $a->get_channel(); $cloudpath = get_cloudpath($f) . (($f['flags'] & ATTACH_FLAG_DIR) ? '?f=&davguest=1' : ''); $parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']); - $aclselect_e = populate_acl($f,false); + $aclselect_e = populate_acl($f, false); $is_a_dir = (($f['flags'] & ATTACH_FLAG_DIR) ? true : false); $lockstate = (($f['allow_cid'] || $f['allow_gid'] || $f['deny_cid'] || $f['deny_gid']) ? 'lock' : 'unlock'); + // Encode path that is used for link so it's a valid URL + // Keep slashes as slashes, otherwise mod_rewrite doesn't work correctly + $encoded_path = str_replace('%2F', '/', rawurlencode($cloudpath)); $o = replace_macros(get_markup_template('attach_edit.tpl'), array( '$header' => t('Edit file permissions'), '$file' => $f, - '$cloudpath' => z_root() . '/' . $cloudpath, + '$cloudpath' => z_root() . '/' . $encoded_path, '$parentpath' => $parentpath, '$uid' => $channel['channel_id'], '$channelnick' => $channel['channel_address'], @@ -134,13 +147,14 @@ function filestorage_content(&$a) { '$isadir' => $is_a_dir, '$cpdesc' => t('Copy/paste this code to attach file to a post'), '$cpldesc' => t('Copy/paste this URL to link file from a web page'), - '$submit' => t('Submit') - + '$submit' => t('Submit'), + '$attach_btn_title' => t('Attach this file to a new post'), + '$link_btn_title' => t('Show URL to this file'), )); - return $o; - } + echo $o; + killme(); + } goaway(z_root() . '/cloud/' . $which); - } diff --git a/mod/follow.php b/mod/follow.php index 663fb7536..e480a0964 100644 --- a/mod/follow.php +++ b/mod/follow.php @@ -26,10 +26,9 @@ function follow_init(&$a) { // If we can view their stream, pull in some posts - if($result['abook']['abook_their_perms'] & PERMS_R_STREAM) + if(($result['abook']['abook_their_perms'] & PERMS_R_STREAM) || ($result['abook']['xchan_network'] === 'rss')) proc_run('php','include/onepoll.php',$result['abook']['abook_id']); - goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1'); } diff --git a/mod/fsuggest.php b/mod/fsuggest.php index 8b6f077d3..2f4f9606b 100644 --- a/mod/fsuggest.php +++ b/mod/fsuggest.php @@ -52,7 +52,7 @@ function fsuggest_post(&$a) { ); if(count($r)) { $fsuggest_id = $r[0]['id']; - q("UPDATE `fsuggest` SET `note` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", + q("UPDATE `fsuggest` SET `note` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($note), intval($fsuggest_id), intval(local_user()) diff --git a/mod/group.php b/mod/group.php index 0f265f6fb..f67623a83 100644 --- a/mod/group.php +++ b/mod/group.php @@ -44,7 +44,7 @@ function group_post(&$a) { $public = intval($_POST['public']); if((strlen($groupname)) && (($groupname != $group['name']) || ($public != $group['visible']))) { - $r = q("UPDATE `groups` SET `name` = '%s', visible = %d WHERE `uid` = %d AND `id` = %d LIMIT 1", + $r = q("UPDATE `groups` SET `name` = '%s', visible = %d WHERE `uid` = %d AND `id` = %d", dbesc($groupname), intval($public), intval(local_user()), @@ -117,15 +117,15 @@ function group_content(&$a) { check_form_security_token_ForbiddenOnErr('group_member_change', 't'); - $r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and not (xchan_flags & %d) and not (abook_flags & %d) and not (abook_flags & %d) limit 1", - dbesc(argv(2)), + $r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and not (xchan_flags & %d)>0 and not (abook_flags & %d)>0 and not (abook_flags & %d)>0 limit 1", + dbesc(base64url_decode(argv(2))), intval(local_user()), intval(XCHAN_FLAGS_DELETED), intval(ABOOK_FLAG_BLOCKED), intval(ABOOK_FLAG_PENDING) ); if(count($r)) - $change = argv(2); + $change = base64url_decode(argv(2)); } @@ -204,14 +204,14 @@ function group_content(&$a) { foreach($members as $member) { if($member['xchan_url']) { $member['archived'] = (($member['abook_flags'] & ABOOK_FLAG_ARCHIVED) ? true : false); - $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . $member['xchan_hash'] . '\',\'' . $sec_token . '\'); return false;'; + $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;'; $groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode); } else group_rmv_member(local_user(),$group['name'],$member['xchan_hash']); } - $r = q("SELECT abook.*, xchan.* FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel` = %d AND not (abook_flags & %d) and not (xchan_flags & %d) and not (abook_flags & %d) order by xchan_name asc", + $r = q("SELECT abook.*, xchan.* FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel` = %d AND not (abook_flags & %d)>0 and not (xchan_flags & %d)>0 and not (abook_flags & %d)>0 order by xchan_name asc", intval(local_user()), intval(ABOOK_FLAG_BLOCKED), intval(XCHAN_FLAGS_DELETED), @@ -223,7 +223,7 @@ function group_content(&$a) { foreach($r as $member) { if(! in_array($member['xchan_hash'],$preselected)) { $member['archived'] = (($member['abook_flags'] & ABOOK_FLAG_ARCHIVED) ? true : false); - $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . $member['xchan_hash'] . '\',\'' . $sec_token . '\'); return false;'; + $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;'; $groupeditor['contacts'][] = micropro($member,true,'mpall', $textmode); } } diff --git a/mod/hcard.php b/mod/hcard.php new file mode 100644 index 000000000..3cb2fa01e --- /dev/null +++ b/mod/hcard.php @@ -0,0 +1,54 @@ +<?php + +function hcard_init(&$a) { + + if(argc() > 1) + $which = argv(1); + else { + notice( t('Requested profile is not available.') . EOL ); + $a->error = 404; + return; + } + + $profile = ''; + $channel = $a->get_channel(); + + if((local_user()) && (argc() > 2) && (argv(2) === 'view')) { + $which = $channel['channel_address']; + $profile = argv(1); + $r = q("select profile_guid from profile where id = %d and uid = %d limit 1", + intval($profile), + intval(local_user()) + ); + if(! $r) + $profile = ''; + $profile = $r[0]['profile_guid']; + } + + $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/feed/' . $which .'" />' . "\r\n" ; + + if(! $profile) { + $x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1", + dbesc(argv(1)) + ); + if($x) { + $a->profile = $x[0]; + } + } + + profile_load($a,$which,$profile); + + +} + + +function hcard_content(&$a) { + + require_once('include/widgets.php'); + return widget_profile(array()); + + + +} + + diff --git a/mod/help.php b/mod/help.php index 81ecd6ba9..a3dafcc9b 100644 --- a/mod/help.php +++ b/mod/help.php @@ -34,8 +34,6 @@ function help_content(&$a) { $doctype = 'markdown'; - require_once('library/markdown.php'); - $text = ''; if(argc() > 1) { @@ -73,17 +71,22 @@ function help_content(&$a) { )); } - $text = preg_replace_callback("/#include (.*?)\;/ism", 'preg_callback_help_include', $text); - if($doctype === 'html') $content = $text; - if($doctype === 'markdown') + if($doctype === 'markdown') { + require_once('library/markdown.php'); + # escape #include tags + $text = preg_replace('/#include/ism', '%%include', $text); $content = Markdown($text); + $content = preg_replace('/%%include/ism', '#include', $content); + } if($doctype === 'bbcode') { require_once('include/bbcode.php'); $content = bbcode($text); } + $content = preg_replace_callback("/#include (.*?)\;/ism", 'preg_callback_help_include', $content); + return replace_macros(get_markup_template("help.tpl"), array( '$content' => $content )); @@ -93,8 +96,17 @@ function help_content(&$a) { function preg_callback_help_include($matches) { - if($matches[1]) - return str_replace($matches[0],load_doc_file($matches[1]),$matches[0]); + if($matches[1]) { + $include = str_replace($matches[0],load_doc_file($matches[1]),$matches[0]); + if(preg_match('/\.bb$/', $matches[1]) || preg_match('/\.txt$/', $matches[1])) { + require_once('include/bbcode.php'); + $include = bbcode($include); + } elseif(preg_match('/\.md$/', $matches[1])) { + require_once('library/markdown.php'); + $include = Markdown($include); + } + return $include; + } } diff --git a/mod/home.php b/mod/home.php index bc352976d..b2538795f 100644 --- a/mod/home.php +++ b/mod/home.php @@ -9,9 +9,10 @@ function home_init(&$a) { $ret = array(); call_hooks('home_init',$ret); - $channel = $a->get_channel(); + $splash = ((argc() > 1 && argv(1) === 'splash') ? true : false); - if(local_user() && $channel && $channel['xchan_url']) { + $channel = $a->get_channel(); + if(local_user() && $channel && $channel['xchan_url'] && ! $splash) { $dest = $channel['channel_startpage']; if(! $dest) $dest = get_pconfig(local_user(),'system','startpage'); @@ -23,14 +24,14 @@ function home_init(&$a) { goaway($dest); } - if(get_account_id()) { + if(get_account_id() && ! $splash) { goaway(z_root() . '/new_channel'); } } -function home_content(&$a) { +function home_content(&$a, $update = 0, $load = false) { $o = ''; @@ -39,10 +40,31 @@ function home_content(&$a) { if(x($_SESSION,'mobile_theme')) unset($_SESSION['mobile_theme']); + $splash = ((argc() > 1 && argv(1) === 'splash') ? true : false); + + if(get_config('system','projecthome')) { + $o .= file_get_contents('assets/home.html'); + $a->page['template'] = 'full'; + $a->page['title'] = t('Red Matrix - "The Network"'); + return $o; + } + + + // Deprecated $channel_address = get_config("system", "site_channel" ); - if ($channel_address){ + + // See if the sys channel set a homepage + if (! $channel_address) { + require_once('include/identity.php'); + $u = get_sys_channel(); + if ($u) { + $u = array($u); + // change to channel_id when below deprecated and skip the $u=... + $channel_address = $u[0]['channel_address']; + } + } - // We can do better, but until we figure out auto-linkification, let's keep things simple + if($channel_address) { $page_id = 'home'; @@ -50,11 +72,6 @@ function home_content(&$a) { dbesc($channel_address) ); - if(! $u) { - notice( t('Channel not found.') . EOL); - return; - } - $r = q("select item.* from item left join item_id on item.id = item_id.iid where item.uid = %d and sid = '%s' and service = 'WEBPAGE' and item_restrict = %d limit 1", @@ -63,39 +80,161 @@ function home_content(&$a) { intval(ITEM_WEBPAGE) ); - if(! $r) { - notice( t('Item not found.') . EOL); - return; + if($r) { + xchan_query($r); + $r = fetch_post_tags($r,true); + $a->profile = array('profile_uid' => $u[0]['channel_id']); + $a->profile_uid = $u[0]['channel_id']; + $o .= prepare_page($r[0]); + return $o; } - - xchan_query($r); - $r = fetch_post_tags($r,true); - $a->profile = array('profile_uid' => $u[0]['channel_id']); - $o .= prepare_page($r[0]); - return $o; } - if(get_config('system','projecthome')) { - $o .= file_get_contents('assets/home.html'); - $a->page['template'] = 'full'; - $a->page['title'] = t('Red Matrix - "The Network"'); - return $o; - } + // Nope, we didn't find an item. Let's see if there's any html if(file_exists('home.html')) { $o .= file_get_contents('home.html'); } else { - - // If there's no site channel or home contents configured, fallback to the old behaviour - $sitename = get_config('system','sitename'); if($sitename) $o .= '<h1>' . sprintf( t("Welcome to %s") ,$sitename) . '</h1>'; - if (! $a->config['system']['no_login_on_homepage']) - $o .= login(($a->config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1); + + if(intval(get_config('system','block_public')) && (! local_user()) && (! remote_user())) { + // If there's nothing special happening, just spit out a login box + + if (! $a->config['system']['no_login_on_homepage']) + $o .= login(($a->config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1); + return $o; + } + else { + + if(! $update) { + + $maxheight = get_config('system','home_divmore_height'); + if(! $maxheight) + $maxheight = 75; + + $o .= '<div id="live-home"></div>' . "\r\n"; + $o .= "<script> var profile_uid = " . ((intval(local_user())) ? local_user() : (-1)) + . "; var profile_page = " . $a->pager['page'] + . "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; + + $a->page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( + '$baseurl' => z_root(), + '$pgtype' => 'home', + '$uid' => ((local_user()) ? local_user() : '0'), + '$gid' => '0', + '$cid' => '0', + '$cmin' => '0', + '$cmax' => '99', + '$star' => '0', + '$liked' => '0', + '$conv' => '0', + '$spam' => '0', + '$fh' => '1', + '$nouveau' => '0', + '$wall' => '0', + '$list' => '0', + '$page' => (($a->pager['page'] != 1) ? $a->pager['page'] : 1), + '$search' => '', + '$order' => 'comment', + '$file' => '', + '$cats' => '', + '$tags' => '', + '$dend' => '', + '$mid' => '', + '$dbegin' => '' + )); + } + + if($update && ! $load) { + // only setup pagination on initial page view + $pager_sql = ''; + } + else { + $a->set_pager_itemspage(20); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($a->pager['itemspage']), intval($a->pager['start'])); + } + + require_once('include/identity.php'); + $sys = get_sys_channel(); + $uids = " and item.uid = " . intval($sys['channel_id']) . " "; + $a->data['firehose'] = intval($sys['channel_id']); + + $page_mode = 'list'; + + $simple_update = (($update) ? " and ( item.item_flags & " . intval(ITEM_UNSEEN) . " ) > 0 " : ''); + + if($update && $_SESSION['loadtime']) + $simple_update .= " and item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' "; + if($load) + $simple_update = ''; + + //logger('update: ' . $update . ' load: ' . $load); + + if($update) { + + $ordering = "commented"; + + if($load) { + + $_SESSION['loadtime'] = datetime_convert(); + + // Fetch a page full of parent items for this page + + $r = q("SELECT distinct item.id AS item_id, $ordering FROM item + left join abook on item.author_xchan = abook.abook_xchan + WHERE true $uids AND item.item_restrict = 0 + AND item.parent = item.id + and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) + $sql_extra3 $sql_extra $sql_nets + ORDER BY $ordering DESC $pager_sql ", + intval(ABOOK_FLAG_BLOCKED) + ); + + } + + // Then fetch all the children of the parents that are on this page + $parents_str = ''; + $update_unseen = ''; + + if($r) { + + $parents_str = ids_to_querystr($r,'item_id'); + + $items = q("SELECT item.*, item.id AS item_id FROM item + WHERE true $uids AND item.item_restrict = 0 + AND item.parent IN ( %s ) + $sql_extra ", + dbesc($parents_str) + ); + + xchan_query($items,true,(-1)); + $items = fetch_post_tags($items,true); + $items = conv_sort($items,$ordering); + } + else { + $items = array(); + } + + } + + // fake it + $mode = ('network'); + + $o .= conversation($a,$items,$mode,$update,$page_mode); + + if(($items) && (! $update)) + $o .= alt_pager($a,count($items)); + + return $o; + + } + call_hooks('home_content',$o); + return $o; } - - call_hooks('home_content',$o); - return $o; -} + + return $o; + +}
\ No newline at end of file diff --git a/mod/impel.php b/mod/impel.php new file mode 100644 index 000000000..1c7541bef --- /dev/null +++ b/mod/impel.php @@ -0,0 +1,121 @@ +<?php /** @file */ + +// import page design element + + +function impel_init(&$a) { + + $ret = array('success' => false); + + if(! local_user()) + json_return_and_die($ret); + + logger('impel: ' . print_r($_REQUEST,true), LOGGER_DATA); + + $elm = $_REQUEST['element']; + $x = base64url_decode($elm); + if(! $x) + json_return_and_die($ret); + + $j = json_decode($x,true); + if(! $j) + json_return_and_die($ret); + + + $channel = $a->get_channel(); + + $arr = array(); + + switch($j['type']) { + case 'webpage': + $arr['item_restrict'] = ITEM_WEBPAGE; + $namespace = 'WEBPAGE'; + $installed_type = t('webpage'); + break; + case 'block': + $arr['item_restrict'] = ITEM_BUILDBLOCK; + $namespace = 'BUILDBLOCK'; + $installed_type = t('block'); + break; + case 'layout': + $arr['item_restrict'] = ITEM_PDL; + $namespace = 'PDL'; + $installed_type = t('layout'); + break; + default: + logger('mod_impel: unrecognised element type' . print_r($j,true)); + break; + } + $arr['uid'] = local_user(); + $arr['aid'] = $channel['channel_account_id']; + $arr['title'] = $j['title']; + $arr['body'] = $j['body']; + $arr['term'] = $j['term']; + $arr['created'] = datetime_convert('UTC','UTC', $j['created']); + $arr['edited'] = datetime_convert('UTC','UTC',$j['edited']); + $arr['owner_xchan'] = get_observer_hash(); + $arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash()); + $arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode'); + + if(! $j['mid']) + $j['mid'] = item_message_id(); + + $arr['mid'] = $arr['parent_mid'] = $j['mid']; + + + if($j['pagetitle']) { + require_once('library/urlify/URLify.php'); + $pagetitle = strtolower(URLify::transliterate($j['pagetitle'])); + } + + + + // Verify ability to use html or php!!! + + $execflag = false; + + if($arr['mimetype'] === 'application/x-php') { + $z = q("select account_id, account_roles from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", + intval(local_user()) + ); + + if($z && ($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE)) { + $execflag = true; + } + } + + $remote_id = 0; + + $z = q("select * from item_id where sid = '%s' and service = '%s' and uid = %d limit 1", + dbesc($pagetitle), + dbesc($namespace), + intval(local_user()) + ); + $i = q("select id from item where mid = '%s' and uid = %d limit 1", + dbesc($arr['mid']), + intval(local_user()) + ); + if($z && $i) { + $remote_id = $z[0]['id']; + $arr['id'] = $i[0]['id']; + // don't update if it has the same timestamp as the original + if($arr['edited'] > $i[0]['edited']) + $x = item_store_update($arr,$execflag); + } + else { + $x = item_store($arr,$execflag); + } + if($x['success']) + $item_id = $x['item_id']; + + + update_remote_id($channel,$item_id,$arr['item_restrict'],$pagetitle,$namespace,$remote_id,$arr['mid']); + + + $ret['success'] = true; + + info( sprintf( t('%s element installed'), $installed_type)); + + json_return_and_die(true); + +}
\ No newline at end of file diff --git a/mod/import.php b/mod/import.php index d3b237c3a..c9a4edb67 100644 --- a/mod/import.php +++ b/mod/import.php @@ -9,13 +9,28 @@ require_once('include/identity.php'); function import_post(&$a) { - if(! get_account_id()) { + $account_id = get_account_id(); + if(! $account_id) return; + + $max_identities = account_service_class_fetch($account_id,'total_identities'); + $max_friends = account_service_class_fetch($account_id,'total_channels'); + $max_feeds = account_service_class_fetch($account_id,'total_feeds'); + + if($max_identities !== false) { + $r = q("select channel_id from channel where channel_account_id = %d", + intval($account_id) + ); + if($r && count($r) > $max_identities) { + notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL); + return; + } } + $data = null; $seize = ((x($_REQUEST,'make_primary')) ? intval($_REQUEST['make_primary']) : 0); - + $import_posts = ((x($_REQUEST,'import_posts')) ? intval($_REQUEST['import_posts']) : 0); $src = $_FILES['filename']['tmp_name']; $filename = basename($_FILES['filename']['name']); $filesize = intval($_FILES['filename']['size']); @@ -45,6 +60,8 @@ function import_post(&$a) { $scheme = 'https://'; $api_path = '/api/red/channel/export/basic?f=&channel=' . $channelname; + if($import_posts) + $api_path .= '&posts=1'; $binary = false; $redirects = 0; $opts = array('http_auth' => $email . ':' . $password); @@ -84,9 +101,33 @@ function import_post(&$a) { // We should probably also verify the hash if($r) { - logger('mod_import: duplicate channel. ', print_r($channel,true)); - notice( t('Cannot create a duplicate channel identifier on this system. Import failed.') . EOL); - return; + if($r[0]['channel_guid'] === $channel['channel_guid'] || $r[0]['channel_hash'] === $channel['channel_hash']) { + logger('mod_import: duplicate channel. ', print_r($channel,true)); + notice( t('Cannot create a duplicate channel identifier on this system. Import failed.') . EOL); + return; + } + else { + // try at most ten times to generate a unique address. + $x = 0; + $found_unique = false; + do { + $tmp = $channel['channel_address'] . mt_rand(1000,9999); + $r = q("select * from channel where channel_address = '%s' limit 1", + dbesc($tmp) + ); + if(! $r) { + $channel['channel_address'] = $tmp; + $found_unique = true; + break; + } + $x ++; + } while ($x < 10); + if(! $found_unique) { + logger('mod_import: duplicate channel. randomisation failed.', print_r($channel,true)); + notice( t('Unable to create a unique channel address. Import failed.') . EOL); + return; + } + } } unset($channel['channel_id']); @@ -179,13 +220,14 @@ function import_post(&$a) { // create new hubloc for the new channel at this site - $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_flags, + $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_flags, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey ) - values ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )", + values ( '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )", dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_hash']), dbesc($channel['channel_address'] . '@' . get_app()->get_hostname()), + dbesc('zot'), intval(($seize) ? HUBLOC_FLAGS_PRIMARY : 0), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey']))), @@ -197,7 +239,7 @@ function import_post(&$a) { // reset the original primary hubloc if it is being seized if($seize) - $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where (hubloc_flags & %d) and hubloc_hash = '%s' and hubloc_url != '%s' ", + $r = q("update hubloc set hubloc_flags = (hubloc_flags & ~%d) where (hubloc_flags & %d)>0 and hubloc_hash = '%s' and hubloc_url != '%s' ", intval(HUBLOC_FLAGS_PRIMARY), intval(HUBLOC_FLAGS_PRIMARY), dbesc($channel['channel_hash']), @@ -210,7 +252,7 @@ function import_post(&$a) { // replace our existing xchan if we're seizing control - $r = q("delete from xchan where xchan_hash = '%s' limit 1", + $r = q("delete from xchan where xchan_hash = '%s'", dbesc($channel['channel_hash']) ); @@ -255,12 +297,12 @@ function import_post(&$a) { require_once('include/photo/photo_driver.php'); $photos = import_profile_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']); if($photos[4]) - $photodate = '0000-00-00 00:00:00'; + $photodate = NULL_DATE; else $photodate = $xchan['xchan_photo_date']; $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' - where xchan_hash = '%s' limit 1", + where xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), @@ -275,10 +317,18 @@ function import_post(&$a) { // FIXME - ensure we have an xchan if somebody is trying to pull a fast one + $friends = 0; + $feeds = 0; + // import contacts $abooks = $data['abook']; if($abooks) { foreach($abooks as $abook) { + if($max_friends !== false && $friends > $max_friends) + continue; + if($max_feeds !== false && ($abook['abook_flags'] & ABOOK_FLAG_FEED) && $feeds > $max_feeds) + continue; + unset($abook['abook_id']); $abook['abook_account'] = get_account_id(); $abook['abook_channel'] = $channel['channel_id']; @@ -288,6 +338,10 @@ function import_post(&$a) { . "`) VALUES ('" . implode("', '", array_values($abook)) . "')" ); + + $friends ++; + if($abook['abook_flags'] & ABOOK_FLAG_FEED) + $feeds ++; } } @@ -314,7 +368,7 @@ function import_post(&$a) { unset($group['id']); $group['uid'] = $channel['channel_id']; dbesc_array($group); - $r = dbq("INSERT INTO group (`" + $r = dbq("INSERT INTO groups (`" . implode("`, `", array_keys($group)) . "`) VALUES ('" . implode("', '", array_values($group)) @@ -348,18 +402,75 @@ function import_post(&$a) { } } -// FIXME - ensure we have a self entry if somebody is trying to pull a fast one + $saved_notification_flags = notifications_off($channel['channel_id']); - if($seize) { - // notify old server that it is no longer primary. - + if($import_posts && array_key_exists('item',$data) && $data['item']) { + + foreach($data['item'] as $i) { + $item = get_item_elements($i); + + $r = q("select id, edited from item where mid = '%s' and uid = %d limit 1", + dbesc($item['mid']), + intval($channel['channel_id']) + ); + if($r) { + if($item['edited'] > $r[0]['edited']) { + $item['id'] = $r[0]['id']; + $item['uid'] = $channel['channel_id']; + item_store_update($item); + continue; + } + } + else { + $item['aid'] = $channel['channel_account_id']; + $item['uid'] = $channel['channel_id']; + $item_result = item_store($item); + } + + } + + } + + notifications_on($channel['channel_id'],$saved_notification_flags); + + if(array_key_exists('item_id',$data) && $data['item_id']) { + foreach($data['item_id'] as $i) { + $r = q("select id from item where mid = '%s' and uid = %d limit 1", + dbesc($i['mid']), + intval($channel['channel_id']) + ); + if(! $r) + continue; + $z = q("select * from item_id where service = '%s' and sid = '%s' and iid = %d and uid = %d limit 1", + dbesc($i['service']), + dbesc($i['sid']), + intval($r[0]['id']), + intval($channel['channel_id']) + ); + if(! $z) { + q("insert into item_id (iid,uid,sid,service) values(%d,%d,'%s','%s')", + intval($r[0]['id']), + intval($channel['channel_id']), + dbesc($i['sid']), + dbesc($i['service']) + ); + } + } } + + +// FIXME - ensure we have a self entry if somebody is trying to pull a fast one + + // send out refresh requests + // notify old server that it may no longer be primary. + + proc_run('php','include/notifier.php','location',$channel['channel_id']); + // This will indirectly perform a refresh_all *and* update the directory proc_run('php', 'include/directory.php', $channel['channel_id']); - // send out refresh requests notice( t('Import completed.') . EOL); @@ -367,7 +478,6 @@ function import_post(&$a) { goaway(z_root() . '/network' ); - } @@ -388,6 +498,7 @@ function import_content(&$a) { '$label_old_pass' => t('Your old login password'), '$common' => t('For either option, please choose whether to make this hub your new primary address, or whether your old location should continue this role. You will be able to post from either location, but only one can be marked as the primary location for files, photos, and media.'), '$label_import_primary' => t('Make this hub my primary location'), + '$label_import_posts' => t('Import existing posts if possible'), '$email' => '', '$pass' => '', '$submit' => t('Submit') diff --git a/mod/invite.php b/mod/invite.php index 9e37d1e6d..12080c4d9 100644 --- a/mod/invite.php +++ b/mod/invite.php @@ -117,18 +117,6 @@ function invite_content(&$a) { } } -// $dirloc = get_config('system','directory_submit_url'); -// if(strlen($dirloc)) { -// if($a->config['system']['register_policy'] == REGISTER_CLOSED) -// $linktxt = sprintf( t('Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks.'), dirname($dirloc) . '/siteinfo'); -// elseif($a->config['system']['register_policy'] != REGISTER_CLOSED) -// $linktxt = sprintf( t('To accept this invitation, please visit and register at %s or any other public Friendica website.'), $a->get_baseurl()) -// . "\r\n" . "\r\n" . sprintf( t('Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join.'),dirname($dirloc) . '/siteinfo'); -// } -// else { -// $o = t('Our apologies. This system is not currently configured to connect with other public sites or invite members.'); -// return $o; -// } $ob = $a->get_observer(); if(! $ob) @@ -141,18 +129,16 @@ function invite_content(&$a) { '$invite' => t('Send invitations'), '$addr_text' => t('Enter email addresses, one per line:'), '$msg_text' => t('Your message:'), - '$default_message' => t('You are cordially invited to join me and some other close friends on the Red Matrix - a revolutionary new decentralised communication and information tool.') . "\r\n" . "\r\n" + '$default_message' => t('Please join my community on RedMatrix.') . "\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('Please visit my channel at') + . (($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 RedMatrix location (they are all inter-connected)') + . "\r\n" . "\r\n" . z_root() . '/register' + . "\r\n" . "\r\n" . t('2. Enter my RedMatrix 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" - . z_root() . "/channel/" . $channel['channel_address'] - . "\r\n" . "\r\n" - . t('Once you have registered (on ANY Red Matrix site - they are all inter-connected), please connect with my Red Matrix channel address:') - . "\r\n" . "\r\n" . $ob['xchan_addr'] - . "\r\n" . "\r\n" . t('Click the [Register] link on the following page to join.') . "\r\n" . "\r\n" . z_root() - - . "\r\n" . "\r\n" . t('For more information about the Red Matrix Project and why it has the potential to change the internet as we know it, please visit http://getzot.com') . "\r\n" . "\r\n" , + . t('3. Click [Connect]') + . "\r\n" . "\r\n" , '$submit' => t('Submit') )); diff --git a/mod/item.php b/mod/item.php index d4739244a..894e23a0f 100644 --- a/mod/item.php +++ b/mod/item.php @@ -32,8 +32,17 @@ function item_post(&$a) { require_once('include/security.php'); $uid = local_user(); - $channel = null; + $observer = null; + + $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0); + require_once('include/identity.php'); + $sys = get_sys_channel(); + if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) { + $uid = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } if(x($_REQUEST,'dropitems')) { require_once('include/items.php'); @@ -70,30 +79,32 @@ function item_post(&$a) { $message_id = ((x($_REQUEST,'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : ''); $created = ((x($_REQUEST,'created')) ? datetime_convert('UTC','UTC',$_REQUEST['created']) : datetime_convert()); - $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0); $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0); $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''); $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : ''); $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0); $categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : ''); $webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0); - $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags($_REQUEST['pagetitle']) : ''); + $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : ''); $layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): ''); $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : ''); + // allow API to bulk load a bunch of imported items with sending out a bunch of posts. + $nopush = ((x($_REQUEST,'nopush')) ? intval($_REQUEST['nopush']) : 0); /* - Check service class limits - */ - if (local_user() && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) { - $ret=item_check_service_class(local_user(),x($_REQUEST,'webpage')); - if (!$ret['success']) { - notice( t($ret['message']) . EOL) ; - if(x($_REQUEST,'return')) + * Check service class limits + */ + if ($uid && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) { + $ret = item_check_service_class($uid,x($_REQUEST,'webpage')); + if (!$ret['success']) { + notice( t($ret['message']) . EOL) ; + if(x($_REQUEST,'return')) goaway($a->get_baseurl() . "/" . $return_path ); killme(); + } } - } + if($pagetitle) { require_once('library/urlify/URLify.php'); $pagetitle = strtolower(URLify::transliterate($pagetitle)); @@ -109,6 +120,7 @@ function item_post(&$a) { $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0); $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : ''); + $route = ''; $parent_item = null; $parent_contact = null; $thr_parent = ''; @@ -125,11 +137,11 @@ function item_post(&$a) { intval($parent) ); } - elseif($parent_mid && local_user()) { + elseif($parent_mid && $uid) { // This is coming from an API source, and we are logged in $r = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_mid), - intval(local_user()) + intval($uid) ); } // if this isn't the real parent of the conversation, find it @@ -160,12 +172,12 @@ function item_post(&$a) { $thr_parent = $parent_mid; + $route = $parent_item['route']; } - - $observer = $a->get_observer(); - + if(! $observer) + $observer = $a->get_observer(); if($parent) { logger('mod_item: item_post parent=' . $parent); @@ -218,7 +230,7 @@ function item_post(&$a) { if(! $channel) { - if(local_user() && local_user() == $profile_uid) { + if($uid && $uid == $profile_uid) { $channel = $a->get_channel(); } else { @@ -254,12 +266,32 @@ function item_post(&$a) { killme(); } + $walltowall = false; + $walltowall_comment = false; + if($observer) { logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG); - } - + // wall-to-wall detection. + // For top-level posts, if the author and owner are different it's a wall-to-wall + // For comments, We need to additionally look at the parent and see if it's a wall post that originated locally. + if($observer['xchan_name'] != $owner_xchan['xchan_name']) { + if($parent_item && ($parent_item['item_flags'] & (ITEM_WALL|ITEM_ORIGIN)) == (ITEM_WALL|ITEM_ORIGIN)) { + $walltowall_comment = true; + $walltowall = true; + } + if(! $parent) { + $walltowall = true; + } + } + } + + $public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'],true)); + if($webpage) + $public_policy = ''; + if($public_policy) + $private = 1; if($orig_post) { $private = 0; @@ -275,12 +307,14 @@ function item_post(&$a) { $str_contact_allow = $orig_post['allow_cid']; $str_group_deny = $orig_post['deny_gid']; $str_contact_deny = $orig_post['deny_cid']; + $public_policy = $orig_post['public_policy']; } if((strlen($str_group_allow)) || strlen($str_contact_allow) || strlen($str_group_deny) - || strlen($str_contact_deny)) { + || strlen($str_contact_deny) + || strlen($public_policy)) { $private = 1; } @@ -321,6 +355,15 @@ function item_post(&$a) { $str_group_deny = $channel['channel_deny_gid']; $str_contact_deny = $channel['channel_deny_cid']; } + elseif($walltowall) { + + // use the channel owner's default permissions + + $str_group_allow = $channel['channel_allow_gid']; + $str_contact_allow = $channel['channel_allow_cid']; + $str_group_deny = $channel['channel_deny_gid']; + $str_contact_deny = $channel['channel_deny_cid']; + } else { // use the posted permissions @@ -344,6 +387,7 @@ function item_post(&$a) { || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) + || strlen($public_policy) ) ? 1 : 0); // If this is a comment, set the permissions from the parent. @@ -355,10 +399,12 @@ function item_post(&$a) { || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) - || strlen($parent_item['deny_gid'])) { + || strlen($parent_item['deny_gid']) + || strlen($parent_item['public_policy'])) { $private = (($parent_item['item_private']) ? $parent_item['item_private'] : 1); } + $public_policy = $parent_item['public_policy']; $str_contact_allow = $parent_item['allow_cid']; $str_group_allow = $parent_item['allow_gid']; $str_contact_deny = $parent_item['deny_cid']; @@ -377,13 +423,13 @@ function item_post(&$a) { } - $expires = '0000-00-00 00:00:00'; + $expires = NULL_DATE; if(feature_enabled($profile_uid,'content_expire')) { if(x($_REQUEST,'expire')) { $expires = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expire']); if($expires <= datetime_convert()) - $expires = '0000-00-00 00:00:00'; + $expires = NULL_DATE; } } @@ -407,7 +453,7 @@ function item_post(&$a) { intval($profile_uid) ); if($z && ($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE)) { - if(local_user() && (get_account_id() == $z[0]['account_id'])) { + if($uid && (get_account_id() == $z[0]['account_id'])) { $execflag = true; } else { @@ -422,12 +468,15 @@ function item_post(&$a) { if($mimetype === 'text/bbcode') { - if(local_user() && local_user() == $profile_uid && feature_enabled(local_user(),'markdown')) { + require_once('include/text.php'); + if($uid && $uid == $profile_uid && feature_enabled($uid,'markdown')) { require_once('include/bb2diaspora.php'); + $body = escape_tags($body); + $body = preg_replace_callback('/\[share(.*?)\]/ism','share_shield',$body); $body = diaspora2bb($body,true); + $body = preg_replace_callback('/\[share(.*?)\]/ism','share_unshield',$body); } - // BBCODE alert: the following functions assume bbcode input // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.) // we may need virtual or template classes to implement the possible alternatives @@ -555,11 +604,18 @@ function item_post(&$a) { if($fullnametagged) continue; - $success = handle_tag($a, $body, $access_tag, $str_tags, (local_user()) ? local_user() : $profile_uid , $tag); - logger('handle_tag: ' . print_r($success,tue), LOGGER_DATA); + $success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : $profile_uid , $tag); + logger('handle_tag: ' . print_r($success,true), LOGGER_DATA); if(($access_tag) && (! $parent_item)) { logger('access_tag: ' . $tag . ' ' . print_r($access_tag,true), LOGGER_DATA); - if ($first_access_tag) { + if ($first_access_tag && (! get_pconfig($profile_uid,'system','no_private_mention_acl_override'))) { + + // This is a tough call, hence configurable. The issue is that one can type in a @!privacy mention + // and also have a default ACL (perhaps from viewing a collection) and could be suprised that the + // privacy mention wasn't the only recipient. So the default is to wipe out the existing ACL if a + // private mention is found. This can be over-ridden if you wish private mentions to be in + // addition to the current ACL settings. + $str_contact_allow = ''; $str_group_allow = ''; $first_access_tag = false; @@ -629,7 +685,8 @@ function item_post(&$a) { } } - $item_flags |= ITEM_UNSEEN; + if(local_user() != $profile_uid) + $item_flags |= ITEM_UNSEEN; if($post_type === 'wall' || $post_type === 'wall-comment') $item_flags = $item_flags | ITEM_WALL; @@ -705,9 +762,11 @@ function item_post(&$a) { $datarray['item_restrict'] = $item_restrict; $datarray['item_flags'] = $item_flags; $datarray['layout_mid'] = $layout_mid; + $datarray['public_policy'] = $public_policy; $datarray['comment_policy'] = map_scope($channel['channel_w_comment']); $datarray['term'] = $post_tags; $datarray['plink'] = $plink; + $datarray['route'] = $route; // preview mode - prepare the body for display and send it via json @@ -749,7 +808,7 @@ function item_post(&$a) { $datarray['body'] = z_input_filter($datarray['uid'],$datarray['body'],$datarray['mimetype']); - if(local_user()) { + if($uid) { if($channel['channel_hash'] === $datarray['author_xchan']) { $datarray['sig'] = base64url_encode(rsa_sign($datarray['body'],$channel['channel_prvkey'])); $datarray['item_flags'] = $datarray['item_flags'] | ITEM_VERIFIED; @@ -760,9 +819,9 @@ function item_post(&$a) { $key = get_config('system','pubkey'); $datarray['item_flags'] = $datarray['item_flags'] | ITEM_OBSCURED; if($datarray['title']) - $datarray['title'] = json_encode(aes_encapsulate($datarray['title'],$key)); + $datarray['title'] = json_encode(crypto_encapsulate($datarray['title'],$key)); if($datarray['body']) - $datarray['body'] = json_encode(aes_encapsulate($datarray['body'],$key)); + $datarray['body'] = json_encode(crypto_encapsulate($datarray['body'],$key)); } if($orig_post) { @@ -772,7 +831,9 @@ function item_post(&$a) { update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid); - proc_run('php', "include/notifier.php", 'edit_post', $post_id); + if(! $nopush) + proc_run('php', "include/notifier.php", 'edit_post', $post_id); + if((x($_REQUEST,'return')) && strlen($return_path)) { logger('return: ' . $return_path); goaway($a->get_baseurl() . "/" . $return_path ); @@ -782,7 +843,6 @@ function item_post(&$a) { else $post_id = 0; - $post = item_store($datarray,$execflag); $post_id = $post['item_id']; @@ -831,7 +891,7 @@ function item_post(&$a) { // They will show up as people comment on them. if($parent_item['item_restrict'] & ITEM_HIDDEN) { - $r = q("UPDATE `item` SET `item_restrict` = %d WHERE `id` = %d LIMIT 1", + $r = q("UPDATE `item` SET `item_restrict` = %d WHERE `id` = %d", intval($parent_item['item_restrict'] - ITEM_HIDDEN), intval($parent_item['id']) ); @@ -844,6 +904,12 @@ function item_post(&$a) { // NOTREACHED } + if($parent) { + // Store the comment signature information in case we need to relay to Diaspora + $ditem = $datarray; + $ditem['author'] = $observer; + store_diaspora_comment_sig($ditem,$channel,$parent_item, $post_id, (($walltowall_comment) ? 1 : 0)); + } update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid); @@ -852,7 +918,8 @@ function item_post(&$a) { call_hooks('post_local_end', $datarray); - proc_run('php', 'include/notifier.php', $notify_type, $post_id); + if(! $nopush) + proc_run('php', 'include/notifier.php', $notify_type, $post_id); logger('post_complete'); @@ -924,251 +991,14 @@ function item_content(&$a) { } } -/** - * This function removes the tag $tag from the text $body and replaces it with - * the appropiate link. - * - * @param unknown_type $body the text to replace the tag in - * @param unknown_type $access_tag - used to return tag ACL exclusions e.g. @!foo - * @param unknown_type $str_tags string to add the tag to - * @param unknown_type $profile_uid - * @param unknown_type $tag the tag to replace - * - * @return boolean true if replaced, false if not replaced - */ -function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { - - $replaced = false; - $r = null; - - - $termtype = ((strpos($tag,'#') === 0) ? TERM_HASHTAG : TERM_UNKNOWN); - $termtype = ((strpos($tag,'@') === 0) ? TERM_MENTION : $termtype); - $termtype = ((strpos($tag,'#^[') === 0) ? TERM_BOOKMARK : $termtype); - - - //is it a hash tag? - if(strpos($tag,'#') === 0) { - if(strpos($tag,'#^[') === 0) { - if(preg_match('/#\^\[(url|zrl)(.*?)\](.*?)\[\/(url|zrl)\]/',$tag,$match)) { - $basetag = $match[3]; - $url = ((substr($match[2],0,1) === '=') ? substr($match[2],1) : $match[3]); - $replaced = true; - - } - } - // if the tag is already replaced... - elseif(strpos($tag,'[zrl=')) { - //...do nothing - return $replaced; - } - if($tag == '#getzot') { - $basetag = 'getzot'; - $url = 'https://redmatrix.me'; - $newtag = '#[zrl=' . $url . ']' . $basetag . '[/zrl]'; - $body = str_replace($tag,$newtag,$body); - $replaced = true; - } - if(! $replaced) { - - //base tag has the tags name only - - if((substr($tag,0,7) === '#"') && (substr($tag,-6,6) === '"')) { - $basetag = substr($tag,7); - $basetag = substr($basetag,0,-6); - } - else - $basetag = str_replace('_',' ',substr($tag,1)); - - //create text for link - $url = $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag); - $newtag = '#[zrl=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/zrl]'; - //replace tag by the link - $body = str_replace($tag, $newtag, $body); - $replaced = true; - } - //is the link already in str_tags? - if(! stristr($str_tags,$newtag)) { - //append or set str_tags - if(strlen($str_tags)) - $str_tags .= ','; - $str_tags .= $newtag; - } - return array('replaced' => $replaced, 'termtype' => $termtype, 'term' => $basetag, 'url' => $url, 'contact' => $r[0]); - } - - //is it a person tag? - - if(strpos($tag,'@') === 0) { - - // The @! tag will alter permissions - $exclusive = ((strpos($tag,'!') === 1) ? true : false); - - //is it already replaced? - if(strpos($tag,'[zrl=')) - return $replaced; - - //get the person's name - - $name = substr($tag,(($exclusive) ? 2 : 1)); // The name or name fragment we are going to replace - $newname = $name; // a copy that we can mess with - $tagcid = 0; - - $r = null; - - // is it some generated name? - - $forum = false; - $trailing_plus_name = false; - - // @channel+ is a forum or network delivery tag - - if(substr($newname,-1,1) === '+') { - $forum = true; - $newname = substr($newname,0,-1); - } - - // Here we're looking for an address book entry as provided by the auto-completer - // of the form something+nnn where nnn is an abook_id or the first chars of xchan_hash - - if(strrpos($newname,'+')) { - //get the id - - if(strrpos($tagcid,' ')) - $tagcid = substr($tagcid,0,strrpos($tagcid,' ')); - - $tagcid = substr($newname,strrpos($newname,'+') + 1); - - if(strlen($tagcid) < 16) - $abook_id = intval($tagcid); - //remove the next word from tag's name - if(strpos($name,' ')) { - $name = substr($name,0,strpos($name,' ')); - } - - if($abook_id) { // if there was an id - // select channel with that id from the logged in user's address book - $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_id = %d AND abook_channel = %d LIMIT 1", - intval($abook_id), - intval($profile_uid) - ); - } - else { - $r = q("SELECT * FROM xchan - WHERE xchan_hash like '%s%%' LIMIT 1", - dbesc($tagcid) - ); - } - } - - if(! $r) { - - // look for matching names in the address book - - // Two ways to deal with spaces - doube quote the name or use underscores - // we see this after input filtering so quotes have been html entity encoded - - if((substr($name,0,6) === '"') && (substr($name,-6,6) === '"')) { - $newname = substr($name,6); - $newname = substr($newname,0,-6); - } - else - $newname = str_replace('_',' ',$name); - - //select someone from this user's contacts by name - $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash - WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1", - dbesc($newname), - intval($profile_uid) - ); - - if(! $r) { - //select someone by attag or nick and the name passed in - $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash - WHERE xchan_addr like ('%s') AND abook_channel = %d LIMIT 1", - dbesc($newname . '@%'), - intval($profile_uid) - ); - } - - if(! $r) { - - // it's possible somebody has a name ending with '+', which we stripped off as a forum indicator - // This is very rare but we want to get it right. - - $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash - WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1", - dbesc($newname . '+'), - intval($profile_uid) - ); - if($r) - $trailing_plus_name = true; - } - } - - // $r is set if we found something - - if($r) { - $profile = $r[0]['xchan_url']; - $newname = $r[0]['xchan_name']; - // add the channel's xchan_hash to $access_tag if exclusive - if($exclusive) { - $access_tag .= 'cid:' . $r[0]['xchan_hash']; - } - } - else { - // check for a group/collection exclusion tag - - // note that we aren't setting $replaced even though we're replacing text. - // This tag isn't going to get a term attached to it. It's only used for - // access control. The link points to out own channel just so it doesn't look - // weird - as all the other tags are linked to something. - - if(local_user() && local_user() == $profile_uid) { - require_once('include/group.php'); - $grp = group_byname($profile_uid,$name); - if($grp) { - $g = q("select hash from groups where id = %d and visible = 1 limit 1", - intval($grp[0]['id']) - ); - if($g && $exclusive) { - $access_tag .= 'gid:' . $g[0]['hash']; - } - $channel = get_app()->get_channel(); - if($channel) { - $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $newname . '[/zrl]'; - $body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body); - } - } - } - } - - // if there is an url for this channel - - if(isset($profile)) { - $replaced = true; - //create profile link - $profile = str_replace(',','%2c',$profile); - $url = $profile; - $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . (($forum && ! $trailing_plus_name) ? '+' : '') . '[/zrl]'; - $body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body); - //append tag to str_tags - if(! stristr($str_tags,$newtag)) { - if(strlen($str_tags)) - $str_tags .= ','; - $str_tags .= $newtag; - } - } - } - return array('replaced' => $replaced, 'termtype' => $termtype, 'term' => $newname, 'url' => $url, 'contact' => $r[0]); -} - - function fix_attached_photo_permissions($uid,$xchan_hash,$body, $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny) { + if(get_pconfig($uid,'system','force_public_uploads')) { + $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = ''; + } + $match = null; // match img and zmg image links if(preg_match_all("/\[[zi]mg(.*?)\](.*?)\[\/[zi]mg\]/",$body,$match)) { @@ -1218,7 +1048,7 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body, $private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false); $r = q("UPDATE item SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d - WHERE id = %d AND uid = %d limit 1", + WHERE id = %d AND uid = %d", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), @@ -1238,6 +1068,10 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body, function fix_attached_file_permissions($channel,$observer_hash,$body, $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny) { + if(get_pconfig($channel['channel_id'],'system','force_public_uploads')) { + $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = ''; + } + $match = false; if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",$body,$match)) { @@ -1258,12 +1092,13 @@ function fix_attached_file_permissions($channel,$observer_hash,$body, } } } + function item_check_service_class($channel_id,$iswebpage) { $ret = array('success' => false, $message => ''); if ($iswebpage) { $r = q("select count(i.id) as total from item i right join channel c on (i.author_xchan=c.channel_hash and i.uid=c.channel_id ) - and i.parent=i.id and (i.item_restrict & %d) and not (i.item_restrict & %d) and i.uid= %d ", + and i.parent=i.id and (i.item_restrict & %d)>0 and not (i.item_restrict & %d)>0 and i.uid= %d ", intval(ITEM_WEBPAGE), intval(ITEM_DELETED), intval($channel_id) @@ -1296,3 +1131,4 @@ function item_check_service_class($channel_id,$iswebpage) { $ret['success'] = true; return $ret; } + diff --git a/mod/layouts.php b/mod/layouts.php index 318e6e29f..aaf5db0ef 100644 --- a/mod/layouts.php +++ b/mod/layouts.php @@ -1,36 +1,82 @@ <?php -function layouts_content(&$a) { +require_once('include/identity.php'); +require_once('include/conversation.php'); +require_once('include/acl_selectors.php'); + +function layouts_init(&$a) { + + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } if(argc() > 1) $which = argv(1); - else { + else + return; + + profile_load($a,$which); + +} + + +function layouts_content(&$a) { + + if(! $a->profile) { notice( t('Requested profile is not available.') . EOL ); $a->error = 404; return; } - profile_load($a,$which,0); + $which = argv(1); + $uid = local_user(); + $owner = 0; + $channel = null; + $observer = $a->get_observer(); - // Figure out who the page owner is. - $r = q("select channel_id from channel where channel_address = '%s'", - dbesc($which) - ); - if($r) { - $owner = intval($r[0]['channel_id']); + $channel = $a->get_channel(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } + } + + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) + ); + if($r) { + $owner = intval($r[0]['channel_id']); + } + } + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + $perms = get_all_perms($owner,$ob_hash); + + if(! $perms['write_pages']) { + notice( t('Permission denied.') . EOL); + return; } // Block design features from visitors - if((! local_user()) || (local_user() != $owner)) { + if((! $uid) || ($uid != $owner)) { notice( t('Permission denied.') . EOL); return; } // Get the observer, check their permissions - $observer = $a->get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); $perms = get_all_perms($owner,$ob_hash); @@ -41,7 +87,9 @@ function layouts_content(&$a) { } if((argc() > 3) && (argv(2) === 'share') && (argv(3))) { - $r = q("select sid, service, mimetype, title, body from item_id left join item on item.id = item_id.iid where item_id.uid = %d and item.mid = '%s' and service = 'PDL' order by sid asc", + $r = q("select sid, service, mimetype, title, body from item_id + left join item on item.id = item_id.iid + where item_id.uid = %d and item.mid = '%s' and service = 'PDL' order by sid asc", intval($owner), dbesc(argv(3)) ); @@ -63,34 +111,38 @@ function layouts_content(&$a) { 'id' => 'layout-help-tab', )); - $o .= replace_macros(get_markup_template('common_tabs.tpl'),array('$tabs' => $tabs)); // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages - // Nickname is set to the observers xchan, and profile_uid to the owners. This lets you post pages at other people's channels. - - require_once ('include/conversation.php'); + // Nickname is set to the observers xchan, and profile_uid to the owners. + // This lets you post pages at other people's channels. $x = array( - 'webpage' => ITEM_PDL, - 'is_owner' => true, - 'nickname' => $a->profile['channel_address'], - 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'bang' => (($group || $cid) ? '!' : ''), - 'showacl' => false, - 'visitor' => false, - 'nopreview' => 1, - 'ptlabel' => t('Layout Name'), + 'webpage' => ITEM_PDL, + 'is_owner' => true, + 'nickname' => $a->profile['channel_address'], + 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'bang' => '', + 'showacl' => false, + 'visitor' => false, + 'nopreview' => 1, + 'ptlabel' => t('Layout Name'), 'profile_uid' => intval($owner), ); - $o .= status_editor($a,$x); + if($_REQUEST['title']) + $x['title'] = $_REQUEST['title']; + if($_REQUEST['body']) + $x['body'] = $_REQUEST['body']; + if($_REQUEST['pagetitle']) + $x['pagetitle'] = $_REQUEST['pagetitle']; + - // Get a list of blocks. We can't display all them because endless scroll makes that unusable, so just list titles and an edit link. - // TODO - this should be replaced with pagelist_widget + $o .= status_editor($a,$x); - $r = q("select iid, sid, mid from item_id left join item on item.id = item_id.iid where item_id.uid = %d and service = 'PDL' order by sid asc", + $r = q("select iid, sid, mid from item_id left join item on item.id = item_id.iid + where item_id.uid = %d and service = 'PDL' order by sid asc", intval($owner) ); @@ -99,24 +151,28 @@ function layouts_content(&$a) { if($r) { $pages = array(); foreach($r as $rr) { - $pages[$rr['iid']][] = array('url' => $rr['iid'],'title' => $rr['sid'], 'mid' => $rr['mid']); + $pages[$rr['iid']][] = array( + 'url' => $rr['iid'], + 'title' => $rr['sid'], + 'mid' => $rr['mid'] + ); } } - //Build the base URL for edit links - $url = z_root() . "/editlayout/" . $which; + $url = z_root() . '/editlayout/' . $which; - return $o . replace_macros(get_markup_template("layoutlist.tpl"), array( + $o .= replace_macros(get_markup_template('layoutlist.tpl'), array( '$baseurl' => $url, - '$edit' => t('Edit'), - '$share' => t('Share'), - '$pages' => $pages, + '$edit' => t('Edit'), + '$share' => t('Share'), + '$pages' => $pages, '$channel' => $which, - '$view' => t('View'), + '$view' => t('View'), '$preview' => '1', )); + return $o; } diff --git a/mod/like.php b/mod/like.php index 916faf230..04a2b43cd 100755 --- a/mod/like.php +++ b/mod/like.php @@ -209,13 +209,17 @@ function like_content(&$a) { } else { + // this is used to like an item or comment + $item_id = ((argc() == 2) ? notags(trim(argv(1))) : 0); logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG); + // get the item. Allow linked photos (which are normally hidden) to be liked - $r = q("SELECT * FROM item WHERE id = %d and item_restrict = 0 LIMIT 1", - dbesc($item_id) + $r = q("SELECT * FROM item WHERE id = %d and (item_restrict = 0 or item_restrict = %d) LIMIT 1", + intval($item_id), + intval(ITEM_HIDDEN) ); if(! $item_id || (! $r)) { @@ -259,26 +263,18 @@ function like_content(&$a) { else killme(); - - $r = q("SELECT * FROM item WHERE verb = '%s' AND item_restrict = 0 + $r = q("SELECT id FROM item WHERE verb = '%s' AND item_restrict = 0 AND author_xchan = '%s' AND ( parent = %d OR thr_parent = '%s') LIMIT 1", dbesc($activity), dbesc($observer['xchan_hash']), intval($item_id), dbesc($item['mid']) ); - if($r) { - $like_item = $r[0]; - - // Already liked/disliked it, delete it - $r = q("UPDATE item SET item_restrict = ( item_restrict ^ %d ), changed = '%s' WHERE id = %d LIMIT 1", - intval(ITEM_DELETED), - dbesc(datetime_convert()), - intval($like_item['id']) - ); - - proc_run('php',"include/notifier.php","like",$like_item['id']); + if($r) { + // already liked it. Drop that item. + require_once('include/items.php'); + drop_item($r[0]['id'],false,DROPITEM_PHASE1); return; } @@ -325,6 +321,15 @@ function like_content(&$a) { if($item['item_flags'] & ITEM_WALL) $item_flags |= ITEM_WALL; + // if this was a linked photo and was hidden, unhide it. + + if($item['item_restrict'] & ITEM_HIDDEN) { + $r = q("update item set item_restrict = (item_restrict ^ %d) where id = %d", + intval(ITEM_HIDDEN), + intval($item['id']) + ); + } + } if($verb === 'like') diff --git a/mod/lockview.php b/mod/lockview.php index 0ea708c80..e39f2707b 100644 --- a/mod/lockview.php +++ b/mod/lockview.php @@ -16,11 +16,12 @@ function lockview_content(&$a) { if (!in_array($type, array('item','photo','event'))) killme(); - + $r = q("SELECT * FROM %s WHERE id = %d LIMIT 1", dbesc($type), intval($item_id) ); + if(! $r) killme(); @@ -33,7 +34,13 @@ function lockview_content(&$a) { if(($item['item_private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid'])) && (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) { - echo '<li>' . t('Remote privacy information not available.') . '</li>'; + + // if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any + // specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it + // as unknown specific recipients. The sender will have the visibility list and will fall through to the + // next section. + + echo '<li>' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</li>'; killme(); } @@ -78,4 +85,5 @@ function lockview_content(&$a) { echo $o . implode($l); killme(); + } diff --git a/mod/locs.php b/mod/locs.php new file mode 100644 index 000000000..b1169fcca --- /dev/null +++ b/mod/locs.php @@ -0,0 +1,104 @@ +<?php /** @file */ + + +function locs_post(&$a) { + + if(! local_user()) + return; + + $channel = $a->get_channel(); + + if($_REQUEST['primary']) { + $hubloc_id = intval($_REQUEST['primary']); + if($hubloc_id) { + $r = q("select hubloc_id from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1", + intval($hubloc_id), + dbesc($channel['channel_hash']) + ); + if(! $r) { + notice( t('Location not found.') . EOL); + return; + } + $r = q("update hubloc set hubloc_flags = (hubloc_flags & ~%d) where (hubloc_flags & %d)>0 and hubloc_hash = '%s' ", + intval(HUBLOC_FLAGS_PRIMARY), + intval(HUBLOC_FLAGS_PRIMARY), + dbesc($channel['channel_hash']) + ); + $r = q("update hubloc set hubloc_flags = (hubloc_flags & %d) where hubloc_id = %d and hubloc_hash = '%s'", + intval(HUBLOC_FLAGS_PRIMARY), + intval($hubloc_id), + dbesc($channel['channel_hash']) + ); + proc_run('php','include/notifier.php','location',$channel['channel_id']); + return; + } + } + + if($_REQUEST['drop']) { + $hubloc_id = intval($_REQUEST['drop']); + if($hubloc_id) { + $r = q("select hubloc_id, hubloc_flags from hubloc where hubloc_id = %d and hubloc_url != '%s' and hubloc_hash = '%s' limit 1", + intval($hubloc_id), + dbesc(z_root()), + dbesc($channel['channel_hash']) + ); + if(! $r) { + notice( t('Location not found.') . EOL); + return; + } + if($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) { + notice( t('Primary location cannot be removed.') . EOL); + return; + } + $r = q("update hubloc set hubloc_flags = (hubloc_flags & %d) where hubloc_id = %d and hubloc_hash = '%s'", + intval(HUBLOC_FLAGS_DELETED), + intval($hubloc_id), + dbesc($channel['channel_hash']) + ); + proc_run('php','include/notifier.php','location',$channel['channel_id']); + return; + } + } +} + + + +function locs_content(&$a) { + + + + if(! local_user()) { + notice( t('Permission denied.') . EOL); + return; + } + + $channel = $a->get_channel(); + + $r = q("select * from hubloc where hubloc_hash = '%s'", + dbesc($channel['channel_hash']) + ); + + if(! $r) { + notice( t('No locations found.') . EOL); + return; + } + + + for($x = 0; $x < count($r); $x ++) { + $r[$x]['primary'] = (($r[$x]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) ? true : false); + $r[$x]['deleted'] = (($r[$x]['hubloc_flags'] & HUBLOC_FLAGS_DELETED) ? true : false); + } + + + + $o = replace_macros(get_markup_template('locmanage.tpl'), array( + '$header' => t('Manage Channel Locations'), + '$loc' => t('Location (address)'), + '$mkprm' => t('Primary Location'), + '$drop' => t('Drop location'), + '$submit' => t('Submit'), + '$hubs' => $r + )); + + return $o; +}
\ No newline at end of file diff --git a/mod/lostpass.php b/mod/lostpass.php index dd7c7a7d5..3269128f1 100644 --- a/mod/lostpass.php +++ b/mod/lostpass.php @@ -21,7 +21,7 @@ function lostpass_post(&$a) { $hash = random_string(); - $r = q("UPDATE account SET account_reset = '%s' WHERE account_id = %d LIMIT 1", + $r = q("UPDATE account SET account_reset = '%s' WHERE account_id = %d", dbesc($hash), intval($aid) ); @@ -73,7 +73,7 @@ function lostpass_content(&$a) { $salt = random_string(32); $password_encoded = hash('whirlpool', $salt . $new_password); - $r = q("UPDATE account SET account_salt = '%s', account_password = '%s', account_reset = '' where account_id = %d limit 1", + $r = q("UPDATE account SET account_salt = '%s', account_password = '%s', account_reset = '' where account_id = %d", dbesc($salt), dbesc($password_encoded), intval($aid) diff --git a/mod/mail.php b/mod/mail.php index 6976209b7..6c778b956 100644 --- a/mod/mail.php +++ b/mod/mail.php @@ -17,7 +17,7 @@ function mail_post(&$a) { $body = ((x($_REQUEST,'body')) ? escape_tags(trim($_REQUEST['body'])) : ''); $recipient = ((x($_REQUEST,'messageto')) ? notags(trim($_REQUEST['messageto'])) : ''); $rstr = ((x($_REQUEST,'messagerecip')) ? notags(trim($_REQUEST['messagerecip'])) : ''); - $expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : '0000-00-00 00:00:00'); + $expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : NULL_DATE); // If we have a raw string for a recipient which hasn't been auto-filled, // it means they probably aren't in our address book, hence we don't know @@ -72,7 +72,10 @@ function mail_post(&$a) { if(! ($their_perms & PERMS_W_MAIL)) { notice( t('Selected channel has private message restrictions. Send failed.')); - return; + // reported issue: let's still save the message and continue. We'll just tell them + // that nothing useful is likely to happen. They might have spent hours on it. + // return; + } } @@ -110,6 +113,7 @@ function mail_content(&$a) { } $channel = $a->get_channel(); + head_set_icon($channel['xchan_photo_s']); $cipher = get_pconfig(local_user(),'system','default_cipher'); @@ -138,7 +142,7 @@ function mail_content(&$a) { if(! intval(argv(2))) return; $cmd = argv(1); - $r = q("update mail set mail_flags = mail_flags | %d where id = %d and channel_id = %d limit 1", + $r = q("update mail set mail_flags = mail_flags | %d where id = %d and channel_id = %d", intval(MAIL_RECALLED), intval(argv(2)), intval(local_user()) @@ -160,13 +164,16 @@ function mail_content(&$a) { $tpl = get_markup_template('msg-header.tpl'); - $a->page['htmlhead'] .= replace_macros($tpl, array( + $header = replace_macros($tpl, array( '$baseurl' => $a->get_baseurl(true), '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), '$nickname' => $channel['channel_address'], '$linkurl' => t('Please enter a link URL:'), '$expireswhen' => t('Expires YYYY-MM-DD HH:MM') )); + + $a->page['htmlhead'] .= $header; + $preselect = (isset($a->argv[2])?array($a->argv[2]):false); $prename = $preurl = $preid = ''; @@ -229,7 +236,7 @@ function mail_content(&$a) { '$attach' => t('Attach file'), '$insert' => t('Insert web link'), '$wait' => t('Please wait'), - '$submit' => t('Submit'), + '$submit' => t('Send'), '$defexpire' => '', '$feature_expire' => ((feature_enabled(local_user(),'content_expire')) ? true : false), '$expires' => t('Set expiration date'), @@ -273,7 +280,7 @@ function mail_content(&$a) { $tpl = get_markup_template('msg-header.tpl'); $a->page['htmlhead'] .= replace_macros($tpl, array( - '$nickname' => $channel['channel_addr'], + '$nickname' => $channel['channel_address'], '$baseurl' => $a->get_baseurl(true), '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), '$linkurl' => t('Please enter a link URL:'), diff --git a/mod/manage.php b/mod/manage.php index 0772e2d61..b0de945bf 100644 --- a/mod/manage.php +++ b/mod/manage.php @@ -17,7 +17,7 @@ function manage_content(&$a) { intval(get_account_id()) ); if($r) { - q("update account set account_default_channel = %d where account_id = %d limit 1", + q("update account set account_default_channel = %d where account_id = %d", intval($change_channel), intval(get_account_id()) ); @@ -28,34 +28,108 @@ function manage_content(&$a) { if($change_channel) { $r = change_channel($change_channel); - if($r && $r['channel_startpage']) - goaway(z_root() . '/' . $r['channel_startpage']); + if((argc() > 2) && !(argv(2) === 'default')) { + goaway(z_root() . '/' . implode('/',array_slice($a->argv,2))); // Go to whatever is after /manage/, but with the new channel + } + else { + if($r && $r['channel_startpage']) + goaway(z_root() . '/' . $r['channel_startpage']); // If nothing extra is specified, go to the default page + } goaway(z_root()); } $channels = null; if(local_user()) { - $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and not ( channel_pageflags & %d ) order by channel_name ", + $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and not ( channel_pageflags & %d )>0 order by channel_name ", intval(get_account_id()), intval(PAGE_REMOVED) ); - $selected_channel = null; $account = get_app()->get_account(); if($r && count($r)) { $channels = $r; for($x = 0; $x < count($channels); $x ++) { $channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']); - if($channels[$x]['channel_id'] == local_user()) - $selected_channel = $channels[$x]; $channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : ''); $channels[$x]['default_links'] = '1'; + + + $c = q("SELECT id, item_restrict, item_flags FROM item + WHERE (item_restrict = %d) and ( item_flags & %d )>0 and uid = %d", + intval(ITEM_VISIBLE), + intval(ITEM_UNSEEN), + intval($channels[$x]['channel_id']) + ); + + if($c) { + foreach ($c as $it) { + if($it['item_flags'] & ITEM_WALL) + $channels[$x]['home'] ++; + else + $channels[$x]['network'] ++; + } + } + + + $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d)>0 and not ((abook_flags & %d)>0 or (xchan_flags & %d)>0)", + intval($channels[$x]['channel_id']), + intval(ABOOK_FLAG_PENDING), + intval(ABOOK_FLAG_SELF|ABOOK_FLAG_IGNORED), + intval(XCHAN_FLAGS_DELETED|XCHAN_FLAGS_ORPHAN) + ); + + if($intr) + $channels[$x]['intros'] = intval($intr[0]['total']); + + + $mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND not (mail_flags & %d)>0 and from_xchan != '%s' ", + intval($channels[$x]['channel_id']), + intval(MAIL_SEEN), + dbesc($channels[$x]['channel_hash']) + ); + + if($mails) + $channels[$x]['mail'] = intval($mails[0]['total']); + + + $events = q("SELECT type, start, adjust FROM `event` + WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0 + ORDER BY `start` ASC ", + intval($channels[$x]['channel_id']), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) + ); + + if($events) { + $channels[$x]['all_events'] = count($events); + + if($channels[$x]['all_events']) { + $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); + foreach($events as $e) { + $bd = false; + if($e['type'] === 'birthday') { + $channels[$x]['birthdays'] ++; + $bd = true; + } + else { + $channels[$x]['events'] ++; + } + if(datetime_convert('UTC', ((intval($e['adjust'])) ? date_default_timezone_get() : 'UTC'), $e['start'], 'Y-m-d') === $str_now) { + $channels[$x]['all_events_today'] ++; + if($bd) + $channels[$x]['birthdays_today'] ++; + else + $channels[$x]['events_today'] ++; + } + } + } + } } } - $r = q("select count(channel_id) as total from channel where channel_account_id = %d and not ( channel_pageflags & %d )", + $r = q("select count(channel_id) as total from channel where channel_account_id = %d and not ( channel_pageflags & %d )>0", intval(get_account_id()), intval(PAGE_REMOVED) ); @@ -72,16 +146,17 @@ function manage_content(&$a) { array( 'new_channel', t('Create a new channel'), t('Create a new channel')) ); - $o = replace_macros(get_markup_template('channels.tpl'), array( '$header' => t('Channel Manager'), '$msg_selected' => t('Current Channel'), - '$selected' => $selected_channel, - '$desc' => t('Attach to one of your channels by selecting it.'), + '$selected' => local_user(), + '$desc' => t('Switch to one of your channels by selecting it.'), '$msg_default' => t('Default Channel'), '$msg_make_default' => t('Make Default'), '$links' => $links, '$all_channels' => $channels, + '$mail_format' => t('%d new messages'), + '$intros_format' => t('%d new introductions'), '$channel_usage_message' => $channel_usage_message, )); diff --git a/mod/menu.php b/mod/menu.php index a2d0c2385..92923e1ff 100644 --- a/mod/menu.php +++ b/mod/menu.php @@ -1,13 +1,23 @@ <?php require_once('include/menu.php'); +require_once('include/identity.php'); function menu_post(&$a) { - if(! local_user()) + $uid = local_user(); + + if(array_key_exists('sys',$_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { + $sys = get_sys_channel(); + $uid = intval($sys['channel_id']); + $a->is_sys = true; + } + + if(! $uid) return; - $_REQUEST['menu_channel_id'] = local_user(); + $_REQUEST['menu_channel_id'] = $uid; + if($_REQUEST['menu_bookmark']) $_REQUEST['menu_flags'] |= MENU_BOOKMARK; if($_REQUEST['menu_system']) @@ -19,7 +29,7 @@ function menu_post(&$a) { $r = menu_edit($_REQUEST); if($r) { info( t('Menu updated.') . EOL); - goaway(z_root() . '/mitem/' . $menu_id); + goaway(z_root() . '/mitem/' . $menu_id . (($a->is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to update menu.'). EOL); @@ -28,7 +38,7 @@ function menu_post(&$a) { $r = menu_create($_REQUEST); if($r) { info( t('Menu created.') . EOL); - goaway(z_root() . '/mitem/' . $r); + goaway(z_root() . '/mitem/' . $r . (($a->is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to create menu.'). EOL); @@ -40,36 +50,42 @@ function menu_post(&$a) { function menu_content(&$a) { - if(! local_user()) { + $uid = local_user(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + $uid = intval($sys['channel_id']); + } + + if(! $uid) { notice( t('Permission denied.') . EOL); return ''; } -// $a->set_widget('design',design_tools()); - - if(argc() == 1) { // list menus - $x = menu_list(local_user()); - - $o = replace_macros(get_markup_template('menulist.tpl'),array( - '$title' => t('Manage Menus'), - '$menus' => $x, - '$edit' => t('Edit'), - '$drop' => t('Drop'), - '$new' => t('New'), - '$hintnew' => t('Create a new menu'), - '$hintdrop' => t('Delete this menu'), - '$hintcontent' => t('Edit menu contents'), - '$hintedit' => t('Edit this menu') - )); - - return $o; - - + $x = menu_list($uid); + if($x) { + for($y = 0; $y < count($x); $y ++) { + $x[$y]['bookmark'] = (($x[$y]['menu_flags'] & MENU_BOOKMARK) ? true : false); + } + } + $o = replace_macros(get_markup_template('menulist.tpl'),array( + '$title' => t('Manage Menus'), + '$menus' => $x, + '$edit' => t('Edit'), + '$drop' => t('Drop'), + '$new' => t('New'), + '$bmark' => t('Bookmarks allowed'), + '$hintnew' => t('Create a new menu'), + '$hintdrop' => t('Delete this menu'), + '$hintcontent' => t('Edit menu contents'), + '$hintedit' => t('Edit this menu') + )); + return $o; } @@ -87,19 +103,19 @@ function menu_content(&$a) { } elseif(intval(argv(1))) { - $m = menu_fetch_id(intval(argv(1)),local_user()); + $m = menu_fetch_id(intval(argv(1)),$uid); if(! $m) { notice( t('Menu not found.') . EOL); return ''; } if(argc() == 3 && argv(2) == 'drop') { - $r = menu_delete_id(intval(argv(1)),local_user()); + $r = menu_delete_id(intval(argv(1)),$uid); if($r) info( t('Menu deleted.') . EOL); else notice( t('Menu could not be deleted.'). EOL); - goaway(z_root() . '/menu'); + goaway(z_root() . '/menu' . (($a->is_sys) ? '?f=&sys=1' : '')); } else { $o = replace_macros(get_markup_template('menuedit.tpl'), array( diff --git a/mod/message.php b/mod/message.php index c14bf2161..7f3b6180a 100644 --- a/mod/message.php +++ b/mod/message.php @@ -61,18 +61,18 @@ function message_content(&$a) { foreach($r as $rr) { $o .= replace_macros($tpl, array( - '$id' => $rr['id'], - '$from_name' => $rr['from']['xchan_name'], - '$from_url' => chanlink_hash($rr['from_xchan']), + '$id' => $rr['id'], + '$from_name' => $rr['from']['xchan_name'], + '$from_url' => chanlink_hash($rr['from_xchan']), '$from_photo' => $rr['from']['xchan_photo_s'], - '$to_name' => $rr['to']['xchan_name'], - '$to_url' => chanlink_hash($rr['to_xchan']), - '$to_photo' => $rr['to']['xchan_photo_s'], - '$subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'), - '$delete' => t('Delete message'), - '$body' => smilies(bbcode($rr['body'])), - '$date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')), - '$seen' => $rr['seen'] + '$to_name' => $rr['to']['xchan_name'], + '$to_url' => chanlink_hash($rr['to_xchan']), + '$to_photo' => $rr['to']['xchan_photo_s'], + '$subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'), + '$delete' => t('Delete conversation'), + '$body' => smilies(bbcode($rr['body'])), + '$date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')), + '$seen' => $rr['seen'] )); } $o .= alt_pager($a,count($r)); diff --git a/mod/mitem.php b/mod/mitem.php index 3240bb68b..7098d7489 100644 --- a/mod/mitem.php +++ b/mod/mitem.php @@ -4,12 +4,22 @@ require_once('include/menu.php'); require_once('include/acl_selectors.php'); function mitem_init(&$a) { - if(! local_user()) + + $uid = local_user(); + + if(array_key_exists('sys',$_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { + $sys = get_sys_channel(); + $uid = intval($sys['channel_id']); + $a->is_sys = true; + } + + if(! $uid) return; + if(argc() < 2) return; - $m = menu_fetch_id(intval(argv(1)),local_user()); + $m = menu_fetch_id(intval(argv(1)),$uid); if(! $m) { notice( t('Menu not found.') . EOL); return ''; @@ -20,8 +30,18 @@ function mitem_init(&$a) { function mitem_post(&$a) { - if(! local_user()) + $uid = local_user(); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + $uid = intval($sys['channel_id']); + } + + if(! $uid) { return; + } + + if(! $a->data['menu']) return; @@ -29,7 +49,7 @@ function mitem_post(&$a) { $channel = $a->get_channel(); - $_REQUEST['mitem_channel_id'] = local_user(); + $_REQUEST['mitem_channel_id'] = $uid; $_REQUEST['menu_id'] = $a->data['menu']['menu_id']; $_REQUEST['mitem_flags'] = 0; @@ -42,20 +62,20 @@ function mitem_post(&$a) { $mitem_id = ((argc() > 2) ? intval(argv(2)) : 0); if($mitem_id) { $_REQUEST['mitem_id'] = $mitem_id; - $r = menu_edit_item($_REQUEST['menu_id'],local_user(),$_REQUEST); + $r = menu_edit_item($_REQUEST['menu_id'],$uid,$_REQUEST); if($r) { info( t('Menu element updated.') . EOL); - goaway(z_root() . '/mitem/' . $_REQUEST['menu_id']); + goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . (($a->is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to update menu element.') . EOL); } else { - $r = menu_add_item($_REQUEST['menu_id'],local_user(),$_REQUEST); + $r = menu_add_item($_REQUEST['menu_id'],$uid,$_REQUEST); if($r) { info( t('Menu element added.') . EOL); - goaway(z_root() . '/mitem/' . $_REQUEST['menu_id']); + goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . (($a->is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to add menu element.') . EOL); @@ -69,7 +89,20 @@ function mitem_post(&$a) { function mitem_content(&$a) { - if(! local_user()) { + $uid = local_user(); + $channel = $a->get_channel(); + $observer = $a->get_observer(); + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + $uid = intval($sys['channel_id']); + $channel = $sys; + $ob_hash = $sys['xchan_hash']; + } + + if(! $uid) { notice( t('Permission denied.') . EOL); return ''; } @@ -79,67 +112,61 @@ function mitem_content(&$a) { return ''; } - $channel = $a->get_channel(); - - $m = menu_fetch($a->data['menu']['menu_name'],local_user(), get_observer_hash()); + $m = menu_fetch($a->data['menu']['menu_name'],$uid,$ob_hash); $a->data['menu_item'] = $m; if(argc() == 2) { $r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc", intval($a->data['menu']['menu_id']), - local_user() + intval($uid) ); $o .= replace_macros(get_markup_template('mitemlist.tpl'),array( - '$title' => t('Manage Menu Elements'), + '$title' => t('Manage Menu Elements'), '$menuname' => $a->data['menu']['menu_name'], '$menudesc' => $a->data['menu']['menu_desc'], - '$edmenu' => t('Edit menu'), - '$menu_id' => $a->data['menu']['menu_id'], - '$mlist' => $r, - '$edit' => t('Edit element'), - '$drop' => t('Drop element'), - '$new' => t('New element'), + '$edmenu' => t('Edit menu'), + '$menu_id' => $a->data['menu']['menu_id'], + '$mlist' => $r, + '$edit' => t('Edit element'), + '$drop' => t('Drop element'), + '$new' => t('New element'), '$hintmenu' => t('Edit this menu container'), - '$hintnew' => t('Add menu element'), + '$hintnew' => t('Add menu element'), '$hintdrop' => t('Delete this menu item'), '$hintedit' => t('Edit this menu item') - )); - - + )); + return $o; - } if(argc() > 2) { - - if(argv(2) === 'new') { $perm_defaults = array( 'allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], - 'deny_cid' => $channel['channel_deny_cid'], - 'deny_gid' => $channel['channel_deny_gid'] + 'deny_cid' => $channel['channel_deny_cid'], + 'deny_gid' => $channel['channel_deny_gid'] ); $o = replace_macros(get_markup_template('mitemedit.tpl'), array( - '$header' => t('New Menu Element'), - '$menu_id' => $a->data['menu']['menu_id'], + '$header' => t('New Menu Element'), + '$menu_id' => $a->data['menu']['menu_id'], '$permissions' => t('Menu Item Permissions'), - '$permdesc' => t("\x28click to open/close\x29"), - '$aclselect' => populate_acl($perm_defaults,false), - '$mitem_desc' => array('mitem_desc', t('Link text'), '', '','*'), - '$mitem_link' => array('mitem_link', t('URL of link'), '', '', '*'), - '$usezid' => array('usezid', t('Use Red magic-auth if available'), true, ''), - '$newwin' => array('newwin', t('Open link in new window'), false,''), + '$permdesc' => t("\x28click to open/close\x29"), + '$aclselect' => populate_acl($perm_defaults,false), + '$mitem_desc' => array('mitem_desc', t('Link text'), '', '','*'), + '$mitem_link' => array('mitem_link', t('URL of link'), '', '', '*'), + '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), true, ''), + '$newwin' => array('newwin', t('Open link in new window'), false,''), // permissions go here '$mitem_order' => array('mitem_order', t('Order in list'),'0',t('Higher numbers will sink to bottom of listing')), - '$submit' => t('Create') + '$submit' => t('Create') )); return $o; } @@ -148,23 +175,23 @@ function mitem_content(&$a) { elseif(intval(argv(2))) { $m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1", intval(argv(2)), - intval(local_user()) + intval($uid) ); if(! $m) { notice( t('Menu item not found.') . EOL); - goaway(z_root() . '/menu'); + goaway(z_root() . '/menu'. (($a->is_sys) ? '?f=&sys=1' : '')); } $mitem = $m[0]; if(argc() == 4 && argv(3) == 'drop') { - $r = menu_del_item($mitem['mitem_menu_id'], local_user(),intval(argv(2))); + $r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2))); if($r) info( t('Menu item deleted.') . EOL); else notice( t('Menu item could not be deleted.'). EOL); - goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id']); + goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . (($a->is_sys) ? '?f=&sys=1' : '')); } else { @@ -179,7 +206,7 @@ function mitem_content(&$a) { '$mitem_id' => intval(argv(2)), '$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '','*'), '$mitem_link' => array('mitem_link', t('URL of link'), $mitem['mitem_link'], '', '*'), - '$usezid' => array('usezid', t('Use Red magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), ''), + '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), ''), '$newwin' => array('newwin', t('Open link in new window'), (($mitem['mitem_flags'] & MENU_ITEM_NEWWIN) ? 1 : 0),''), // permissions go here '$mitem_order' => array('mitem_order', t('Order in list'),$mitem['mitem_order'],t('Higher numbers will sink to bottom of listing')), @@ -188,10 +215,5 @@ function mitem_content(&$a) { return $o; } } - } - - - - } diff --git a/mod/network.php b/mod/network.php index f12471467..d444dbd59 100644 --- a/mod/network.php +++ b/mod/network.php @@ -24,7 +24,7 @@ function network_content(&$a, $update = 0, $load = false) { if(! local_user()) { $_SESSION['return_url'] = $a->query_string; - return login(false); + return login(false); } @@ -34,6 +34,21 @@ function network_content(&$a, $update = 0, $load = false) { $channel = $a->get_channel(); + + $datequery = $datequery2 = ''; + + $group = 0; + + $nouveau = false; + + $datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); + $datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : ''); + $nouveau = ((x($_GET,'new')) ? intval($_GET['new']) : 0); + $gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0); + $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : ''); + $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); + + $search = (($_GET['search']) ? $_GET['search'] : ''); if($search) { if(strpos($search,'@') === 0) { @@ -47,33 +62,23 @@ function network_content(&$a, $update = 0, $load = false) { } } elseif(strpos($search,'#') === 0) { - $search = $_GET['search'] = substr($search,1); + $hashtags = substr($search,1); + $search = $_GET['search'] = ''; } } - - - $datequery = $datequery2 = ''; - - $group = 0; - - $nouveau = false; - - $datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); - $datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : ''); - $nouveau = ((x($_GET,'new')) ? intval($_GET['new']) : 0); - $gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0); - - if($datequery) $_GET['order'] = 'post'; + + // filter by collection (e.g. group) + if($gid) { - $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1", - intval($gid), - intval(local_user()) - ); - if(! $r) { + $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1", + intval($gid), + intval(local_user()) + ); + if(! $r) { if($update) killme(); notice( t('No such group') . EOL ); @@ -81,27 +86,26 @@ function network_content(&$a, $update = 0, $load = false) { // NOTREACHED } - $group = $gid; + $group = $gid; $group_hash = $r[0]['hash']; - $def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>'); + $def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>'); } $o = ''; - // if no tabs are selected, defaults to comments - $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); - $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); - $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment'); - $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0); - $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0); - $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0); - $cmin = ((x($_GET,'cmin')) ? intval($_GET['cmin']) : 0); - $cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99); - $firehose = ((x($_GET,'fh')) ? intval($_GET['fh']) : 0); - $file = ((x($_GET,'file')) ? $_GET['file'] : ''); + $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); + $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); + $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment'); + $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0); + $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0); + $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0); + $cmin = ((x($_GET,'cmin')) ? intval($_GET['cmin']) : 0); + $cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99); + $firehose = ((x($_GET,'fh')) ? intval($_GET['fh']) : 0); + $file = ((x($_GET,'file')) ? $_GET['file'] : ''); if(x($_GET,'search') || x($_GET,'file')) @@ -122,21 +126,21 @@ function network_content(&$a, $update = 0, $load = false) { $channel_acl = array( 'allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], - 'deny_cid' => $channel['channel_deny_cid'], - 'deny_gid' => $channel['channel_deny_gid'] + 'deny_cid' => $channel['channel_deny_cid'], + 'deny_gid' => $channel['channel_deny_gid'] ); $x = array( - 'is_owner' => true, - 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), + 'is_owner' => true, + 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), 'default_location' => $channel['channel_location'], - 'nickname' => $channel['channel_address'], - 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'acl' => populate_acl((($group || $cid) ? $def_acl : $channel_acl)), - 'bang' => (($group || $cid) ? '!' : ''), - 'visitor' => true, - 'profile_uid' => local_user() + 'nickname' => $channel['channel_address'], + 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'acl' => populate_acl((($group || $cid) ? $def_acl : $channel_acl)), + 'bang' => (($group || $cid) ? '!' : ''), + 'visitor' => true, + 'profile_uid' => local_user() ); $o .= status_editor($a,$x); @@ -146,33 +150,33 @@ function network_content(&$a, $update = 0, $load = false) { // We don't have to deal with ACL's on this page. You're looking at everything // that belongs to you, hence you can see all of it. We will filter by group if - // desired. + // desired. - - $sql_options = (($star) - ? " and (item_flags & " . intval(ITEM_STARRED) . ")" + + $sql_options = (($star) + ? " and (item_flags & " . intval(ITEM_STARRED) . ") > 0" : ''); $sql_nets = ''; - $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ") $sql_options ) "; + $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ")>0 $sql_options ) "; if($group) { $contact_str = ''; - $contacts = group_get_members($group); - if($contacts) { + $contacts = group_get_members($group); + if($contacts) { foreach($contacts as $c) { if($contact_str) $contact_str .= ','; - $contact_str .= "'" . $c['xchan'] . "'"; + $contact_str .= "'" . $c['xchan'] . "'"; } - } - else { - $contact_str = ' 0 '; + } + else { + $contact_str = ' 0 '; info( t('Collection is empty')); - } + } - $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent and item_restrict = 0 ) "; + $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent and item_restrict = 0 ) "; $x = group_rec_byhash(local_user(), $group_hash); @@ -180,60 +184,74 @@ function network_content(&$a, $update = 0, $load = false) { $o = '<h2>' . t('Collection: ') . $x['name'] . '</h2>' . $o; - } + } elseif($cid) { - $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ") limit 1", + $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ") > 0 limit 1", intval($cid), intval(local_user()) - ); - if($r) { - $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_user()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; + ); + if($r) { + $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_user()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; $o = '<h2>' . t('Connection: ') . $r[0]['xchan_name'] . '</h2>' . $o; - } - else { + } + else { notice( t('Invalid connection.') . EOL); goaway($a->get_baseurl(true) . '/network'); - } + } } + if(x($category)) { + $sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY)); + } + if(x($hashtags)) { + $sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG)); + } if(! $update) { // The special div is needed for liveUpdate to kick in for this page. - // We only launch liveUpdate if you aren't filtering in some incompatible + // We only launch liveUpdate if you aren't filtering in some incompatible // way and also you aren't writing a comment (discovered in javascript). if($gid || $cid || $cmin || ($cmax != 99) || $star || $liked || $conv || $spam || $nouveau || $list) - $firehose = 0; + $firehose = 0; + + $maxheight = get_pconfig(local_user(),'system','network_divmore_height'); + if(! $maxheight) + $maxheight = 400; + $o .= '<div id="live-network"></div>' . "\r\n"; - $o .= "<script> var profile_uid = " . $_SESSION['uid'] . "; var profile_page = " . $a->pager['page'] . ";</script>"; + $o .= "<script> var profile_uid = " . local_user() + . "; var profile_page = " . $a->pager['page'] + . "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; $a->page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( '$baseurl' => z_root(), - '$pgtype' => 'network', - '$uid' => ((local_user()) ? local_user() : '0'), - '$gid' => (($gid) ? $gid : '0'), - '$cid' => (($cid) ? $cid : '0'), - '$cmin' => (($cmin) ? $cmin : '0'), - '$cmax' => (($cmax) ? $cmax : '0'), - '$star' => (($star) ? $star : '0'), - '$liked' => (($liked) ? $liked : '0'), - '$conv' => (($conv) ? $conv : '0'), - '$spam' => (($spam) ? $spam : '0'), - '$fh' => (($firehose) ? $firehose : '0'), + '$pgtype' => 'network', + '$uid' => ((local_user()) ? local_user() : '0'), + '$gid' => (($gid) ? $gid : '0'), + '$cid' => (($cid) ? $cid : '0'), + '$cmin' => (($cmin) ? $cmin : '0'), + '$cmax' => (($cmax) ? $cmax : '0'), + '$star' => (($star) ? $star : '0'), + '$liked' => (($liked) ? $liked : '0'), + '$conv' => (($conv) ? $conv : '0'), + '$spam' => (($spam) ? $spam : '0'), + '$fh' => (($firehose) ? $firehose : '0'), '$nouveau' => (($nouveau) ? $nouveau : '0'), - '$wall' => '0', - '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), - '$page' => (($a->pager['page'] != 1) ? $a->pager['page'] : 1), - '$search' => (($search) ? $search : ''), - '$order' => $order, - '$file' => $file, - '$cats' => '', - '$dend' => $datequery, - '$mid' => '', - '$dbegin' => $datequery2 + '$wall' => '0', + '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), + '$page' => (($a->pager['page'] != 1) ? $a->pager['page'] : 1), + '$search' => (($search) ? $search : ''), + '$order' => $order, + '$file' => $file, + '$cats' => $category, + '$tags' => $hashtags, + '$dend' => $datequery, + '$mid' => '', + '$dbegin' => $datequery2 )); } @@ -246,17 +264,19 @@ function network_content(&$a, $update = 0, $load = false) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2)))); } - $sql_extra2 = (($nouveau) ? '' : " AND `item`.`parent` = `item`.`id` "); + $sql_extra2 = (($nouveau) ? '' : " AND item.parent = item.id "); $sql_extra3 = (($nouveau) ? '' : $sql_extra3); if(x($_GET,'search')) { $search = escape_tags($_GET['search']); - if(strpos($search,'#') === 0) + if(strpos($search,'#') === 0) { $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG); - else - $sql_extra .= sprintf(" AND `item`.`body` like '%s' ", + } + else { + $sql_extra .= sprintf(" AND item.body like '%s' ", dbesc(protect_sprintf('%' . $search . '%')) ); + } } if(strlen($file)) { @@ -264,7 +284,7 @@ function network_content(&$a, $update = 0, $load = false) { } if($conv) { - $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or ( item_flags & %d ))) ", + $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or ( item_flags & %d ) > 0)) ", dbesc(protect_sprintf($channel['channel_hash'])), intval(ITEM_MENTIONSME) ); @@ -279,7 +299,7 @@ function network_content(&$a, $update = 0, $load = false) { else { $itemspage = get_pconfig(local_user(),'system','itemspage'); $a->set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage'])); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($a->pager['itemspage']), intval($a->pager['start'])); } @@ -287,7 +307,7 @@ function network_content(&$a, $update = 0, $load = false) { // Not everybody who shows up in the network stream will be in your address book. // By default those that aren't are assumed to have closeness = 99; but this isn't - // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in + // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in // the stream with a NULL address book entry. $sql_nets .= " AND "; @@ -314,18 +334,38 @@ function network_content(&$a, $update = 0, $load = false) { $uids = " and item.uid = " . local_user() . " "; } - $simple_update = (($update) ? " and ( item.item_flags & " . intval(ITEM_UNSEEN) . " ) " : ''); + if(get_pconfig(local_user(),'system','network_list_mode')) + $page_mode = 'list'; + else + $page_mode = 'client'; + + $simple_update = (($update) ? " and ( item.item_flags & " . intval(ITEM_UNSEEN) . " ) > 0 " : ''); + + // This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day + // or three and look at your matrix page - after opening up your browser. The first page loads just as it + // should. All of a sudden a few seconds later, page 2 will get inserted at the beginning of the page + // (before the page 1 content). The update code is actually doing just what it's supposed + // to, it's fetching posts that have the ITEM_UNSEEN bit set. But the reason that page 2 content is being + // returned in an UPDATE is because you hadn't gotten that far yet - you're still on page 1 and everything + // that we loaded for page 1 is now marked as seen. But the stuff on page 2 hasn't been. So... it's being + // treated as "new fresh" content because it is unseen. We need to distinguish it somehow from content + // which "arrived as you were reading page 1". We're going to do this + // by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items + // which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers... + + if($update && $_SESSION['loadtime']) + $simple_update .= " and item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' "; if($load) $simple_update = ''; if($nouveau && $load) { // "New Item View" - show all items unthreaded in reverse created date order - $items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` - WHERE true $uids AND item_restrict = 0 + $items = q("SELECT item.*, item.id AS item_id, received FROM item + WHERE true $uids AND item_restrict = 0 $simple_update $sql_extra $sql_nets - ORDER BY `item`.`received` DESC $pager_sql " + ORDER BY item.received DESC $pager_sql " ); require_once('include/items.php'); @@ -339,27 +379,29 @@ function network_content(&$a, $update = 0, $load = false) { // Normal conversation view if($order === 'post') - $ordering = "`created`"; + $ordering = "created"; else - $ordering = "`commented`"; + $ordering = "commented"; if($load) { + $_SESSION['loadtime'] = datetime_convert(); + // Fetch a page full of parent items for this page - $r = q("SELECT distinct item.id AS item_id FROM item + $r = q("SELECT distinct item.id AS item_id, $ordering FROM item left join abook on item.author_xchan = abook.abook_xchan WHERE true $uids AND item.item_restrict = 0 AND item.parent = item.id and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) $sql_extra3 $sql_extra $sql_nets - ORDER BY item.$ordering DESC $pager_sql ", + ORDER BY $ordering DESC $pager_sql ", intval(ABOOK_FLAG_BLOCKED) ); } else { - if(! $firehose) { + if(! $firehose) { // update $r = q("SELECT item.parent AS item_id FROM item left join abook on item.author_xchan = abook.abook_xchan @@ -379,29 +421,45 @@ function network_content(&$a, $update = 0, $load = false) { $parents_str = ids_to_querystr($r,'item_id'); - $items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` - WHERE true $uids AND `item`.`item_restrict` = 0 - AND `item`.`parent` IN ( %s ) + $items = q("SELECT item.*, item.id AS item_id FROM item + WHERE true $uids AND item.item_restrict = 0 + AND item.parent IN ( %s ) $sql_extra ", dbesc($parents_str) ); - xchan_query($items); + xchan_query($items,true,(($firehose) ? local_user() : 0)); $items = fetch_post_tags($items,true); $items = conv_sort($items,$ordering); - } + } else { $items = array(); } - if($parents_str) - $update_unseen = ' AND parent IN ( ' . dbesc($parents_str) . ' )'; + if($page_mode === 'list') { + + /** + * in "list mode", only mark the parent item and any like activities as "seen". + * We won't distinguish between comment likes and post likes. The important thing + * is that the number of unseen comments will be accurate. The SQL to separate the + * comment likes could also get somewhat hairy. + */ + if($parents_str) { + $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; + $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; + } + } + else { + if($parents_str) { + $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; + } + } } if(($update_unseen) && (! $firehose)) - $r = q("UPDATE `item` SET item_flags = ( item_flags ^ %d) - WHERE (item_flags & %d) AND `uid` = %d $update_unseen ", + $r = q("UPDATE item SET item_flags = ( item_flags & ~%d) + WHERE (item_flags & %d) > 0 AND uid = %d $update_unseen ", intval(ITEM_UNSEEN), intval(ITEM_UNSEEN), intval(local_user()) @@ -409,10 +467,11 @@ function network_content(&$a, $update = 0, $load = false) { $mode = (($nouveau) ? 'network-new' : 'network'); - $o .= conversation($a,$items,$mode,$update,'client'); - if(($items) && (! $update)) - $o .= alt_pager($a,count($items)); + $o .= conversation($a,$items,$mode,$update,$page_mode); + + if(($items) && (! $update)) + $o .= alt_pager($a,count($items)); return $o; } diff --git a/mod/new_channel.php b/mod/new_channel.php index eafef2c08..047048f0a 100644 --- a/mod/new_channel.php +++ b/mod/new_channel.php @@ -1,6 +1,8 @@ <?php require_once('include/identity.php'); +require_once('include/permissions.php'); + function new_channel_init(&$a) { @@ -100,7 +102,7 @@ function new_channel_content(&$a) { $name = ((x($_REQUEST,'name')) ? $_REQUEST['name'] : "" ); $nickname = ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : "" ); - + $privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" ); $o = replace_macros(get_markup_template('new_channel.tpl'), array( @@ -113,6 +115,8 @@ function new_channel_content(&$a) { '$nick_desc' => t('Your nickname will be used to create an easily remembered channel address (like an email address) which you can share with others.'), '$label_import' => t('Or <a href="import">import an existing channel</a> from another location'), '$name' => $name, + '$help_role' => t('Please choose a channel type (such as social networking or community forum) and privacy requirements so we can select the best permissions for you'), + '$role' => array('permissions_role' , t('Channel Type'), ($privacy_role) ? $privacy_role : 'social', '<a href="help/roles" target="_blank">'.t('Read more about roles').'</a>',get_roles()), '$nickname' => $nickname, '$submit' => t('Create') )); diff --git a/mod/notifications.php b/mod/notifications.php index 09f89e88a..5507ee7e2 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -33,7 +33,7 @@ function notifications_post(&$a) { $fid = $r[0]['fid']; if($_POST['submit'] == t('Discard')) { - $r = q("DELETE FROM `intro` WHERE `id` = %d LIMIT 1", + $r = q("DELETE FROM `intro` WHERE `id` = %d", intval($intro_id) ); if(! $fid) { @@ -41,7 +41,7 @@ function notifications_post(&$a) { // The check for blocked and pending is in case the friendship was already approved // and we just want to get rid of the now pointless notification - $r = q("DELETE FROM `contact` WHERE `id` = %d AND `uid` = %d AND `self` = 0 AND `blocked` = 1 AND `pending` = 1 LIMIT 1", + $r = q("DELETE FROM `contact` WHERE `id` = %d AND `uid` = %d AND `self` = 0 AND `blocked` = 1 AND `pending` = 1", intval($contact_id), intval(local_user()) ); @@ -49,7 +49,7 @@ function notifications_post(&$a) { goaway($a->get_baseurl(true) . '/notifications/intros'); } if($_POST['submit'] == t('Ignore')) { - $r = q("UPDATE `intro` SET `ignore` = 1 WHERE `id` = %d LIMIT 1", + $r = q("UPDATE `intro` SET `ignore` = 1 WHERE `id` = %d", intval($intro_id)); goaway($a->get_baseurl(true) . '/notifications/intros'); } diff --git a/mod/oembed.php b/mod/oembed.php index a053a8c98..d4a4424f5 100644 --- a/mod/oembed.php +++ b/mod/oembed.php @@ -19,9 +19,10 @@ function oembed_init(&$a){ else { echo "<html><body>"; - $j = oembed_fetch_url(base64url_decode(argv(1))); + $src = base64url_decode(argv(1)); + $j = oembed_fetch_url($src); echo $j->html; -// logger('mod-oembed ' . $j->html, LOGGER_ALL); +// logger('mod-oembed ' . $h, LOGGER_ALL); echo "</body></html>"; } } diff --git a/mod/openid.php b/mod/openid.php index 2112e0af4..9752db440 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -127,6 +127,8 @@ function openid_content(&$a) { elseif($photo_other) $pphoto = $photo_other; + $mimetype = guess_image_type($pphoto); + $x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype, xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags) @@ -135,7 +137,7 @@ function openid_content(&$a) { dbesc(''), dbesc(''), dbesc(''), - dbesc('image/jpeg'), + dbesc($mimetype), dbesc($pphoto), dbesc($addr), dbesc($url), @@ -157,7 +159,7 @@ function openid_content(&$a) { $photos = import_profile_photo($pphoto,$url); if($photos) { $z = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', - xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' limit 1", + xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), diff --git a/mod/p.php b/mod/p.php new file mode 100644 index 000000000..9d1c12dbc --- /dev/null +++ b/mod/p.php @@ -0,0 +1,52 @@ +<?php /** @file */ + +require_once('include/bb2diaspora.php'); + +// used in Diaspora communications to provide a server copy of a sent post in XML format. + +function p_init(&$a) { + + if(argc() < 2) + http_status_exit(401); + + $mid = str_replace('.xml','',argv(1)); + + $r = q("select * from item where mid = '%s' and (item_flags & %d)>0 and item_private = 0 limit 1", + dbesc($mid), + intval(ITEM_WALL) + ); + + + if((! $r) || (! perm_is_allowed($r[0]['uid'],'','view_stream'))) + http_status_exit(404); + + + $c = q("select * from channel where channel_id = %d limit 1", + intval($r[0]['uid']) + ); + + if(! $c) + http_status_exit(404); + + $myaddr = $c[0]['channel_address'] . '@' . $a->get_hostname(); + + $item = $r[0]; + + $title = $item['title']; + $body = bb2diaspora_itembody($item); + $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); + + $tpl = get_markup_template('diaspora_post.tpl'); + $msg = replace_macros($tpl, array( + '$body' => xmlify($body), + '$guid' => $item['mid'], + '$handle' => xmlify($myaddr), + '$public' => 'true', + '$created' => $created, + '$provider' => (($item['app']) ? $item['app'] : 'redmatrix') + )); + + header('Content-type: text/xml'); + echo $msg; + killme(); +}
\ No newline at end of file diff --git a/mod/page.php b/mod/page.php index b3f53a227..e8f17ebda 100644 --- a/mod/page.php +++ b/mod/page.php @@ -14,13 +14,11 @@ function page_init(&$a) { if($a->profile['profile_uid']) head_set_icon($a->profile['thumb']); -} - + // load the item here in the init function because we need to extract + // the page layout and initialise the correct theme. -function page_content(&$a) { - $observer = $a->get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); @@ -97,11 +95,27 @@ function page_content(&$a) { } } + $a->data['webpage'] = $r; + + + +} + + + + +function page_content(&$a) { + + $r = $a->data['webpage']; + if(! $r) + return; // logger('layout: ' . print_r($a->layout,true)); // Use of widgets should be determined by Comanche, but we don't have it on system pages yet, so... + // I recommend we now get rid of this bit - it's quite a hack to work around... - mike + if ($perms['write_pages']) { $chan = $a->channel['channel_id']; $who = $channel_address; diff --git a/mod/parse_url.php b/mod/parse_url.php index 340e1a67e..23d608411 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -307,7 +307,14 @@ function parse_url_content(&$a) { $max_images = intval($max_images); foreach ($siteinfo["images"] as $imagedata) { - $image .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]' . "\n"; + if ($url) { + $image .= sprintf('[url=%s]', $url); + } + $image .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]'; + if ($url) { + $image .= '[/url]'; + } + $image .= "\n"; $total_images ++; if($max_images && $max_images >= $total_images) break; diff --git a/mod/photo.php b/mod/photo.php index 9302278b6..66280cb76 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -66,12 +66,12 @@ function photo_init(&$a) { intval($uid) ); if(count($r)) { - $data = $r[0]['data']; + $data = dbunescbin($r[0]['data']); $mimetype = $r[0]['type']; } if(! isset($data)) { $data = file_get_contents($default); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; } } else { @@ -140,7 +140,7 @@ function photo_init(&$a) { ); if($r && $allowed) { - $data = $r[0]['data']; + $data = dbunescbin($r[0]['data']); $mimetype = $r[0]['type']; } else { @@ -176,15 +176,15 @@ function photo_init(&$a) { case 4: $data = file_get_contents(get_default_profile_photo()); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; break; case 5: $data = file_get_contents(get_default_profile_photo(80)); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; break; case 6: $data = file_get_contents(get_default_profile_photo(48)); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; break; default: killme(); @@ -224,9 +224,21 @@ function photo_init(&$a) { } else { - - header("Expires: " . gmdate("D, d M Y H:i:s", time() + (3600*24)) . " GMT"); - header("Cache-Control: max-age=" . (3600*24)); + // The photo cache default is 1 day to provide a privacy trade-off, + // as somebody reducing photo permissions on a photo that is already + // "in the wild" won't be able to stop the photo from being viewed + // for this amount amount of time once it is in the browser cache. + // The privacy expectations of your site members and their perception + // of privacy where it affects the entire project may be affected. + // This has performance considerations but we highly recommend you + // leave it alone. + + $cache = get_config('system','photo_cache_time'); + if(! $cache) + $cache = (3600 * 24); // 1 day + + header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT"); + header("Cache-Control: max-age=" . $cache); } echo $data; diff --git a/mod/photos.php b/mod/photos.php index c43beb8d4..8a54eca4f 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -196,7 +196,7 @@ function photos_post(&$a) { } } - goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); + goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']); } if(($a->argc > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false)) || (x($_POST,'albname') !== false)) { @@ -206,6 +206,7 @@ function photos_post(&$a) { $rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : ''); $item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0); $albname = ((x($_POST,'albname')) ? notags(trim($_POST['albname'])) : ''); + $adult = ((x($_POST,'adult')) ? intval($_POST['adult']) : 0); $str_group_allow = perms2str($_POST['group_allow']); $str_contact_allow = perms2str($_POST['contact_allow']); $str_group_deny = perms2str($_POST['group_deny']); @@ -226,7 +227,7 @@ function photos_post(&$a) { intval($page_owner_uid) ); if(count($r)) { - $ph = photo_factory($r[0]['data'], $r[0]['type']); + $ph = photo_factory(dbunescbin($r[0]['data']), $r[0]['type']); if($ph->is_valid()) { $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 ); $ph->rotate($rotate_deg); @@ -234,8 +235,8 @@ function photos_post(&$a) { $width = $ph->getWidth(); $height = $ph->getHeight(); - $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 0 limit 1", - dbesc($ph->imageString()), + $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 0", + dbescbin($ph->imageString()), intval($height), intval($width), dbesc($resource_id), @@ -247,8 +248,8 @@ function photos_post(&$a) { $width = $ph->getWidth(); $height = $ph->getHeight(); - $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 1 limit 1", - dbesc($ph->imageString()), + $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 1", + dbescbin($ph->imageString()), intval($height), intval($width), dbesc($resource_id), @@ -261,8 +262,8 @@ function photos_post(&$a) { $width = $ph->getWidth(); $height = $ph->getHeight(); - $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 2 limit 1", - dbesc($ph->imageString()), + $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 2", + dbescbin($ph->imageString()), intval($height), intval($width), dbesc($resource_id), @@ -273,13 +274,11 @@ function photos_post(&$a) { } } - $p = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `uid` = %d and ( photo_flags = %d or photo_flags = %d ) ORDER BY `scale` DESC", + $p = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `uid` = %d ORDER BY `scale` DESC", dbesc($resource_id), - intval($page_owner_uid), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) + intval($page_owner_uid) ); - if(count($p)) { + if($p) { $ext = $phototypes[$p[0]['type']]; $r = q("UPDATE `photo` SET `description` = '%s', `album` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource_id` = '%s' AND `uid` = %d", @@ -296,6 +295,14 @@ function photos_post(&$a) { $item_private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false); + $old_adult = (($p[0]['photo_flags'] & PHOTO_ADULT) ? 1 : 0); + if($old_adult != $adult) { + $r = q("update photo set photo_flags = ( photo_flags ^ %d) where resource_id = '%s' and uid = %d", + intval(PHOTO_ADULT), + dbesc($resource_id), + intval($page_owner_uid) + ); + } /* Don't make the item visible if the only change was the album name */ @@ -313,15 +320,17 @@ function photos_post(&$a) { intval($item_id), intval($page_owner_uid) ); + + if($r) { + $old_tag = $r[0]['tag']; + $old_inform = $r[0]['inform']; + } } - if($r) { - $old_tag = $r[0]['tag']; - $old_inform = $r[0]['inform']; - } + // make sure the linked item has the same permissions as the photo regardless of any other changes $x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d - where id = %d limit 1", + where id = %d", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), @@ -361,7 +370,7 @@ function photos_post(&$a) { if($fullnametagged) continue; - require_once('mod/item.php'); + require_once('include/text.php'); $body = $access_tag = ''; $success = handle_tag($a, $body, $access_tag, $str_tags, (local_user()) ? local_user() : $a->profile['profile_uid'] , $tag); @@ -380,6 +389,7 @@ function photos_post(&$a) { if($success['replaced']) { $tagged[] = $tag; + $post_tags[] = array( 'uid' => $a->profile['profile_uid'], 'type' => $success['termtype'], @@ -397,8 +407,14 @@ function photos_post(&$a) { ); if($r) { + $r = fetch_post_tags($r,true); $datarray = $r[0]; - $datarray['term'] = $post_tags; + if($post_tags) { + if((! array_key_exists('term',$datarray)) || (! is_array($datarray['term']))) + $datarray['term'] = $post_tags; + else + $datarray['term'] = array_merge($datarray['term'],$post_tags); + } item_store_update($datarray,$execflag); } @@ -420,8 +436,11 @@ function photos_post(&$a) { if(! $r['success']) { notice($r['message'] . EOL); } - - goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); + + if($_REQUEST['newalbum']) + goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum'])); + else + goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC',date_default_timezone_get(),'now', 'Y'))); } @@ -431,20 +450,17 @@ function photos_content(&$a) { // URLs: // photos/name - // photos/name/upload - // photos/name/upload/xxxxx (xxxxx is album name) - // photos/name/album/xxxxx - // photos/name/album/xxxxx/edit + // photos/name/album/xxxxx (xxxxx is album name) // photos/name/image/xxxxx - // photos/name/image/xxxxx/edit if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) { notice( t('Public access denied.') . EOL); return; } - - + + $unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0); + require_once('include/bbcode.php'); require_once('include/security.php'); require_once('include/conversation.php'); @@ -468,11 +484,9 @@ function photos_content(&$a) { if(argc() > 3) { $datatype = argv(2); $datum = argv(3); - } - elseif((argc() > 2) && (argv(2) === 'upload')) - $datatype = 'upload'; - else + } else { $datatype = 'summary'; + } if(argc() > 4) $cmd = argv(4); @@ -495,7 +509,6 @@ function photos_content(&$a) { $can_post = perm_is_allowed($owner_uid,$observer['xchan_hash'],'post_photos'); $can_view = perm_is_allowed($owner_uid,$observer['xchan_hash'],'view_photos'); - if(! $can_view) { notice( t('Access to this item is restricted.') . EOL); return; @@ -513,42 +526,11 @@ function photos_content(&$a) { $_is_owner = (local_user() && (local_user() == $owner_uid)); $o .= profile_tabs($a,$_is_owner, $a->data['channel']['channel_address']); - // - // dispatch request - // - /** * Display upload form */ - if($datatype === 'upload') { - if(! ($can_post)) { - notice( t('Permission denied.')); - return; - } - - - - if(array_key_exists('albums', $a->data)) - $albums = get_app()->data['albums']; - else - $albums = photos_albums_list($a->data['channel'],$a->data['observer']); - - - $selname = (($datum) ? hex2bin($datum) : ''); - $albumselect = '<select id="photos-upload-album-select" name="album" size="4">'; - - $albumselect .= '<option value="" ' . ((! $selname) ? ' selected="selected" ' : '') . '> </option>'; - if(count($albums['albums'])) { - foreach($albums['albums'] as $album) { - if(! $album['text']) - continue; - $selected = (($selname === $album['text']) ? ' selected="selected" ' : ''); - $albumselect .= '<option value="' . $album['text'] . '"' . $selected . '>' . $album['text'] . '</option>'; - } - } - - $albumselect .= '</select>'; + if( $can_post) { $uploader = ''; @@ -556,12 +538,8 @@ function photos_content(&$a) { 'addon_text' => $uploader, 'default_upload' => true); - call_hooks('photo_upload_form',$ret); - $default_upload = '<input id="photos-upload-choose" type="file" name="userfile" /> <div class="photos-upload-submit-wrapper" > - <input type="submit" name="submit" value="' . t('Submit') . '" id="photos-upload-submit" /> </div>'; - /* Show space usage */ $r = q("select sum(size) as total from photo where aid = %d and scale = 0 ", @@ -571,10 +549,10 @@ function photos_content(&$a) { $limit = service_class_fetch($a->data['channel']['channel_id'],'photo_upload_limit'); if($limit !== false) { - $usage_message = sprintf( t("You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."), $r[0]['total'] / 1024000, $limit / 1024000 ); + $usage_message = sprintf( t("%1$.2f MB of %2$.2f MB photo storage used."), $r[0]['total'] / 1024000, $limit / 1024000 ); } else { - $usage_message = sprintf( t('You have used %1$.2f Mbytes of photo storage.'), $r[0]['total'] / 1024000 ); + $usage_message = sprintf( t('%1$.2f MB photo storage used.'), $r[0]['total'] / 1024000 ); } if($_is_owner) { @@ -586,50 +564,71 @@ function photos_content(&$a) { 'deny_cid' => $channel['channel_deny_cid'], 'deny_gid' => $channel['channel_deny_gid'] ); - } - $albumselect_e = $albumselect; + $lockstate = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'); + } + $aclselect_e = (($_is_owner) ? populate_acl($channel_acl,false) : ''); + $selname = (($datum) ? hex2bin($datum) : ''); + + $albums = ((array_key_exists('albums', $a->data)) ? $a->data['albums'] : photos_albums_list($a->data['channel'],$a->data['observer'])); + $tpl = get_markup_template('photos_upload.tpl'); - $o .= replace_macros($tpl,array( + $upload_form = replace_macros($tpl,array( '$pagename' => t('Upload Photos'), '$sessid' => session_id(), '$usage' => $usage_message, '$nickname' => $a->data['channel']['channel_address'], - '$newalbum' => t('New album name: '), - '$existalbumtext' => t('or existing album name: '), + '$newalbum_label' => t('Enter a new album name'), + '$newalbum_placeholder' => t('or select an existing one (doubleclick)'), '$nosharetext' => t('Do not show a status post for this upload'), - '$albumselect' => $albumselect_e, + '$albums' => $albums['albums'], + '$selname' => $selname, '$permissions' => t('Permissions'), '$aclselect' => $aclselect_e, + '$lockstate' => $lockstate, '$uploader' => $ret['addon_text'], - '$default' => (($ret['default_upload']) ? $default_upload : ''), - '$uploadurl' => $ret['post_url'] + '$default' => (($ret['default_upload']) ? true : false), + '$uploadurl' => $ret['post_url'], + '$submit' => t('Submit') )); - return $o; } + // + // dispatch request + // + /* * Display a single photo album */ if($datatype === 'album') { + + + if((strlen($datum) & 1) || (! ctype_xdigit($datum))) { + notice( t('Album name could not be decoded') . EOL); + logger('mod_photos: illegal album encoding: ' . $datum); + $datum = ''; + } + $album = hex2bin($datum); $r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` = '%s' - AND `scale` <= 4 and (photo_flags = %d or photo_flags = %d ) $sql_extra GROUP BY `resource_id`", + AND `scale` <= 4 and ((photo_flags = %d) or (photo_flags & %d ) > 0) $sql_extra GROUP BY `resource_id`", intval($owner_uid), dbesc($album), intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) + intval(($unsafe) ? (PHOTO_PROFILE|PHOTO_ADULT) : PHOTO_PROFILE) ); if(count($r)) { $a->set_pager_total(count($r)); - $a->set_pager_itemspage(40); + $a->set_pager_itemspage(60); + } else { + goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address']); } if($_GET['order'] === 'posted') @@ -637,62 +636,51 @@ function photos_content(&$a) { else $order = 'DESC'; - $r = q("SELECT `resource_id`, `id`, `filename`, type, max(`scale`) AS `scale`, `description` FROM `photo` WHERE `uid` = %d AND `album` = '%s' - AND `scale` <= 4 and (photo_flags = %d or photo_flags = %d ) $sql_extra GROUP BY `resource_id` ORDER BY `created` $order LIMIT %d , %d", + + $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.scale, p.description, p.created FROM photo p INNER JOIN + (SELECT resource_id, max(scale) scale FROM photo WHERE uid = %d AND album = '%s' AND scale <= 4 AND (photo_flags = %d or photo_flags = %d ) $sql_extra GROUP BY resource_id) ph + ON (p.resource_id = ph.resource_id AND p.scale = ph.scale) + ORDER BY created $order LIMIT %d OFFSET %d", intval($owner_uid), dbesc($album), intvaL(PHOTO_NORMAL), - intval(PHOTO_PROFILE), - intval($a->pager['start']), - intval($a->pager['itemspage']) + intval(($unsafe) ? (PHOTO_PROFILE|PHOTO_ADULT) : PHOTO_PROFILE), + intval($a->pager['itemspage']), + intval($a->pager['start']) ); - - $o .= '<h3>' . $album . '</h3>'; - if($cmd === 'edit') { - if(($album !== t('Profile Photos')) && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) { - if($can_post) { - if($a->get_template_engine() === 'internal') { - $album_e = template_escape($album); - } - else { - $album_e = $album; - } - - $edit_tpl = get_markup_template('album_edit.tpl'); - $o .= replace_macros($edit_tpl,array( - '$nametext' => t('New album name: '), - '$nickname' => $a->data['channel']['channel_address'], - '$album' => $album_e, - '$hexalbum' => bin2hex($album), - '$submit' => t('Submit'), - '$dropsubmit' => t('Delete Album') - )); + //edit album name + $album_edit = null; + if(($album !== t('Profile Photos')) && ($album !== 'Profile Photos') && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) { + if($can_post) { + if($a->get_template_engine() === 'internal') { + $album_e = template_escape($album); } - } - } - else { - if(($album !== t('Profile Photos')) && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) { - if($can_post) { - $o .= '<div id="album-edit-link"><a href="'. $a->get_baseurl() . '/photos/' - . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album) . '/edit' . '">' - . t('Edit Album') . '</a></div>'; - } + else { + $album_e = $album; + } + $albums = ((array_key_exists('albums', $a->data)) ? $a->data['albums'] : photos_albums_list($a->data['channel'],$a->data['observer'])); + $edit_tpl = get_markup_template('album_edit.tpl'); + $album_edit = replace_macros($edit_tpl,array( + '$nametext' => t('Enter a new album name'), + '$name_placeholder' => t('or select an existing one (doubleclick)'), + '$nickname' => $a->data['channel']['channel_address'], + '$album' => $album_e, + '$albums' => $albums['albums'], + '$hexalbum' => bin2hex($album), + '$submit' => t('Submit'), + '$dropsubmit' => t('Delete Album') + )); } } if($_GET['order'] === 'posted') - $o .= '<div class="photos-upload-link" ><a href="' . $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album) . '" >' . t('Show Newest First') . '</a></div>'; + $order = array(t('Show Newest First'), $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album)); else - $o .= '<div class="photos-upload-link" ><a href="' . $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted" >' . t('Show Oldest First') . '</a></div>'; - - - if($can_post) { - $o .= '<div class="photos-upload-link" ><a href="' . $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/upload/' . bin2hex($album) . '" >' . t('Upload New Photos') . '</a></div>'; - } + $order = array(t('Show Oldest First'), $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted'); - $tpl = get_markup_template('photo_album.tpl'); - if(count($r)) + $photos = array(); + if(count($r)) { $twist = 'rotright'; foreach($r as $rr) { @@ -706,38 +694,59 @@ function photos_content(&$a) { $imgalt_e = $rr['filename']; $desc_e = $rr['description']; + $imagelink = ($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $rr['resource_id'] + . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '')); + + $photos[] = array( + 'id' => $rr['id'], + 'twist' => ' ' . $twist . rand(2,4), + 'link' => $imagelink, + 'title' => t('View Photo'), + 'src' => $a->get_baseurl() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext, + 'alt' => $imgalt_e, + 'desc'=> $desc_e, + 'ext' => $ext, + 'hash'=> $rr['resource_id'], + 'unknown' => t('Unknown') + ); + } + } -// prettyphoto has potential license issues, so we can no longer include it in core -// The following lines would need to be modified so that they are provided in theme specific files -// instead of core modules for themes that wish to make use of prettyphoto. I would suggest -// the feature as a per-theme display option and putting the rel line inside a template. - -// if(feature_enabled($a->data['channel']['channel_id'],'prettyphoto')){ -// $imagelink = ($a->get_baseurl() . '/photo/' . $rr['resource_id'] . '.' . $ext ); -// $rel=("prettyPhoto[pp_gal]"); -// } -// else { - $imagelink = ($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $rr['resource_id'] - . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '')); - $rel=("photo"); -// } - - $o .= replace_macros($tpl,array( - '$id' => $rr['id'], - '$twist' => ' ' . $twist . rand(2,4), - '$photolink' => $imagelink, - '$rel' => $rel, - '$phototitle' => t('View Photo'), - '$imgsrc' => $a->get_baseurl() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext, - '$imgalt' => $imgalt_e, - '$desc'=> $desc_e, - '$ext' => $ext, - '$hash'=> $rr['resource_id'], + if($_REQUEST['aj']) { + if($photos) { + $o = replace_macros(get_markup_template('photosajax.tpl'),array( + '$photos' => $photos, )); + } + else { + $o = '<div id="content-complete"></div>'; + } + echo $o; + killme(); + } + else { + $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>"; + $tpl = get_markup_template('photo_album.tpl'); + $o .= replace_macros($tpl, array( + '$photos' => $photos, + '$album' => $album, + '$album_edit' => array(t('Edit Album'), $album_edit), + '$can_post' => $can_post, + '$upload' => array(t('Upload'), $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/upload/' . bin2hex($album)), + '$order' => $order, + '$upload_form' => $upload_form, + '$usage' => $usage_message + )); } - $o .= '<div id="photo-album-end"></div>'; - $o .= paginate($a); + + if((! $photos) && ($_REQUEST['aj'])) { + $o .= '<div id="content-complete"></div>'; + echo $o; + killme(); + } + +// $o .= paginate($a); return $o; @@ -752,25 +761,18 @@ function photos_content(&$a) { // fetch image, item containing image, then comments $ph = q("SELECT aid,uid,xchan,resource_id,created,edited,title,`description`,album,filename,`type`,height,width,`size`,scale,profile,photo_flags,allow_cid,allow_gid,deny_cid,deny_gid FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s' - and (photo_flags = %d or photo_flags = %d ) $sql_extra ORDER BY `scale` ASC ", + $sql_extra ORDER BY `scale` ASC ", intval($owner_uid), - dbesc($datum), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) - + dbesc($datum) ); if(! $ph) { /* Check again - this time without specifying permissions */ - $ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' - and ( photo_flags = %d or photo_flags = %d ) - LIMIT 1", + $ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' LIMIT 1", intval($owner_uid), - dbesc($datum), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) + dbesc($datum) ); if($ph) notice( t('Permission denied. Access to this item may be restricted.') . EOL); @@ -791,11 +793,9 @@ function photos_content(&$a) { $prvnxt = q("SELECT `resource_id` FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `scale` = 0 - and ( photo_flags = %d or photo_flags = %d ) $sql_extra ORDER BY `created` $order ", + $sql_extra ORDER BY `created` $order ", dbesc($ph[0]['album']), - intval($owner_uid), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) + intval($owner_uid) ); if(count($prvnxt)) { @@ -837,16 +837,14 @@ function photos_content(&$a) { $tools = array( 'profile'=>array($a->get_baseurl() . '/profile_photo/use/'.$ph[0]['resource_id'], t('Use as profile photo')), ); - - // lock - $lock = ( ( ($ph[0]['uid'] == local_user()) && (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid']) - || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) ) - ? t('Private Message') - : Null); - - } + // lockstate + $lockstate = ( ( (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid']) + || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) ) + ? array('lock', t('Private Photo')) + : array('unlock', Null)); + $a->page['htmlhead'] .= '<script>$(document).keydown(function(event) {' . "\n"; if($prevlink) $a->page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 37) { event.preventDefault(); window.location.href = \'' . $prevlink . '\'; }' . "\n"; @@ -855,7 +853,7 @@ function photos_content(&$a) { $a->page['htmlhead'] .= '});</script>'; if($prevlink) - $prevlink = array($prevlink, '<i class="icon-backward photo-icons""></i>') ; + $prevlink = array($prevlink, t('Previous')); $photo = array( 'href' => $a->get_baseurl() . '/photo/' . $hires['resource_id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']], @@ -864,7 +862,7 @@ function photos_content(&$a) { ); if($nextlink) - $nextlink = array($nextlink, '<i class="icon-forward photo-icons"></i>'); + $nextlink = array($nextlink, t('Next')); // Do we have an item for this photo? @@ -894,23 +892,21 @@ function photos_content(&$a) { $r = conv_sort($r,'commented'); } - - $tags = array(); if($link_item['term']) { $cnt = 0; - foreach($link_item['term'] as $t) + foreach($link_item['term'] as $t) { $tags[$cnt] = array(0 => format_term_for_display($t)); if($can_post && ($ph[0]['uid'] == $owner_uid)) { - $tags[$cnt][1] = 'tagrm?f=&item=' . $link_item['id']; + $tags[$cnt][1] = 'tagrm/drop/' . $link_item['id'] . '/' . bin2hex($t['term']); //?f=&item=' . $link_item['id']; $tags[$cnt][2] = t('Remove'); } $cnt ++; + } } - if((local_user()) && (local_user() == $link_item['uid'])) { - q("UPDATE `item` SET item_flags = (item_flags ^ %d) WHERE parent = %d and uid = %d and (item_flags & %d)", + q("UPDATE `item` SET item_flags = (item_flags & ~%d) WHERE parent = %d and uid = %d and (item_flags & %d)>0", intval(ITEM_UNSEEN), intval($link_item['parent']), intval(local_user()), @@ -927,23 +923,22 @@ function photos_content(&$a) { $edit = null; if($can_post) { - if(array_key_exists('albums', $a->data)) - $albums = get_app()->data['albums']; - else - $albums = photos_albums_list($a->data['channel'],$a->data['observer']); - $album_e = $ph[0]['album']; $caption_e = $ph[0]['description']; $aclselect_e = populate_acl($ph[0]); + $albums = ((array_key_exists('albums', $a->data)) ? $a->data['albums'] : photos_albums_list($a->data['channel'],$a->data['observer'])); + + $_SESSION['album_return'] = bin2hex($ph[0]['album']); $edit = array( 'edit' => t('Edit photo'), - 'id' => $ph[0]['id'], + 'id' => $link_item['id'], 'rotatecw' => t('Rotate CW (right)'), 'rotateccw' => t('Rotate CCW (left)'), 'albums' => $albums['albums'], 'album' => $album_e, - 'newalbum' => t('New album name'), + 'newalbum_label' => t('Enter a new album name'), + 'newalbum_placeholder' => t('or select an existing one (doubleclick)'), 'nickname' => $a->data['channel']['channel_address'], 'resource_id' => $ph[0]['resource_id'], 'capt_label' => t('Caption'), @@ -951,8 +946,11 @@ function photos_content(&$a) { 'tag_label' => t('Add a Tag'), 'permissions' => t('Permissions'), 'aclselect' => $aclselect_e, - 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping'), + 'lockstate' => $lockstate[0], + 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'), 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0), + 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'), + 'adult' => array('adult',t('Flag as adult in album view'), (($ph[0]['photo_flags'] & PHOTO_ADULT) ? 1 : 0),''), 'submit' => t('Submit'), 'delete' => t('Delete Photo') ); @@ -981,7 +979,7 @@ function photos_content(&$a) { $comments = ''; if(! count($r)) { if($can_post || $can_comment) { - $comments .= replace_macros($cmnt_tpl,array( + $commentbox = replace_macros($cmnt_tpl,array( '$return_path' => '', '$mode' => 'photos', '$jsreload' => $return_url, @@ -1007,7 +1005,7 @@ function photos_content(&$a) { $like = ''; $dislike = ''; - // display comments + if($r) { foreach($r as $item) { @@ -1015,10 +1013,33 @@ function photos_content(&$a) { like_puller($a,$item,$dlike,'dislike'); } - $like = ((isset($alike[$link_item['id']])) ? format_like($alike[$link_item['id']],$alike[$link_item['id'] . '-l'],'like',$link_item['id']) : ''); - $dislike = ((isset($dlike[$link_item['id']])) ? format_like($dlike[$link_item['id']],$dlike[$link_item['id'] . '-l'],'dislike',$link_item['id']) : ''); + $like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : ''); + $like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : ''); + if (count($like_list) > MAX_LIKERS) { + $like_list_part = array_slice($like_list, 0, MAX_LIKERS); + array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); + } else { + $like_list_part = ''; + } + $like_button_label = tt('Like','Likes',$like_count,'noun'); + + //if (feature_enabled($conv->get_profile_owner(),'dislike')) { + $dislike_count = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid']] : ''); + $dislike_list = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid'] . '-l'] : ''); + $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun'); + if (count($dislike_list) > MAX_LIKERS) { + $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS); + array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); + } else { + $dislike_list_part = ''; + } + //} + + $like = ((isset($alike[$link_item['mid']])) ? format_like($alike[$link_item['mid']],$alike[$link_item['mid'] . '-l'],'like',$link_item['mid']) : ''); + $dislike = ((isset($dlike[$link_item['mid']])) ? format_like($dlike[$link_item['mid']],$dlike[$link_item['mid'] . '-l'],'dislike',$link_item['mid']) : ''); + // display comments foreach($r as $item) { $comment = ''; @@ -1052,7 +1073,7 @@ function photos_content(&$a) { $body_e = prepare_text($item['body'],$item['mimetype']); $comments .= replace_macros($template,array( - '$id' => $item['item_id'], + '$id' => $item['id'], '$mode' => 'photos', '$profile_url' => $profile_link, '$name' => $name_e, @@ -1061,7 +1082,7 @@ function photos_content(&$a) { '$title' => $title_e, '$body' => $body_e, '$ago' => relative_date($item['created']), - '$indent' => (($item['parent'] != $item['item_id']) ? ' comment' : ''), + '$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''), '$drop' => $drop, '$comment' => $comment )); @@ -1069,7 +1090,7 @@ function photos_content(&$a) { } if($can_post || $can_comment) { - $comments .= replace_macros($cmnt_tpl,array( + $commentbox = replace_macros($cmnt_tpl,array( '$return_path' => '', '$jsreload' => $return_url, '$type' => 'wall-comment', @@ -1096,21 +1117,35 @@ function photos_content(&$a) { $photo_tpl = get_markup_template('photo_view.tpl'); $o .= replace_macros($photo_tpl, array( - '$id' => $ph[0]['id'], + '$id' => $link_item['id'], //$ph[0]['id'], '$album' => $album_e, '$tools' => $tools, - '$lock' => $lock, + '$lock' => $lockstate[1], '$photo' => $photo, '$prevlink' => $prevlink, '$nextlink' => $nextlink, '$desc' => $ph[0]['description'], + '$filename' => $ph[0]['filename'], + '$unknown' => t('Unknown'), '$tag_hdr' => t('In This Photo:'), '$tags' => $tags, '$edit' => $edit, '$likebuttons' => $likebuttons, '$like' => $like_e, '$dislike' => $dislike_e, + '$like_count' => $like_count, + '$like_list' => $like_list, + '$like_list_part' => $like_list_part, + '$like_button_label' => $like_button_label, + '$like_modal_title' => t('Likes','noun'), + '$dislike_modal_title' => t('Dislikes','noun'), + '$dislike_count' => $dislike_count, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''), + '$dislike_list' => $dislike_list, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''), + '$dislike_list_part' => $dislike_list_part, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''), + '$dislike_button_label' => $dislike_button_label, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''), + '$modal_dismiss' => t('Close'), '$comments' => $comments, + '$commentbox' => $commentbox, '$paginate' => $paginate, )); @@ -1123,29 +1158,30 @@ function photos_content(&$a) { //$o = ''; $r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' - and ( photo_flags = %d or photo_flags = %d ) $sql_extra GROUP BY `resource_id`", + and ((photo_flags = %d) or (photo_flags & %d) > 0) $sql_extra GROUP BY `resource_id`", intval($a->data['channel']['channel_id']), dbesc('Contact Photos'), dbesc( t('Contact Photos')), intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) + intval(($unsafe) ? (PHOTO_PROFILE|PHOTO_ADULT) : PHOTO_PROFILE) ); if(count($r)) { $a->set_pager_total(count($r)); - $a->set_pager_itemspage(20); + $a->set_pager_itemspage(60); } - - $r = q("SELECT `resource_id`, `id`, `filename`, type, `album`, max(`scale`) AS `scale` FROM `photo` - WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' - and ( photo_flags = %d or photo_flags = %d ) - $sql_extra GROUP BY `resource_id` ORDER BY `created` DESC LIMIT %d , %d", + + $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.album, p.scale, p.created FROM photo p INNER JOIN + (SELECT resource_id, max(scale) scale FROM photo + WHERE uid=%d AND album != '%s' AND album != '%s' + AND (photo_flags = %d or ( photo_flags & %d ) > 0 ) $sql_extra group by resource_id) ph + ON (p.resource_id = ph.resource_id and p.scale = ph.scale) ORDER by p.created DESC LIMIT %d OFFSET %d", intval($a->data['channel']['channel_id']), dbesc('Contact Photos'), dbesc( t('Contact Photos')), intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE), - intval($a->pager['start']), - intval($a->pager['itemspage']) + intval(($unsafe) ? (PHOTO_PROFILE|PHOTO_ADULT) : PHOTO_PROFILE), + intval($a->pager['itemspage']), + intval($a->pager['start']) ); @@ -1186,16 +1222,39 @@ function photos_content(&$a) { } } - $tpl = get_markup_template('photos_recent.tpl'); - $o .= replace_macros($tpl, array( - '$title' => t('Recent Photos'), - '$can_post' => $can_post, - '$upload' => array(t('Upload New Photos'), $a->get_baseurl().'/photos/'.$a->data['channel']['channel_address'].'/upload'), - '$photos' => $photos, - )); + if($_REQUEST['aj']) { + if($photos) { + $o = replace_macros(get_markup_template('photosajax.tpl'),array( + '$photos' => $photos, + )); + } + else { + $o = '<div id="content-complete"></div>'; + } + echo $o; + killme(); + } + else { + $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>"; + $tpl = get_markup_template('photos_recent.tpl'); + $o .= replace_macros($tpl, array( + '$title' => t('Recent Photos'), + '$can_post' => $can_post, + '$upload' => array(t('Upload'), $a->get_baseurl().'/photos/'.$a->data['channel']['channel_address'].'/upload'), + '$photos' => $photos, + '$upload_form' => $upload_form, + '$usage' => $usage_message + )); - - $o .= paginate($a); + } + + if((! $photos) && ($_REQUEST['aj'])) { + $o .= '<div id="content-complete"></div>'; + echo $o; + killme(); + } + +// paginate($a); return $o; } diff --git a/mod/ping.php b/mod/ping.php index 49475de66..593ae21f8 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -41,6 +41,20 @@ function ping_init(&$a) { header("content-type: application/json"); + $vnotify = false; + + if(local_user()) { + $vnotify = get_pconfig(local_user(),'system','vnotify'); + $evdays = intval(get_pconfig(local_user(),'system','evdays')); + $ob_hash = get_observer_hash(); + } + + // if unset show all visual notification types + if($vnotify === false) + $vnotify = (-1); + if($evdays < 1) + $evdays = 3; + /** * If you have several windows open to this site and switch to a different channel * in one of them, the others may get into a confused state showing you a page or options @@ -71,6 +85,11 @@ function ping_init(&$a) { } unset($_SESSION['sysmsg_info']); } + if(! ($vnotify & VNOTIFY_INFO)) + $result['info'] = array(); + if(! ($vnotify & VNOTIFY_ALERT)) + $result['notice'] = array(); + if($a->install) { echo json_encode($result); @@ -89,7 +108,7 @@ function ping_init(&$a) { $basic_presence = false; if($r) { $basic_presence = true; - q("update chatpresence set cp_last = '%s' where cp_id = %d limit 1", + q("update chatpresence set cp_last = '%s' where cp_id = %d", dbesc(datetime_convert()), intval($r[0]['cp_id']) ); @@ -110,7 +129,9 @@ function ping_init(&$a) { * and shouldn't count as online anymore. We allow an expection for bots. */ - q("delete from chatpresence where cp_last < UTC_TIMESTAMP() - INTERVAL 3 MINUTE and cp_client != 'auto' "); + q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ", + db_utcnow(), db_quoteinterval('3 MINUTE') + ); if((! local_user()) || ($result['invalid'])) { echo json_encode($result); @@ -130,14 +151,14 @@ function ping_init(&$a) { if(x($_REQUEST, 'markRead') && local_user()) { switch($_REQUEST['markRead']) { case 'network': - $r = q("update item set item_flags = ( item_flags ^ %d ) where (item_flags & %d) and uid = %d", + $r = q("update item set item_flags = ( item_flags & ~%d ) where (item_flags & %d) > 0 and uid = %d", intval(ITEM_UNSEEN), intval(ITEM_UNSEEN), intval(local_user()) ); break; case 'home': - $r = q("update item set item_flags = ( item_flags ^ %d ) where (item_flags & %d) and (item_flags & %d) and uid = %d", + $r = q("update item set item_flags = ( item_flags & ~%d ) where (item_flags & %d) > 0 and (item_flags & %d) > 0 and uid = %d", intval(ITEM_UNSEEN), intval(ITEM_UNSEEN), intval(ITEM_WALL), @@ -145,7 +166,7 @@ function ping_init(&$a) { ); break; case 'messages': - $r = q("update mail set mail_flags = ( mail_flags ^ %d ) where channel_id = %d and not (mail_flags & %d)", + $r = q("update mail set mail_flags = ( mail_flags | %d ) where channel_id = %d and not (mail_flags & %d) > 0", intval(MAIL_SEEN), intval(local_user()), intval(MAIL_SEEN) @@ -166,6 +187,14 @@ function ping_init(&$a) { } } + if(x($_REQUEST, 'markItemRead') && local_user()) { + $r = q("update item set item_flags = ( item_flags & ~%d ) where parent = %d and uid = %d", + intval(ITEM_UNSEEN), + intval($_REQUEST['markItemRead']), + intval(local_user()) + ); + } + /** @@ -179,17 +208,17 @@ function ping_init(&$a) { ); if($t && intval($t[0]['total']) > 49) { $z = q("select * from notify where uid = %d - and seen = 0 order by date desc limit 0, 50", + and seen = 0 order by date desc limit 50", intval(local_user()) ); } else { $z1 = q("select * from notify where uid = %d - and seen = 0 order by date desc limit 0, 50", + and seen = 0 order by date desc limit 50", intval(local_user()) ); $z2 = q("select * from notify where uid = %d - and seen = 1 order by date desc limit 0, %d", + and seen = 1 order by date desc limit %d", intval(local_user()), intval(50 - intval($t[0]['total'])) ); @@ -204,7 +233,7 @@ function ping_init(&$a) { 'url' => $zz['url'], 'photo' => $zz['photo'], 'when' => relative_date($zz['date']), - 'class' => (($zz['seen']) ? 'notify-seen' : 'notify-unseen'), + 'hclass' => (($zz['seen']) ? 'notify-seen' : 'notify-unseen'), 'message' => strip_tags(bbcode($zz['msg'])) ); } @@ -217,8 +246,8 @@ function ping_init(&$a) { if(argc() > 1 && argv(1) === 'messages') { $channel = $a->get_channel(); $t = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan - where channel_id = %d and not ( mail_flags & %d ) and not (mail_flags & %d ) - and from_xchan != '%s' order by created desc limit 0,50", + where channel_id = %d and not ( mail_flags & %d ) > 0 and not (mail_flags & %d ) > 0 + and from_xchan != '%s' order by created desc limit 50", intval(local_user()), intval(MAIL_SEEN), intval(MAIL_DELETED), @@ -233,7 +262,7 @@ function ping_init(&$a) { 'url' => $zz['xchan_url'], 'photo' => $zz['xchan_photo_s'], 'when' => relative_date($zz['created']), - 'class' => (($zz['mail_flags'] & MAIL_SEEN) ? 'notify-seen' : 'notify-unseen'), + 'hclass' => (($zz['mail_flags'] & MAIL_SEEN) ? 'notify-seen' : 'notify-unseen'), 'message' => t('sent you a private message'), ); } @@ -247,10 +276,12 @@ function ping_init(&$a) { $result = array(); $r = q("SELECT * FROM item - WHERE item_restrict = %d and ( item_flags & %d ) and uid = %d", + WHERE item_restrict = %d and ( item_flags & %d ) > 0 and uid = %d + and author_xchan != '%s' ORDER BY created DESC", intval(ITEM_VISIBLE), intval(ITEM_UNSEEN), - intval(local_user()) + intval(local_user()), + dbesc($ob_hash) ); if($r) { @@ -269,7 +300,7 @@ function ping_init(&$a) { if(argc() > 1 && (argv(1) === 'intros')) { $result = array(); - $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) and not ((abook_flags & %d) or (xchan_flags & %d))", + $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) > 0 and not ((abook_flags & %d) > 0 or (xchan_flags & %d) > 0) ORDER BY abook_created DESC", intval(local_user()), intval(ABOOK_FLAG_PENDING), intval(ABOOK_FLAG_SELF|ABOOK_FLAG_IGNORED), @@ -284,7 +315,7 @@ function ping_init(&$a) { 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => relative_date($rr['abook_created']), - 'class' => ('notify-unseen'), + 'hclass' => ('notify-unseen'), 'message' => t('added your channel') ); } @@ -303,7 +334,7 @@ function ping_init(&$a) { WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0 ORDER BY `start` DESC ", intval(local_user()), - dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) ); @@ -325,7 +356,7 @@ function ping_init(&$a) { 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => $when, - 'class' => ('notify-unseen'), + 'hclass' => ('notify-unseen'), 'message' => t('posted an event') ); } @@ -341,101 +372,127 @@ function ping_init(&$a) { * Normal ping - just the counts, no detail */ - $t = q("select count(*) as total from notify where uid = %d and seen = 0", - intval(local_user()) - ); - if($t) - $result['notify'] = intval($t[0]['total']); + if($vnotify & VNOTIFY_SYSTEM) { + $t = q("select count(*) as total from notify where uid = %d and seen = 0", + intval(local_user()) + ); + if($t) + $result['notify'] = intval($t[0]['total']); + } $t1 = dba_timer(); - $r = q("SELECT id, item_restrict, item_flags FROM item - WHERE (item_restrict = %d) and ( item_flags & %d ) and uid = %d", - intval(ITEM_VISIBLE), - intval(ITEM_UNSEEN), - intval(local_user()) - ); + if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) { + $r = q("SELECT id, item_restrict, item_flags FROM item + WHERE (item_restrict = %d) and ( item_flags & %d ) > 0 and uid = %d + and author_xchan != '%s'", + intval(ITEM_VISIBLE), + intval(ITEM_UNSEEN), + intval(local_user()), + dbesc($ob_hash) + ); - if(count($r)) { - $arr = array('items' => $r); - call_hooks('network_ping', $arr); + if($r) { + $arr = array('items' => $r); + call_hooks('network_ping', $arr); - foreach ($r as $it) { - if($it['item_flags'] & ITEM_WALL) - $result['home'] ++; - else - $result['network'] ++; + foreach ($r as $it) { + if($it['item_flags'] & ITEM_WALL) + $result['home'] ++; + else + $result['network'] ++; + } } } + if(! ($vnotify & VNOTIFY_NETWORK)) + $result['network'] = 0; + if(! ($vnotify & VNOTIFY_CHANNEL)) + $result['home'] = 0; + $t2 = dba_timer(); - $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) and not ((abook_flags & %d) or (xchan_flags & %d))", - intval(local_user()), - intval(ABOOK_FLAG_PENDING), - intval(ABOOK_FLAG_SELF|ABOOK_FLAG_IGNORED), - intval(XCHAN_FLAGS_DELETED|XCHAN_FLAGS_ORPHAN) - ); + if($vnotify & VNOTIFY_INTRO) { + $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) > 0 and not ((abook_flags & %d) > 0 or (xchan_flags & %d) > 0)", + intval(local_user()), + intval(ABOOK_FLAG_PENDING), + intval(ABOOK_FLAG_SELF|ABOOK_FLAG_IGNORED), + intval(XCHAN_FLAGS_DELETED|XCHAN_FLAGS_ORPHAN) + ); - $t3 = dba_timer(); + $t3 = dba_timer(); - if($intr) - $result['intros'] = intval($intr[0]['total']); + if($intr) + $result['intros'] = intval($intr[0]['total']); + } $t4 = dba_timer(); $channel = get_app()->get_channel(); - $mails = q("SELECT count(id) as total from mail - WHERE channel_id = %d AND not (mail_flags & %d) and from_xchan != '%s' ", - intval(local_user()), - intval(MAIL_SEEN), - dbesc($channel['channel_hash']) - ); - if($mails) - $result['mail'] = intval($mails[0]['total']); - - if ($a->config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) { - $regs = q("SELECT count(account_id) as total from account where (account_flags & %d)", - intval(ACCOUNT_PENDING) + if($vnotify & VNOTIFY_MAIL) { + $mails = q("SELECT count(id) as total from mail + WHERE channel_id = %d AND not (mail_flags & %d) > 0 and from_xchan != '%s' ", + intval(local_user()), + intval(MAIL_SEEN), + dbesc($channel['channel_hash']) ); - if($regs) - $result['register'] = intval($regs[0]['total']); + if($mails) + $result['mail'] = intval($mails[0]['total']); + } + + if($vnotify & VNOTIFY_REGISTER) { + if ($a->config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) { + $regs = q("SELECT count(account_id) as total from account where (account_flags & %d) > 0", + intval(ACCOUNT_PENDING) + ); + if($regs) + $result['register'] = intval($regs[0]['total']); + } } $t5 = dba_timer(); - $events = q("SELECT type, start, adjust FROM `event` - WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0 - ORDER BY `start` ASC ", - intval(local_user()), - dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')), - dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) - ); - - if($events) { - $result['all_events'] = count($events); - - if($result['all_events']) { - $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); - foreach($events as $x) { - $bd = false; - if($x['type'] === 'birthday') { - $result['birthdays'] ++; - $bd = true; - } - else { - $result['events'] ++; - } - if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['start'], 'Y-m-d') === $str_now) { - $result['all_events_today'] ++; - if($bd) - $result['birthdays_today'] ++; - else - $result['events_today'] ++; + if($vnotify & (VNOTIFY_EVENT|VNOTIFY_EVENTTODAY|VNOTIFY_BIRTHDAY)) { + $events = q("SELECT type, start, adjust FROM `event` + WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0 + ORDER BY `start` ASC ", + intval(local_user()), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) + ); + + if($events) { + $result['all_events'] = count($events); + + if($result['all_events']) { + $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); + foreach($events as $x) { + $bd = false; + if($x['type'] === 'birthday') { + $result['birthdays'] ++; + $bd = true; + } + else { + $result['events'] ++; + } + if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['start'], 'Y-m-d') === $str_now) { + $result['all_events_today'] ++; + if($bd) + $result['birthdays_today'] ++; + else + $result['events_today'] ++; + } } } } } + if(! ($vnotify & VNOTIFY_EVENT)) + $result['all_events'] = $result['events'] = 0; + if(! ($vnotify & VNOTIFY_EVENTTODAY)) + $result['all_events_today'] = $result['events_today'] = 0; + if(! ($vnotify & VNOTIFY_BIRTHDAY)) + $result['birthdays'] = 0; + $x = json_encode($result); diff --git a/mod/poco.php b/mod/poco.php index 9295f13de..3f932e92f 100644 --- a/mod/poco.php +++ b/mod/poco.php @@ -15,7 +15,7 @@ function poco_init(&$a) { $user = notags(trim(argv(1))); } if(! x($user)) { - $c = q("select * from pconfig where cat = 'system' and k = 'suggestme' and v = 1"); + $c = q("select * from pconfig where cat = 'system' and k = 'suggestme' and v = '1'"); if(! $c) { logger('mod_poco: system mode. No candidates.', LOGGER_DEBUG); http_status_exit(404); @@ -60,7 +60,7 @@ function poco_init(&$a) { } if($justme) - $sql_extra = " and ( abook_flags & " . ABOOK_FLAG_SELF . " ) "; + $sql_extra = " and ( abook_flags & " . ABOOK_FLAG_SELF . " )>0 "; else $sql_extra = " and abook_flags = 0 "; @@ -69,14 +69,14 @@ function poco_init(&$a) { if($system_mode) { $r = q("SELECT count(*) as `total` from abook where ( abook_flags & " . ABOOK_FLAG_SELF . - " ) and abook_channel in (select uid from pconfig where cat = 'system' and k = 'suggestme' and v = 1) "); + " )>0 and abook_channel in (select uid from pconfig where cat = 'system' and k = 'suggestme' and v = '1') "); } else { $r = q("SELECT count(*) as `total` from abook where abook_channel = %d $sql_extra ", intval($channel_id) ); - $c = q("select * from menu_item where ( mitem_flags & " . intval(MENU_ITEM_CHATROOM) . " ) and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' and mitem_channel_id = %d", + $c = q("select * from menu_item where ( mitem_flags & " . intval(MENU_ITEM_CHATROOM) . " )>0 and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' and mitem_channel_id = %d", intval($channel_id) ); } @@ -93,17 +93,17 @@ function poco_init(&$a) { if($system_mode) { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where ( abook_flags & " . ABOOK_FLAG_SELF . - " ) and abook_channel in (select uid from pconfig where cat = 'system' and k = 'suggestme' and v = 1) limit %d, %d ", - intval($startIndex), - intval($itemsPerPage) + " )>0 and abook_channel in (select uid from pconfig where cat = 'system' and k = 'suggestme' and v = '1') limit %d offset %d ", + intval($itemsPerPage), + intval($startIndex) ); } else { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d - $sql_extra LIMIT %d, %d", + $sql_extra LIMIT %d OFFSET %d", intval($channel_id), - intval($startIndex), - intval($itemsPerPage) + intval($itemsPerPage), + intval($startIndex) ); } @@ -167,8 +167,11 @@ function poco_init(&$a) { $entry['displayName'] = $rr['xchan_name']; if($fields_ret['urls']) { $entry['urls'] = array(array('value' => $rr['xchan_url'], 'type' => 'profile')); + $network = $rr['xchan_network']; + if(strpos($network,'friendica') !== false) + $network = 'friendica'; if($rr['xchan_addr']) - $entry['urls'][] = array('value' => 'acct:' . $rr['xchan_addr'], 'type' => 'zot'); + $entry['urls'][] = array('value' => 'acct:' . $rr['xchan_addr'], 'type' => $network); } if($fields_ret['preferredUsername']) $entry['preferredUsername'] = substr($rr['xchan_addr'],0,strpos($rr['xchan_addr'],'@')); diff --git a/mod/post.php b/mod/post.php index 3b4f66baf..9e818a7e2 100644 --- a/mod/post.php +++ b/mod/post.php @@ -98,7 +98,7 @@ function post_init(&$a) { // Any channel will do, providing it's currently active. We just need to have an // identity to attach to the packet we send back. So find one. - $c = q("select * from channel where not ( channel_pageflags & %d ) limit 1", + $c = q("select * from channel where not ( channel_pageflags & %d )>0 limit 1", intval(PAGE_REMOVED) ); @@ -415,8 +415,8 @@ function post_init(&$a) { * } *} * - * Currently defined message types are 'activity', 'mail', 'profile' and 'channel_sync', which each have - * different content schemas. + * Currently defined message types are 'activity', 'mail', 'profile', 'location' and 'channel_sync', + * which each have different content schemas. * * Ping packet: * A ping packet does not require any parameters except the type. It may or may not be encrypted. @@ -507,6 +507,7 @@ function post_post(&$a) { json_return_and_die($ret); } + if($msgtype === 'pickup') { /** @@ -597,11 +598,24 @@ function post_post(&$a) { $ret['success'] = true; $ret['pickup'] = array(); foreach($r as $rr) { - $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => json_decode($rr['outq_msg'],true)); + if($rr['outq_msg']) { + $x = json_decode($rr['outq_msg'],true); - $x = q("delete from outq where outq_hash = '%s' limit 1", - dbesc($rr['outq_hash']) - ); + if(! $x) + continue; + + if(array_key_exists('message_list',$x)) { + foreach($x['message_list'] as $xx) { + $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => $xx); + } + } + else + $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => $x); + + $x = q("delete from outq where outq_hash = '%s'", + dbesc($rr['outq_hash']) + ); + } } } @@ -645,7 +659,7 @@ function post_post(&$a) { // Update our DB to show when we last communicated successfully with this hub // This will allow us to prune dead hubs from using up resources - $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d limit 1", + $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($hub['hubloc_id']) ); @@ -653,17 +667,17 @@ function post_post(&$a) { // a dead hub came back to life - reset any tombstones we might have if($hub['hubloc_status'] & HUBLOC_OFFLINE) { - q("update hubloc set hubloc_status = (hubloc_status ^ %d) where hubloc_id = %d limit 1", + q("update hubloc set hubloc_status = (hubloc_status & ~%d) where hubloc_id = %d", intval(HUBLOC_OFFLINE), intval($hub['hubloc_id']) ); if($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) { - q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_id = %d limit 1", + q("update hubloc set hubloc_flags = (hubloc_flags & ~%d) where hubloc_id = %d", intval(HUBLOC_FLAGS_ORPHANCHECK), intval($hub['hubloc_id']) ); } - q("update xchan set xchan_flags = (xchan_flags ^ %d) where (xchan_flags & %d) and xchan_hash = '%s' limit 1", + q("update xchan set xchan_flags = (xchan_flags & ~%d) where (xchan_flags & %d)>0 and xchan_hash = '%s'", intval(XCHAN_FLAGS_ORPHAN), intval(XCHAN_FLAGS_ORPHAN), dbesc($hub['hubloc_hash']) @@ -718,7 +732,9 @@ function post_post(&$a) { $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); // garbage collect any old unused notifications - q("delete from verify where type = 'auth' and created < UTC_TIMESTAMP() - INTERVAL 10 MINUTE"); + q("delete from verify where type = 'auth' and created < %s - INTERVAL %s", + db_utcnow(), db_quoteinterval('10 MINUTE') + ); $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", dbesc($sender_hash) @@ -767,7 +783,7 @@ function post_post(&$a) { $ret['message'] .= 'verification key not found' . EOL; json_return_and_die($ret); } - $r = q("delete from verify where id = %d limit 1", + $r = q("delete from verify where id = %d", intval($z[0]['id']) ); @@ -782,6 +798,7 @@ function post_post(&$a) { $ret['service_class'] = $u[0]['account_service_class']; // Set "do not track" flag if this site or this channel's profile is restricted + // in some way if(intval(get_config('system','block_public'))) $ret['DNT'] = true; @@ -789,6 +806,8 @@ function post_post(&$a) { $ret['DNT'] = true; if(get_pconfig($c[0]['channel_id'],'system','do_not_track')) $ret['DNT'] = true; + if(get_pconfig($c[0]['channel_id'],'system','hide_online_status')) + $ret['DNT'] = true; json_return_and_die($ret); @@ -796,6 +815,12 @@ function post_post(&$a) { json_return_and_die($ret); } + if($msgtype === 'request') { + // request a particular post/conversation by message_id + $x = zot_process_message_request($data); + json_return_and_die($x); + } + if($msgtype === 'purge') { if($recipients) { diff --git a/mod/profile_photo.php b/mod/profile_photo.php index c587b9606..e9dad6f51 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -33,7 +33,7 @@ function profile_photo_set_profile_perms($profileid = '') { if (intval($profile['is_default']) != 1) { $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", intval(local_user()) ); - $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = %d ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids. + $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids. $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", dbesc($profile['profile_guid'])); $allowcid = "<" . $r0[0]['channel_hash'] . ">"; foreach ($r1 as $entry) { @@ -173,7 +173,7 @@ function profile_photo_post(&$a) { dbesc($base_image['resource_id']), intval(local_user()) ); - $r = q("UPDATE photo SET photo_flags = ( photo_flags ^ %d ) WHERE ( photo_flags & %d ) + $r = q("UPDATE photo SET photo_flags = ( photo_flags & ~%d ) WHERE ( photo_flags & %d )>0 AND resource_id != '%s' AND `uid` = %d", intval(PHOTO_PROFILE), intval(PHOTO_PROFILE), @@ -182,7 +182,7 @@ function profile_photo_post(&$a) { ); } else { - $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d limit 1", + $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", dbesc($a->get_baseurl() . '/photo/' . $base_image['resource_id'] . '-4'), dbesc($a->get_baseurl() . '/photo/' . $base_image['resource_id'] . '-5'), intval($_REQUEST['profile']), @@ -196,7 +196,7 @@ function profile_photo_post(&$a) { $channel = $a->get_channel(); $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s' - where xchan_hash = '%s' limit 1", + where xchan_hash = '%s'", dbesc($im->getType()), dbesc(datetime_convert()), dbesc($channel['xchan_hash']) @@ -302,7 +302,7 @@ function profile_photo_content(&$a) { // unset any existing profile photos $r = q("UPDATE photo SET profile = 0 WHERE profile = 1 AND uid = %d", intval(local_user())); - $r = q("UPDATE photo SET photo_flags = (photo_flags ^ %d ) WHERE (photo_flags & %d ) AND uid = %d", + $r = q("UPDATE photo SET photo_flags = (photo_flags & ~%d ) WHERE (photo_flags & %d )>0 AND uid = %d", intval(PHOTO_PROFILE), intval(PHOTO_PROFILE), intval(local_user())); @@ -320,7 +320,7 @@ function profile_photo_content(&$a) { ); $r = q("UPDATE xchan set xchan_photo_date = '%s' - where xchan_hash = '%s' limit 1", + where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($channel['xchan_hash']) ); @@ -364,7 +364,9 @@ function profile_photo_content(&$a) { // FIXME - yuk '$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . $a->get_baseurl() . '">' . t('skip this step') . '</a>' : '<a href="'. $a->get_baseurl() . '/photos/' . $a->channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>') )); - + + call_hooks('profile_photo_content_end', $o); + return $o; } else { diff --git a/mod/profiles.php b/mod/profiles.php index f6392d4ab..fa6a6e35c 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -11,7 +11,7 @@ function profiles_init(&$a) { if((argc() > 2) && (argv(1) === "drop") && intval(argv(2))) { $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is_default` = 0 LIMIT 1", - intval($a->argv[2]), + intval(argv(2)), intval(local_user()) ); if(! count($r)) { @@ -30,7 +30,7 @@ function profiles_init(&$a) { dbesc($profile_guid), intval(local_user()) ); - $r = q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", + $r = q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d", intval(argv(2)), intval(local_user()) ); @@ -126,12 +126,48 @@ function profiles_init(&$a) { return; // NOTREACHED } + if((argc() > 2) && (argv(1) === 'export')) { + + $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1", + intval(local_user()), + intval(argv(2)) + ); + if(! $r1) { + notice( t('Profile unavailable to export.') . EOL); + $a->error = 404; + return; + } + header('content-type: application/octet_stream'); + header('content-disposition: attachment; filename="' . $r1[0]['profile_name'] . '.json"' ); + + unset($r1[0]['id']); + unset($r1[0]['aid']); + unset($r1[0]['uid']); + unset($r1[0]['is_default']); + unset($r1[0]['publish']); + unset($r1[0]['profile_name']); + unset($r1[0]['profile_guid']); + echo json_encode($r1[0]); + killme(); + } + + + // Run profile_load() here to make sure the theme is set before // we start loading content - if((argc() > 1) && (intval(argv(1)))) { + if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_user(),'multi_profiles')) { + if(feature_enabled(local_user(),'multi_profiles')) + $id = $a->argv[1]; + else { + $x = q("select id from profile where uid = %d and is_default = 1", + intval(local_user()) + ); + if($x) + $id = $x[0]['id']; + } $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", - intval($a->argv[1]), + intval($id), intval(local_user()) ); if(! count($r)) { @@ -159,6 +195,33 @@ function profiles_post(&$a) { call_hooks('profile_post', $_POST); + // import from json export file. + // Only import fields that are allowed on this hub + + if(x($_FILES,'userfile')) { + $src = $_FILES['userfile']['tmp_name']; + $filesize = intval($_FILES['userfile']['size']); + if($filesize) { + $j = @json_decode(@file_get_contents($src),true); + @unlink($src); + if($j) { + $fields = get_profile_fields_advanced(); + if($fields) { + foreach($j as $jj => $v) { + foreach($fields as $f => $n) { + if($jj == $f) { + $_POST[$f] = $v; + break; + } + } + } + } + } + } + } + + + if((argc() > 1) && (argv(1) !== "new") && intval(argv(1))) { $orig = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[1]), @@ -178,32 +241,30 @@ function profiles_post(&$a) { notify( t('Profile Name is required.') . EOL); return; } - - $year = intval($_POST['year']); - if($year < 1900 || $year > 2100 || $year < 0) - $year = 0; - $month = intval($_POST['month']); - if(($month > 12) || ($month < 0)) - $month = 0; - $mtab = array(0,31,29,31,30,31,30,31,31,30,31,30,31); - $day = intval($_POST['day']); - if(($day > $mtab[$month]) || ($day < 0)) - $day = 0; - -// if($year && (! ($month && $day))) { -// $month = 1; $day = 1; -// } - - $dob = '0000-00-00'; - $dob = sprintf('%04d-%02d-%02d',$year,$month,$day); + $dob = $_POST['dob'] ? escape_tags(trim($_POST['dob'])) : '0000-00-00'; // FIXME: Needs to be validated? + + $y = substr($dob,0,4); + if((! ctype_digit($y)) || ($y < 1900)) + $ignore_year = true; + else + $ignore_year = false; + + if($dob != '0000-00-00') { + if(strpos($dob,'0000-') === 0) { + $ignore_year = true; + $dob = substr($dob,5); + } + $dob = datetime_convert('UTC','UTC',(($ignore_year) ? '1900-' . $dob : $dob),(($ignore_year) ? 'm-d' : 'Y-m-d')); + if($ignore_year) + $dob = '0000-' . $dob; + } $name = escape_tags(trim($_POST['name'])); if($orig[0]['name'] != $name) $namechanged = true; - $pdesc = escape_tags(trim($_POST['pdesc'])); $gender = escape_tags(trim($_POST['gender'])); $address = escape_tags(trim($_POST['address'])); @@ -240,7 +301,7 @@ function profiles_post(&$a) { $with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : ''); if(! strlen($howlong)) - $howlong = '0000-00-00 00:00:00'; + $howlong = NULL_DATE; else $howlong = datetime_convert(date_default_timezone_get(),'UTC',$howlong); @@ -284,9 +345,41 @@ function profiles_post(&$a) { $with = $orig[0]['with']; } - - - + $profile_fields_basic = get_profile_fields_basic(); + $profile_fields_advanced = get_profile_fields_advanced(); + $advanced = ((feature_enabled(local_user(),'advanced_profiles')) ? true : false); + if($advanced) + $fields = $profile_fields_advanced; + else + $fields = $profile_fields_basic; + + $z = q("select * from profdef where true"); + if($z) { + foreach($z as $zz) { + if(array_key_exists($zz['field_name'],$fields)) { + $w = q("select * from profext where channel_id = %d and hash = '%s' and k = '%s' limit 1", + intval(local_user()), + dbesc($orig[0]['profile_guid']), + dbesc($zz['field_name']) + ); + if($w) { + q("update profext set v = '%s' where id = %d", + dbesc(escape_tags(trim($_POST[$zz['field_name']]))), + intval($w[0]['id']) + ); + } + else { + q("insert into profext ( channel_id, hash, k, v ) values ( %d, '%s', '%s', '%s') ", + intval(local_user()), + dbesc($orig[0]['profile_guid']), + dbesc($zz['field_name']), + dbesc(escape_tags(trim($_POST[$zz['field_name']]))) + ); + } + } + } + } + $changes = array(); $value = ''; if($is_default) { @@ -385,7 +478,7 @@ function profiles_post(&$a) { `work` = '%s', `education` = '%s', `hide_friends` = %d - WHERE `id` = %d AND `uid` = %d LIMIT 1", + WHERE `id` = %d AND `uid` = %d", dbesc($profile_name), dbesc($name), dbesc($pdesc), @@ -438,7 +531,7 @@ function profiles_post(&$a) { $channel = $a->get_channel(); if($namechanged && $is_default) { - $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s' limit 1", + $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'", dbesc($name), dbesc(datetime_convert()), dbesc($channel['xchan_hash']) @@ -446,6 +539,8 @@ function profiles_post(&$a) { } if($is_default) { + // reload the info for the sidebar widget - why does this not work? + profile_load($a,$channel['channel_address']); proc_run('php','include/directory.php',local_user()); } } @@ -458,14 +553,30 @@ function profiles_content(&$a) { $o = ''; + $channel = $a->get_channel(); + if(! local_user()) { notice( t('Permission denied.') . EOL); return; } - if((argc() > 1) && (intval(argv(1)))) { + require_once('include/identity.php'); + + $profile_fields_basic = get_profile_fields_basic(); + $profile_fields_advanced = get_profile_fields_advanced(); + + if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_user(),'multi_profiles')) { + if(feature_enabled(local_user(),'multi_profiles')) + $id = $a->argv[1]; + else { + $x = q("select id from profile where uid = %d and is_default = 1", + intval(local_user()) + ); + if($x) + $id = $x[0]['id']; + } $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", - intval($a->argv[1]), + intval($id), intval(local_user()) ); if(! count($r)) { @@ -485,16 +596,39 @@ function profiles_content(&$a) { '$editselect' => $editselect, )); + $advanced = ((feature_enabled(local_user(),'advanced_profiles')) ? true : false); + if($advanced) + $fields = $profile_fields_advanced; + else + $fields = $profile_fields_basic; - $opt_tpl = get_markup_template("profile-hide_friends.tpl"); - $hide_friends = replace_macros($opt_tpl,array( - '$desc' => t('Hide your contact/friend list from viewers of this profile?'), - '$yes_str' => t('Yes'), - '$no_str' => t('No'), - '$yes_selected' => (($r[0]['hide_friends']) ? " checked=\"checked\" " : ""), - '$no_selected' => (($r[0]['hide_friends'] == 0) ? " checked=\"checked\" " : "") - )); + $opt_tpl = get_markup_template("profile_hide_friends.tpl"); + $hide_friends = replace_macros($opt_tpl,array('$field' => array( + 'hide-friends', + t('Hide your contact/friend list from viewers of this profile?'), + $r[0]['hide_friends'], + '', + ))); + + $q = q("select * from profdef where true"); + if($q) { + $extra_fields = array(); + + foreach($q as $qq) { + $mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1", + dbesc($qq['field_name']), + dbesc($r[0]['profile_guid']), + intval(local_user()) + ); + + if(array_key_exists($qq['field_name'],$fields)) { + $extra_fields[] = array($qq['field_name'],$qq['field_desc'],(($mine) ? $mine[0]['v'] : ''), $qq['field_help']); + } + } + } + +//logger('extra_fields: ' . print_r($extra_fields,true)); $f = get_config('system','birthday_input_format'); if(! $f) @@ -505,24 +639,29 @@ function profiles_content(&$a) { $o .= replace_macros($tpl,array( '$form_security_token' => get_form_security_token("profile_edit"), - '$profile_clone_link' => 'profiles/clone/' . $r[0]['id'] . '?t=' - . get_form_security_token("profile_clone"), + '$profile_clone_link' => ((feature_enabled(local_user(),'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t=' + . get_form_security_token("profile_clone") : ''), '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"), + '$fields' => $fields, '$guid' => $r[0]['profile_guid'], '$banner' => t('Edit Profile Details'), '$submit' => t('Submit'), '$viewprof' => t('View this profile'), + '$editvis' => t('Edit visibility'), '$profpic' => t('Change Profile Photo'), '$cr_prof' => t('Create a new profile using these settings'), '$cl_prof' => t('Clone this profile'), '$del_prof' => t('Delete this profile'), + '$exportable' => feature_enabled(local_user(),'profile_export'), + '$lbl_import' => t('Import profile from file'), + '$lbl_export' => t('Export profile to file'), '$lbl_profname' => t('Profile Name:'), '$lbl_fullname' => t('Your Full Name:'), '$lbl_title' => t('Title/Description:'), '$lbl_gender' => t('Your Gender:'), - '$lbl_bd' => sprintf( t("Birthday \x28%s\x29:"),datesel_format($f)), + '$lbl_bd' => t("Birthday :"), '$lbl_address' => t('Street Address:'), '$lbl_city' => t('Locality/City:'), '$lbl_zip' => t('Postal/Zip Code:'), @@ -557,7 +696,9 @@ function profiles_content(&$a) { '$baseurl' => $a->get_baseurl(true), '$profile_id' => $r[0]['id'], '$profile_name' => $r[0]['profile_name'], - '$default' => (($is_default) ? '<p id="profile-edit-default-desc">' . t('This is your <strong>public</strong> profile.<br />It <strong>may</strong> be visible to anybody using the internet.') . '</p>' : ""), + '$is_default' => $is_default, + '$default' => t('This is your default profile.') . EOL . translate_scope(map_scope($channel['channel_r_profile'])), + '$advanced' => $advanced, '$name' => $r[0]['name'], '$pdesc' => $r[0]['pdesc'], '$dob' => dob($r[0]['dob']), @@ -569,10 +710,13 @@ function profiles_content(&$a) { '$country_name' => $r[0]['country_name'], '$age' => ((intval($r[0]['dob'])) ? '(' . t('Age: ') . age($r[0]['dob'],$a->user['timezone'],$a->user['timezone']) . ')' : ''), '$gender' => gender_selector($r[0]['gender']), + '$gender_min' => gender_selector_min($r[0]['gender']), '$marital' => marital_selector($r[0]['marital']), + '$marital_min' => marital_selector_min($r[0]['marital']), '$with' => $r[0]['with'], - '$howlong' => ($r[0]['howlong'] === '0000-00-00 00:00:00' ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong'])), + '$howlong' => ($r[0]['howlong'] === NULL_DATE ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong'])), '$sexual' => sexpref_selector($r[0]['sexual']), + '$sexual_min' => sexpref_selector_min($r[0]['sexual']), '$about' => $r[0]['about'], '$homepage' => $r[0]['homepage'], '$hometown' => $r[0]['hometown'], @@ -591,6 +735,7 @@ function profiles_content(&$a) { '$education' => $r[0]['education'], '$contact' => $r[0]['contact'], '$channels' => $r[0]['channels'], + '$extra_fields' => $extra_fields, )); $arr = array('profile' => $r[0], 'entry' => $o); @@ -624,10 +769,11 @@ function profiles_content(&$a) { '$alt' => t('Profile Image'), '$profile_name' => $rr['profile_name'], '$visible' => (($rr['is_default']) - ? '<strong>' . t('visible to everybody') . '</strong>' + ? '<strong>' . translate_scope(map_scope($channel['channel_r_profile'])) . '</strong>' : '<a href="' . $a->get_baseurl(true) . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>') )); } + } return $o; } diff --git a/mod/profperm.php b/mod/profperm.php index 197062936..55dc8cc77 100644 --- a/mod/profperm.php +++ b/mod/profperm.php @@ -75,13 +75,13 @@ function profperm_content(&$a) { if($change) { if(in_array($change,$ingroup)) { - q("UPDATE abook SET abook_profile = '' WHERE abook_id = %d AND abook_channel = %d LIMIT 1", + q("UPDATE abook SET abook_profile = '' WHERE abook_id = %d AND abook_channel = %d", intval($change), intval(local_user()) ); } else { - q("UPDATE abook SET abook_profile = '%s' WHERE abook_id = %d AND abook_channel = %d LIMIT 1", + q("UPDATE abook SET abook_profile = '%s' WHERE abook_id = %d AND abook_channel = %d", dbesc($profile['profile_guid']), intval($change), intval(local_user()) diff --git a/mod/receive.php b/mod/receive.php new file mode 100644 index 000000000..b7d27d40f --- /dev/null +++ b/mod/receive.php @@ -0,0 +1,77 @@ +<?php + +/** + * Diaspora endpoint + */ + +require_once('include/crypto.php'); +require_once('include/diaspora.php'); + + +function receive_post(&$a) { + + + $enabled = intval(get_config('system','diaspora_enabled')); + if(! $enabled) { + logger('mod-diaspora: disabled'); + http_status_exit(500); + } + + $public = false; + + if((argc() == 2) && (argv(1) === 'public')) { + $public = true; + } + else { + + if(argc() != 3 || argv(1) !== 'users') + http_status_exit(500); + + $guid = argv(2); + + // Diaspora sites *may* provide a truncated guid. + + $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_guid like '%s' AND NOT (channel_pageflags & %d )>0 LIMIT 1", + dbesc($guid . '%'), + intval(PAGE_REMOVED) + ); + if(! $r) + http_status_exit(500); + + $importer = $r[0]; + } + + // It is an application/x-www-form-urlencoded that has been urlencoded twice. + + logger('mod-diaspora: receiving post', LOGGER_DEBUG); + + $xml = urldecode($_POST['xml']); + + logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA); + + if(! $xml) + http_status_exit(500); + + logger('mod-diaspora: message is okay', LOGGER_DEBUG); + + $msg = diaspora_decode($importer,$xml); + + logger('mod-diaspora: decoded', LOGGER_DEBUG); + + logger('mod-diaspora: decoded msg: ' . print_r($msg,true), LOGGER_DATA); + + if(! is_array($msg)) + http_status_exit(500); + + logger('mod-diaspora: dispatching', LOGGER_DEBUG); + + $ret = 0; + if($public) + diaspora_dispatch_public($msg); + else + $ret = diaspora_dispatch($importer,$msg); + + http_status_exit(($ret) ? $ret : 200); + // NOTREACHED +} + diff --git a/mod/register.php b/mod/register.php index 954a32fbf..70bdcf350 100644 --- a/mod/register.php +++ b/mod/register.php @@ -1,6 +1,5 @@ <?php -require_once('include/account.php'); function register_init(&$a) { @@ -38,7 +37,9 @@ function register_post(&$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 > UTC_TIMESTAMP() - INTERVAL 1 day"); + $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) { notice( t('Maximum daily site registrations exceeded. Please try again tomorrow.') . EOL); return; @@ -101,7 +102,7 @@ function register_post(&$a) { $invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : ''); if($using_invites && $invite_code) { - q("delete * from register where hash = '%s' limit 1", dbesc($invite_code)); + q("delete * from register where hash = '%s'", dbesc($invite_code)); set_pconfig($result['account']['account_id'],'system','invites_remaining',$num_invites); } @@ -165,7 +166,9 @@ function register_content(&$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 > UTC_TIMESTAMP() - INTERVAL 1 day"); + $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); @@ -197,13 +200,13 @@ function register_content(&$a) { $invite_code = ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : "" ); - + require_once('include/bbcode.php'); $o = replace_macros(get_markup_template('register.tpl'), array( '$title' => t('Registration'), '$reg_is' => $registration_is, - '$registertext' => get_config('system','register_text'), + '$registertext' => bbcode(get_config('system','register_text')), '$other_sites' => $other_sites, '$invitations' => get_config('system','invitation_only'), '$invite_desc' => t('Membership on this site is by invitation only.'), diff --git a/mod/regmod.php b/mod/regmod.php index c54c0d88e..d75355d5f 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -1,6 +1,5 @@ <?php -require_once('include/account.php'); function regmod_content(&$a) { diff --git a/mod/regver.php b/mod/regver.php index 988fa8c0d..c3ade2ee1 100644 --- a/mod/regver.php +++ b/mod/regver.php @@ -1,7 +1,5 @@ <?php -require_once('include/account.php'); - function regver_content(&$a) { global $lang; diff --git a/mod/removeaccount.php b/mod/removeaccount.php new file mode 100644 index 000000000..70979c07d --- /dev/null +++ b/mod/removeaccount.php @@ -0,0 +1,66 @@ +<?php + +function removeaccount_post(&$a) { + + if(! local_user()) + return; + + if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) + return; + + if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) + return; + + if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify'])))) + return; + + if($_POST['verify'] !== $_SESSION['remove_account_verify']) + return; + + + $account = $a->get_account(); + $account_id = get_account_id(); + + if(! account_verify_password($account['account_email'],$_POST['qxz_password'])) + return; + + if($account['account_password_changed'] != NULL_DATE) { + $d1 = datetime_convert('UTC','UTC','now - 48 hours'); + if($account['account_password_changed'] > d1) { + notice( t('Account removals are not allowed within 48 hours of changing the account password.') . EOL); + return; + } + } + + require_once('include/Contact.php'); + + $global_remove = intval($_POST['global']); + + account_remove($account_id,true); + +} + + + +function removeaccount_content(&$a) { + + if(! local_user()) + goaway(z_root()); + + $hash = random_string(); + + $_SESSION['remove_account_verify'] = $hash; + $tpl = get_markup_template('removeaccount.tpl'); + $o .= replace_macros($tpl, array( + '$basedir' => $a->get_baseurl(), + '$hash' => $hash, + '$title' => t('Remove This Account'), + '$desc' => t('This will completely remove this account including all its channels from the network. Once this has been done it is not recoverable.'), + '$passwd' => t('Please enter your password for verification:'), + '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')), + '$submit' => t('Remove Account') + )); + + return $o; + +}
\ No newline at end of file diff --git a/mod/removeme.php b/mod/removeme.php index f0b4ae3c0..d2ff013b8 100644 --- a/mod/removeme.php +++ b/mod/removeme.php @@ -23,11 +23,19 @@ function removeme_post(&$a) { if(! account_verify_password($account['account_email'],$_POST['qxz_password'])) return; + if($account['account_password_changed'] != NULL_DATE) { + $d1 = datetime_convert('UTC','UTC','now - 48 hours'); + if($account['account_password_changed'] > d1) { + notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL); + return; + } + } + require_once('include/Contact.php'); $global_remove = intval($_POST['global']); - channel_remove(local_user(),1 - $global_remove); + channel_remove(local_user(),1 - $global_remove,true); } diff --git a/mod/rpost.php b/mod/rpost.php index 80406ebef..933db24e3 100644 --- a/mod/rpost.php +++ b/mod/rpost.php @@ -115,7 +115,7 @@ function rpost_content(&$a) { 'nickname' => $channel['channel_address'], 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'acl' => populate_acl($channel, $false), + 'acl' => populate_acl($channel), 'bang' => '', // 'channel_select' => true, 'visitor' => true, diff --git a/mod/search.php b/mod/search.php index 663d355e2..6df9d631a 100644 --- a/mod/search.php +++ b/mod/search.php @@ -23,6 +23,7 @@ function search_content(&$a,$update = 0, $load = false) { $observer = $a->get_observer(); + $observer_hash = (($observer) ? $observer['xchan_hash'] : ''); $o = '<div id="live-search"></div>' . "\r\n"; @@ -67,7 +68,8 @@ function search_content(&$a,$update = 0, $load = false) { ); } else { - $sql_extra = sprintf(" AND `item`.`body` REGEXP '%s' ", dbesc(protect_sprintf(preg_quote($search)))); + $regstr = db_getfunc('REGEXP'); + $sql_extra = sprintf(" AND `item`.`body` $regstr '%s' ", dbesc(protect_sprintf(preg_quote($search)))); } // Here is the way permissions work in the search module... @@ -105,6 +107,7 @@ function search_content(&$a,$update = 0, $load = false) { '$order' => '', '$file' => '', '$cats' => '', + '$tags' => '', '$mid' => '', '$dend' => '', '$dbegin' => '' @@ -113,7 +116,7 @@ function search_content(&$a,$update = 0, $load = false) { } - $pub_sql = public_permissions_sql(get_observer_hash()); + $pub_sql = public_permissions_sql($observer_hash); require_once('include/identity.php'); @@ -122,33 +125,45 @@ function search_content(&$a,$update = 0, $load = false) { if(($update) && ($load)) { $itemspage = get_pconfig(local_user(),'system','itemspage'); $a->set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage'])); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($a->pager['itemspage']), intval($a->pager['start'])); + + // in case somebody turned off public access to sys channel content with permissions + + if(! perm_is_allowed($sys['channel_id'],$observer_hash,'view_stream')) + $sys['xchan_hash'] .= 'disabled'; if($load) { $r = null; - + + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { + $prefix = 'distinct on (created, mid)'; + $suffix = 'ORDER BY created DESC, mid'; + } else { + $prefix = 'distinct'; + $suffix = 'group by mid ORDER BY created DESC'; + } if(local_user()) { - $r = q("SELECT distinct mid, item.id as item_id, item.* from item + $r = q("SELECT $prefix mid, item.id as item_id, item.* from item WHERE item_restrict = 0 AND ((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND item_private = 0 ) OR ( `item`.`uid` = %d )) OR item.owner_xchan = '%s' ) $sql_extra - group by mid ORDER BY created DESC $pager_sql ", + $suffix $pager_sql ", intval(local_user()), dbesc($sys['xchan_hash']) ); } if($r === null) { - $r = q("SELECT distinct mid, item.id as item_id, item.* from item - WHERE item_restrict = 0 - AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' - AND `item`.`deny_gid` = '' AND item_private = 0 ) - and owner_xchan in ( " . stream_perms_xchans(($observer) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) - $pub_sql ) OR owner_xchan = '%s') - $sql_extra - group by mid ORDER BY created DESC $pager_sql", + $r = q("SELECT $prefix mid, item.id as item_id, item.* from item + WHERE item_restrict = 0 + AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' + AND `item`.`deny_gid` = '' AND item_private = 0 ) + and owner_xchan in ( " . stream_perms_xchans(($observer) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) + $pub_sql ) OR owner_xchan = '%s') + $sql_extra + $suffix $pager_sql", dbesc($sys['xchan_hash']) - ); + ); } } else { diff --git a/mod/service_limits.php b/mod/service_limits.php new file mode 100644 index 000000000..83ae2e06c --- /dev/null +++ b/mod/service_limits.php @@ -0,0 +1,23 @@ +<?php /** @file */ + + +function service_limits_content(&$a) { + + if(! local_user()) { + notice( t('Permission denied.') . EOL); + return; + } + + $account = $a->get_account(); + if($account['account_service_class']) { + $x = get_config('service_class',$account['account_service_class']); + if($x) { + $o = print_r($x,true); + return $o; + } + } + return t('No service class restrictions found.'); +} + + +
\ No newline at end of file diff --git a/mod/settings.php b/mod/settings.php index e036755fc..59ce98a2a 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -39,7 +39,9 @@ function settings_post(&$a) { if(! local_user()) return; - // logger('mod_settings: ' . print_r($_REQUEST,true)); + $channel = $a->get_channel(); + + logger('mod_settings: ' . print_r($_REQUEST,true)); if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) return; @@ -120,10 +122,19 @@ function settings_post(&$a) { if((argc() > 1) && (argv(1) === 'features')) { check_form_security_token_redirectOnErr('/settings/features', 'settings_features'); - foreach($_POST as $k => $v) { - if(strpos($k,'feature_') === 0) { - set_pconfig(local_user(),'feature',substr($k,8),((intval($v)) ? 1 : 0)); - } + + // Build list of features and check which are set + $features = get_features(); + $all_features = array(); + foreach($features as $k => $v) { + foreach($v as $f) + $all_features[] = $f[0]; + } + foreach($all_features as $k) { + if(x($_POST,"feature_$k")) + set_pconfig(local_user(),'feature',$k, 1); + else + set_pconfig(local_user(),'feature',$k, 0); } build_sync_packet(); return; @@ -135,7 +146,19 @@ function settings_post(&$a) { $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : $a->channel['channel_theme']); $mobile_theme = ((x($_POST,'mobile_theme')) ? notags(trim($_POST['mobile_theme'])) : ''); - $nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0); + $user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0); + $nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0); + $title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0); + $channel_list_mode = ((x($_POST,'channel_list_mode')) ? intval($_POST['channel_list_mode']) : 0); + $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0); + + $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); + if($channel_divmore_height < 50) + $channel_divmore_height = 50; + $network_divmore_height = ((x($_POST,'network_divmore_height')) ? intval($_POST['network_divmore_height']) : 400); + if($network_divmore_height < 50) + $network_divmore_height = 50; + $browser_update = ((x($_POST,'browser_update')) ? intval($_POST['browser_update']) : 0); $browser_update = $browser_update * 1000; if($browser_update < 10000) @@ -146,17 +169,21 @@ function settings_post(&$a) { $itemspage = 100; - if($mobile_theme !== '') { + if ($mobile_theme == "---") + del_pconfig(local_user(),'system','mobile_theme'); + else { set_pconfig(local_user(),'system','mobile_theme',$mobile_theme); } -// $chanview_full = ((x($_POST,'chanview_full')) ? intval($_POST['chanview_full']) : 0); - + set_pconfig(local_user(),'system','user_scalable',$user_scalable); set_pconfig(local_user(),'system','update_interval', $browser_update); set_pconfig(local_user(),'system','itemspage', $itemspage); set_pconfig(local_user(),'system','no_smilies',$nosmile); -// set_pconfig(local_user(),'system','chanview_full',$chanview_full); - + set_pconfig(local_user(),'system','title_tosource',$title_tosource); + set_pconfig(local_user(),'system','channel_list_mode', $channel_list_mode); + set_pconfig(local_user(),'system','network_list_mode', $network_list_mode); + set_pconfig(local_user(),'system','channel_divmore_height', $channel_divmore_height); + set_pconfig(local_user(),'system','network_divmore_height', $network_divmore_height); if ($theme == $a->channel['channel_theme']){ // call theme_post only if theme has not been changed @@ -166,7 +193,7 @@ function settings_post(&$a) { } } - $r = q("UPDATE channel SET channel_theme = '%s' WHERE channel_id = %d LIMIT 1", + $r = q("UPDATE channel SET channel_theme = '%s' WHERE channel_id = %d", dbesc($theme), intval(local_user()) ); @@ -202,10 +229,11 @@ function settings_post(&$a) { if(! $errs) { $salt = random_string(32); $password_encoded = hash('whirlpool', $salt . $newpass); - $r = q("update account set account_salt = '%s', account_password = '%s' - where account_id = %d limit 1", + $r = q("update account set account_salt = '%s', account_password = '%s', account_password_changed = '%s' + where account_id = %d", dbesc($salt), dbesc($password_encoded), + dbesc(datetime_convert()), intval(get_account_id()) ); if($r) @@ -232,7 +260,7 @@ function settings_post(&$a) { $email = $a->user['email']; } if(! $errs) { - $r = q("update account set account_email = '%s' where account_id = %d limit 1", + $r = q("update account set account_email = '%s' where account_id = %d", dbesc($email), intval($account['account_id']) ); @@ -253,14 +281,111 @@ function settings_post(&$a) { call_hooks('settings_post', $_POST); - + $set_perms = ''; + + $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : ''); + $oldrole = get_pconfig(local_user(),'system','permissions_role'); + + if(($role != $oldrole) || ($role === 'custom')) { + + if($role === 'custom') { + $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0); + $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0); + $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : ''); + $r = q("update channel set channel_default_group = '%s' where channel_id = %d", + dbesc($def_group), + intval(local_user()) + ); + + $global_perms = get_perms(); + + foreach($global_perms as $k => $v) { + $set_perms .= ', ' . $v[0] . ' = ' . intval($_POST[$k]) . ' '; + } + + $str_group_allow = perms2str($_POST['group_allow']); + $str_contact_allow = perms2str($_POST['contact_allow']); + $str_group_deny = perms2str($_POST['group_deny']); + $str_contact_deny = perms2str($_POST['contact_deny']); + $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s', channel_deny_cid = '%s', channel_deny_gid = '%s' + where channel_id = %d", + dbesc($str_contact_allow), + dbesc($str_group_allow), + dbesc($str_contact_deny), + dbesc($str_group_deny), + intval(local_user()) + ); + } + else { + $role_permissions = get_role_perms($_POST['permissions_role']); + if(! $role_permissions) { + notice('Permissions category could not be found.'); + return; + } + $hide_presence = 1 - (intval($role_permissions['online'])); + if($role_permissions['default_collection']) { + $r = q("select hash from groups where uid = %d and name = '%s' limit 1", + intval(local_user()), + dbesc( t('Friends') ) + ); + if(! $r) { + require_once('include/group.php'); + group_add(local_user(), t('Friends')); + group_add_member(local_user(),t('Friends'),$channel['channel_hash']); + $r = q("select hash from groups where uid = %d and name = '%s' limit 1", + intval(local_user()), + dbesc( t('Friends') ) + ); + } + if($r) { + q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d", + dbesc($r[0]['hash']), + dbesc('<' . $r[0]['hash'] . '>'), + intval(local_user()) + ); + } + else { + notice( sprintf('Default privacy collection \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL); + return; + } + } + // no default collection + else { + q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '', + channel_deny_cid = '' where channel_id = %d", + intval(local_user()) + ); + } + + $r = q("update abook set abook_my_perms = %d where abook_channel = %d and (abook_flags & %d)>0", + intval(($role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0), + intval(local_user()), + intval(ABOOK_FLAG_SELF) + ); + set_pconfig(local_user(),'system','autoperms',(($role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0)); + + foreach($role_permissions as $p => $v) { + if(strpos($p,'channel_') !== false) { + $set_perms .= ', ' . $p . ' = ' . intval($v) . ' '; + } + if($p === 'directory_publish') { + $publish = intval($v); + } + } + } + + set_pconfig(local_user(),'system','hide_online_status',$hide_presence); + set_pconfig(local_user(),'system','permissions_role',$role); + } + $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : ''); $timezone = ((x($_POST,'timezone')) ? notags(trim($_POST['timezone'])) : ''); $defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : ''); $openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : ''); $maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0); $expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0); - $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : ''); + $evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3); + $channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : ''); $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0); @@ -269,17 +394,13 @@ function settings_post(&$a) { $expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0); $allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0); - $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0); - $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0); - $page_flags = (((x($_POST,'page-flags')) && (intval($_POST['page-flags']))) ? intval($_POST['page-flags']) : 0); - $blockwall = (((x($_POST,'blockwall')) && (intval($_POST['blockwall']) == 1)) ? 0: 1); // this setting is inverted! + $blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted! $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0); $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0); $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0); - $hide_friends = (($_POST['hide_friends'] == 1) ? 1: 0); - $hidewall = (($_POST['hidewall'] == 1) ? 1: 0); + $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0); $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0); $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0); @@ -291,63 +412,6 @@ function settings_post(&$a) { if($adult != $existing_adult) $pageflags = ($pageflags ^ PAGE_ADULT); - $arr = array(); - $arr['channel_r_stream'] = (($_POST['view_stream']) ? $_POST['view_stream'] : 0); - $arr['channel_r_profile'] = (($_POST['view_profile']) ? $_POST['view_profile'] : 0); - $arr['channel_r_photos'] = (($_POST['view_photos']) ? $_POST['view_photos'] : 0); - $arr['channel_r_abook'] = (($_POST['view_contacts']) ? $_POST['view_contacts'] : 0); - $arr['channel_w_stream'] = (($_POST['send_stream']) ? $_POST['send_stream'] : 0); - $arr['channel_w_wall'] = (($_POST['post_wall']) ? $_POST['post_wall'] : 0); - $arr['channel_w_tagwall'] = (($_POST['tag_deliver']) ? $_POST['tag_deliver'] : 0); - $arr['channel_w_comment'] = (($_POST['post_comments']) ? $_POST['post_comments'] : 0); - $arr['channel_w_mail'] = (($_POST['post_mail']) ? $_POST['post_mail'] : 0); - $arr['channel_w_photos'] = (($_POST['post_photos']) ? $_POST['post_photos'] : 0); - $arr['channel_w_chat'] = (($_POST['chat']) ? $_POST['chat'] : 0); - $arr['channel_a_delegate'] = (($_POST['delegate']) ? $_POST['delegate'] : 0); - $arr['channel_r_storage'] = (($_POST['view_storage']) ? $_POST['view_storage'] : 0); - $arr['channel_w_storage'] = (($_POST['write_storage']) ? $_POST['write_storage'] : 0); - $arr['channel_r_pages'] = (($_POST['view_pages']) ? $_POST['view_pages'] : 0); - $arr['channel_w_pages'] = (($_POST['write_pages']) ? $_POST['write_pages'] : 0); - $arr['channel_a_republish'] = (($_POST['republish']) ? $_POST['republish'] : 0); - $arr['channel_w_like'] = (($_POST['post_like']) ? $_POST['post_like'] : 0); - - $defperms = 0; - if(x($_POST['def_view_stream'])) - $defperms += $_POST['def_view_stream']; - if(x($_POST['def_view_profile'])) - $defperms += $_POST['def_view_profile']; - if(x($_POST['def_view_photos'])) - $defperms += $_POST['def_view_photos']; - if(x($_POST['def_view_contacts'])) - $defperms += $_POST['def_view_contacts']; - if(x($_POST['def_send_stream'])) - $defperms += $_POST['def_send_stream']; - if(x($_POST['def_post_wall'])) - $defperms += $_POST['def_post_wall']; - if(x($_POST['def_tag_deliver'])) - $defperms += $_POST['def_tag_deliver']; - if(x($_POST['def_post_comments'])) - $defperms += $_POST['def_post_comments']; - if(x($_POST['def_post_mail'])) - $defperms += $_POST['def_post_mail']; - if(x($_POST['def_post_photos'])) - $defperms += $_POST['def_post_photos']; - if(x($_POST['def_chat'])) - $defperms += $_POST['def_chat']; - if(x($_POST['def_delegate'])) - $defperms += $_POST['def_delegate']; - if(x($_POST['def_view_storage'])) - $defperms += $_POST['def_view_storage']; - if(x($_POST['def_write_storage'])) - $defperms += $_POST['def_write_storage']; - if(x($_POST['def_view_pages'])) - $defperms += $_POST['def_view_pages']; - if(x($_POST['def_write_pages'])) - $defperms += $_POST['def_write_pages']; - if(x($_POST['def_republish'])) - $defperms += $_POST['def_republish']; - if(x($_POST['def_post_like'])) - $defperms += $_POST['def_post_like']; $notify = 0; @@ -369,6 +433,33 @@ function settings_post(&$a) { $notify += intval($_POST['notify8']); + $vnotify = 0; + + if(x($_POST,'vnotify1')) + $vnotify += intval($_POST['vnotify1']); + if(x($_POST,'vnotify2')) + $vnotify += intval($_POST['vnotify2']); + if(x($_POST,'vnotify3')) + $vnotify += intval($_POST['vnotify3']); + if(x($_POST,'vnotify4')) + $vnotify += intval($_POST['vnotify4']); + if(x($_POST,'vnotify5')) + $vnotify += intval($_POST['vnotify5']); + if(x($_POST,'vnotify6')) + $vnotify += intval($_POST['vnotify6']); + if(x($_POST,'vnotify7')) + $vnotify += intval($_POST['vnotify7']); + if(x($_POST,'vnotify8')) + $vnotify += intval($_POST['vnotify8']); + if(x($_POST,'vnotify9')) + $vnotify += intval($_POST['vnotify9']); + if(x($_POST,'vnotify10')) + $vnotify += intval($_POST['vnotify10']); + if(x($_POST,'vnotify11')) + $vnotify += intval($_POST['vnotify11']); + + $always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0; + $channel = $a->get_channel(); $err = ''; @@ -385,27 +476,23 @@ function settings_post(&$a) { } } - if($timezone != $channel['channel_timezone']) { if(strlen($timezone)) date_default_timezone_set($timezone); } - $str_group_allow = perms2str($_POST['group_allow']); - $str_contact_allow = perms2str($_POST['contact_allow']); - $str_group_deny = perms2str($_POST['group_deny']); - $str_contact_deny = perms2str($_POST['contact_deny']); - set_pconfig(local_user(),'system','use_browser_location',$allow_location); set_pconfig(local_user(),'system','suggestme', $suggestme); set_pconfig(local_user(),'system','post_newfriend', $post_newfriend); set_pconfig(local_user(),'system','post_joingroup', $post_joingroup); set_pconfig(local_user(),'system','post_profilechange', $post_profilechange); set_pconfig(local_user(),'system','blocktags',$blocktags); - set_pconfig(local_user(),'system','hide_online_status',$hide_presence); set_pconfig(local_user(),'system','channel_menu',$channel_menu); + set_pconfig(local_user(),'system','vnotify',$vnotify); + set_pconfig(local_user(),'system','always_show_in_notices',$always_show_in_notices); + set_pconfig(local_user(),'system','evdays',$evdays); - $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d, channel_default_group = '%s', channel_r_stream = %d, channel_r_profile = %d, channel_r_photos = %d, channel_r_abook = %d, channel_w_stream = %d, channel_w_wall = %d, channel_w_tagwall = %d, channel_w_comment = %d, channel_w_mail = %d, channel_w_photos = %d, channel_w_chat = %d, channel_a_delegate = %d, channel_r_storage = %d, channel_w_storage = %d, channel_r_pages = %d, channel_w_pages = %d, channel_a_republish = %d, channel_w_like = %d, channel_allow_cid = '%s', channel_allow_gid = '%s', channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d limit 1", + $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d", dbesc($username), intval($pageflags), dbesc($timezone), @@ -414,45 +501,20 @@ function settings_post(&$a) { intval($unkmail), intval($maxreq), intval($expire), - dbesc($def_group), - intval($arr['channel_r_stream']), - intval($arr['channel_r_profile']), - intval($arr['channel_r_photos']), - intval($arr['channel_r_abook']), - intval($arr['channel_w_stream']), - intval($arr['channel_w_wall']), - intval($arr['channel_w_tagwall']), - intval($arr['channel_w_comment']), - intval($arr['channel_w_mail']), - intval($arr['channel_w_photos']), - intval($arr['channel_w_chat']), - intval($arr['channel_a_delegate']), - intval($arr['channel_r_storage']), - intval($arr['channel_w_storage']), - intval($arr['channel_r_pages']), - intval($arr['channel_w_pages']), - intval($arr['channel_a_republish']), - intval($arr['channel_w_like']), - dbesc($str_contact_allow), - dbesc($str_group_allow), - dbesc($str_contact_deny), - dbesc($str_group_deny), intval(local_user()) ); if($r) info( t('Settings updated.') . EOL); - $r = q("UPDATE `profile` - SET `publish` = %d, - `hide_friends` = %d - WHERE `is_default` = 1 AND `uid` = %d LIMIT 1", - intval($publish), - intval($hide_friends), - intval(local_user()) - ); + if(! is_null($publish)) { + $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d", + intval($publish), + intval(local_user()) + ); + } if($name_change) { - $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s' limit 1", + $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", dbesc($username), dbesc(datetime_convert()), dbesc($channel['channel_hash']) @@ -587,7 +649,7 @@ function settings_content(&$a) { if((argc() > 1) && (argv(1) === 'featured')) { $settings_addons = ""; - $r = q("SELECT * FROM `hook` WHERE `hook` = 'plugin_settings' "); + $r = q("SELECT * FROM `hook` WHERE `hook` = 'feature_settings' "); if(! count($r)) $settings_addons = t('No feature settings configured'); @@ -627,6 +689,7 @@ function settings_content(&$a) { '$submit' => t('Submit'), '$email' => array('email', t('Email Address:'), $email, ''), '$removeme' => t('Remove Account'), + '$removeaccount' => t('Remove this account from this server including all its channels'), '$permanent' => t('Warning: This action is permanent and cannot be reversed.'), '$account_settings' => $account_settings )); @@ -653,7 +716,6 @@ function settings_content(&$a) { '$title' => t('Additional Features'), '$features' => $arr, '$submit' => t('Submit'), - '$field_yesno' => 'field_yesno.tpl', )); return $o; @@ -687,6 +749,7 @@ function settings_content(&$a) { /* * DISPLAY SETTINGS */ + if((argc() > 1) && (argv(1) === 'display')) { $default_theme = get_config('system','theme'); if(! $default_theme) @@ -705,7 +768,6 @@ function settings_content(&$a) { $themes = array(); - $mobile_themes = array("---" => t('No special theme for mobile devices')); $files = glob('view/theme/*'); if($allowed_themes) { foreach($allowed_themes as $th) { @@ -713,22 +775,31 @@ function settings_content(&$a) { $is_experimental = file_exists('view/theme/' . $th . '/experimental'); $unsupported = file_exists('view/theme/' . $th . '/unsupported'); $is_mobile = file_exists('view/theme/' . $th . '/mobile'); + $is_library = file_exists('view/theme/'. $th . '/library'); + $mobile_themes["---"] = t("No special theme for mobile devices"); + if (!$is_experimental or ($is_experimental && (get_config('experimentals','exp_themes')==1 or get_config('experimentals','exp_themes')===false))){ $theme_name = (($is_experimental) ? sprintf(t('%s - (Experimental)'), $f) : $f); - if($is_mobile) { - $mobile_themes[$f]=$theme_name; - } - else { - $themes[$f]=$theme_name; + if (! $is_library) { + if($is_mobile) { + $mobile_themes[$f] = $themes[$f] = $theme_name . ' (' . t('mobile') . ')'; + } + else { + $mobile_themes[$f] = $themes[$f] = $theme_name; + } } } + } } $theme_selected = (!x($_SESSION,'theme')? $default_theme : $_SESSION['theme']); $mobile_theme_selected = (!x($_SESSION,'mobile_theme')? $default_mobile_theme : $_SESSION['mobile_theme']); + + $user_scalable = get_pconfig(local_user(),'system','user_scalable'); + $user_scalable = (($user_scalable===false)? '1': $user_scalable); // default if not set: 1 $browser_update = intval(get_pconfig(local_user(), 'system','update_interval')); - $browser_update = (($browser_update == 0) ? 40 : $browser_update / 1000); // default if not set: 40 seconds + $browser_update = (($browser_update == 0) ? 80 : $browser_update / 1000); // default if not set: 40 seconds $itemspage = intval(get_pconfig(local_user(), 'system','itemspage')); $itemspage = (($itemspage > 0 && $itemspage < 101) ? $itemspage : 20); // default if not set: 20 items @@ -736,6 +807,9 @@ function settings_content(&$a) { $nosmile = get_pconfig(local_user(),'system','no_smilies'); $nosmile = (($nosmile===false)? '0': $nosmile); // default if not set: 0 + $title_tosource = get_pconfig(local_user(),'system','title_tosource'); + $title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0 + $theme_config = ""; if( ($themeconfigfile = get_theme_config_file($theme_selected)) != null){ require_once($themeconfigfile); @@ -752,11 +826,20 @@ function settings_content(&$a) { '$theme' => array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview'), '$mobile_theme' => array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, ''), + '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, ''), '$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')), '$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 100 items')), '$nosmile' => array('nosmile', t("Don't show emoticons"), $nosmile, ''), + '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, ''), '$layout_editor' => t('System Page Layout Editor - (advanced)'), '$theme_config' => $theme_config, + '$expert' => feature_enabled(local_user(),'expert'), + '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_user(),'system','channel_list_mode'), t('(comments displayed separately)')), + '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on matrix page'), get_pconfig(local_user(),'system','network_list_mode'), t('(comments displayed separately)')), + '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_user(),'system','channel_divmore_height')) ? get_pconfig(local_user(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), + '$network_divmore_height' => array('network_divmore_height', t('Matrix page max height of content (in pixels)'), ((get_pconfig(local_user(),'system','network_divmore_height')) ? get_pconfig(local_user(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), + + )); return $o; @@ -772,8 +855,6 @@ function settings_content(&$a) { require_once('include/permissions.php'); - - $p = q("SELECT * FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1", intval(local_user()) ); @@ -826,9 +907,8 @@ function settings_content(&$a) { $expire = $channel['channel_expire_days']; $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT); - $blockwall = $a->user['blockwall']; - $unkmail = $a->user['unkmail']; - $cntunkmail = $a->user['cntunkmail']; +// $unkmail = $a->user['unkmail']; +// $cntunkmail = $a->user['cntunkmail']; $hide_presence = intval(get_pconfig(local_user(), 'system','hide_online_status')); @@ -866,9 +946,7 @@ function settings_content(&$a) { $timezone = date_default_timezone_get(); - - - $opt_tpl = get_markup_template("field_yesno.tpl"); + $opt_tpl = get_markup_template("field_checkbox.tpl"); if(get_config('system','publish_all')) { $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />'; } @@ -921,6 +999,17 @@ function settings_content(&$a) { } } + $evdays = get_pconfig(local_user(),'system','evdays'); + if(! $evdays) + $evdays = 3; + + $permissions_role = get_pconfig(local_user(),'system','permissions_role'); + $permissions_set = (($permissions_role && $permissions_role != 'custom') ? true : false); + $vnotify = get_pconfig(local_user(),'system','vnotify'); + $always_show_in_notices = get_pconfig(local_user(),'system','always_show_in_notices'); + if($vnotify === false) + $vnotify = (-1); + $o .= replace_macros($stpl,array( '$ptitle' => t('Channel Settings'), @@ -929,18 +1018,18 @@ function settings_content(&$a) { '$uid' => local_user(), '$form_security_token' => get_form_security_token("settings"), '$nickname_block' => $prof_addr, - - '$h_basic' => t('Basic Settings'), '$username' => array('username', t('Full Name:'), $username,''), '$email' => array('email', t('Email Address:'), $email, ''), - '$timezone' => array('timezone_select' , t('Your Timezone:'), select_timezone($timezone), ''), + '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()), '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')), '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_user(),'system','use_browser_location')) ? 1 : ''), ''), '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)')), '$h_prv' => t('Security and Privacy Settings'), + '$permissions_set' => $permissions_set, + '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online')), @@ -960,9 +1049,8 @@ function settings_content(&$a) { '$permdesc' => t("\x28click to open/close\x29"), '$aclselect' => populate_acl($perm_defaults,false), '$suggestme' => $suggestme, - '$group_select' => $group_select, - + '$role' => array('permissions_role' , t('Channel permissions category:'), $permissions_role, '', get_roles()), '$profile_in_dir' => $profile_in_dir, '$hide_friends' => $hide_friends, @@ -986,7 +1074,24 @@ function settings_content(&$a) { '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, ''), '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, ''), - + + '$lbl_vnot' => t('Show visual notifications including:'), + + '$vnotify1' => array('vnotify1', t('Unseen matrix activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, ''), + '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, ''), + '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended')), + '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, ''), + '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, ''), + '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes')), + '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, ''), + '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended')), + '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended')), + '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended')), + '$vnotify11' => array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, ''), + '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, ''), + + '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')), + '$h_advn' => t('Advanced Account/Page Type Settings'), '$h_descadvn' => t('Change the behaviour of this account for special situations'), '$pagetype' => $pagetype, diff --git a/mod/setup.php b/mod/setup.php index ad5394335..6f2c7c074 100755 --- a/mod/setup.php +++ b/mod/setup.php @@ -50,16 +50,18 @@ function setup_post(&$a) { $dbuser = trim($_POST['dbuser']); $dbpass = trim($_POST['dbpass']); $dbdata = trim($_POST['dbdata']); + $dbtype = intval(trim($_POST['dbtype'])); $phpath = trim($_POST['phpath']); $adminmail = trim($_POST['adminmail']); $siteurl = trim($_POST['siteurl']); require_once('include/dba/dba_driver.php'); unset($db); - $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, true); + $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); if(! $db->connected) { echo "Database Connect failed: " . $db->error; killme(); + $a->data['db_conn_failed']=true; } /*if(get_db_errno()) { unset($db); @@ -80,9 +82,9 @@ function setup_post(&$a) { return; } }*/ - if(get_db_errno()) { - $a->data['db_conn_failed']=true; - } + //if(get_db_errno()) { + + //} return; break; @@ -93,6 +95,7 @@ function setup_post(&$a) { $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); + $dbtype = intval(notags(trim($_POST['dbtype']))); $phpath = notags(trim($_POST['phpath'])); $timezone = notags(trim($_POST['timezone'])); $adminmail = notags(trim($_POST['adminmail'])); @@ -109,7 +112,7 @@ function setup_post(&$a) { } // connect to db - $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, true); + $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); if(! $db->connected) { echo 'CRITICAL: DB not connected.'; @@ -123,6 +126,7 @@ function setup_post(&$a) { '$dbuser' => $dbuser, '$dbpass' => $dbpass, '$dbdata' => $dbdata, + '$dbtype' => $dbtype, '$timezone' => $timezone, '$siteurl' => $siteurl, '$site_id' => random_string(), @@ -187,7 +191,7 @@ function setup_content(&$a) { } if(x($a->data,'db_failed')) { - $txt = t('You may need to import the file "install/database.sql" manually using phpmyadmin or mysql.') . EOL; + $txt = t('You may need to import the file "install/schema_xxx.sql" manually using a database client.') . EOL; $txt .= t('Please see the file "install/INSTALL.txt".') . EOL ."<hr>" ; $txt .= "<pre>".$a->data['db_failed'] . "</pre>". EOL ; $db_return_text .= $txt; @@ -273,6 +277,7 @@ function setup_content(&$a) { $dbport = intval(notags(trim($_POST['dbport']))); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); + $dbtype = intval(notags(trim($_POST['dbtype']))); $phpath = notags(trim($_POST['phpath'])); $adminmail = notags(trim($_POST['adminmail'])); $siteurl = notags(trim($_POST['siteurl'])); @@ -293,6 +298,7 @@ function setup_content(&$a) { '$dbuser' => array('dbuser', t('Database Login Name'), $dbuser, ''), '$dbpass' => array('dbpass', t('Database Login Password'), $dbpass, ''), '$dbdata' => array('dbdata', t('Database Name'), $dbdata, ''), + '$dbtype' => array('dbtype', t('Database Type'), $dbtype, '', array( 0=>'MySQL', 1=>'PostgreSQL' )), '$adminmail' => array('adminmail', t('Site administrator email address'), $adminmail, t('Your account email address must match this in order to use the web admin panel.')), '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')), @@ -316,6 +322,7 @@ function setup_content(&$a) { $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); + $dbtype = intval(notags(trim($_POST['dbtype']))); $phpath = notags(trim($_POST['phpath'])); $adminmail = notags(trim($_POST['adminmail'])); @@ -335,13 +342,14 @@ function setup_content(&$a) { '$dbpass' => $dbpass, '$dbdata' => $dbdata, '$phpath' => $phpath, + '$dbtype' => $dbtype, '$adminmail' => array('adminmail', t('Site administrator email address'), $adminmail, t('Your account email address must match this in order to use the web admin panel.')), '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')), - '$timezone' => field_timezone('timezone', t('Please select a default timezone for your website'), $timezone, ''), + '$timezone' => array('timezone', t('Please select a default timezone for your website'), $timezone, '', get_timezones()), '$baseurl' => $a->get_baseurl(), @@ -440,7 +448,7 @@ function check_funcs(&$checks) { check_add($ck_funcs, t('libCurl PHP module'), true, true, ""); check_add($ck_funcs, t('GD graphics PHP module'), true, true, ""); check_add($ck_funcs, t('OpenSSL PHP module'), true, true, ""); - check_add($ck_funcs, t('mysqli PHP module'), true, true, ""); + check_add($ck_funcs, t('mysqli or postgres PHP module'), true, true, ""); check_add($ck_funcs, t('mb_string PHP module'), true, true, ""); check_add($ck_funcs, t('mcrypt PHP module'), true, true, ""); @@ -471,9 +479,9 @@ function check_funcs(&$checks) { $ck_funcs[2]['status']= false; $ck_funcs[2]['help']= t('Error: openssl PHP module required but not installed.'); } - if(! function_exists('mysqli_connect')){ + if(! function_exists('mysqli_connect') && !function_exists('pg_connect')){ $ck_funcs[3]['status']= false; - $ck_funcs[3]['help']= t('Error: mysqli PHP module required but not installed.'); + $ck_funcs[3]['help']= t('Error: mysqli or postgres PHP module required but neither are installed.'); } if(! function_exists('mb_strlen')){ $ck_funcs[4]['status']= false; @@ -569,7 +577,7 @@ function check_htaccess(&$checks) { $help = t('SSL certificate cannot be validated. Fix certificate or disable https access to this site.') . EOL; $help .= t('If you have https access to your website or allow connections to TCP port 443 (the https: port), you MUST use a browser-valid certificate. You MUST NOT use self-signed certificates!') . EOL; $help .= t('This restriction is incorporated because public posts from you may for example contain references to images on your own hub.') . EOL; - $help .= t('If your certificate is not recognised, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL; + $help .= t('If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL; $help .= t('This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement.') .EOL; $help .= t('Providers are available that issue free certificates which are browser-valid.'). EOL; @@ -579,7 +587,7 @@ function check_htaccess(&$checks) { if ((! $test['success']) || ($test['body'] != "ok")) { $status = false; - $help = t('Url rewrite in .htaccess is not working. Check your server configuration.'); + $help = t('Url rewrite in .htaccess is not working. Check your server configuration.'.'Test: '.var_export($test,true)); } check_add($checks, t('Url rewrite is working'), $status, true, $help); } else { @@ -607,8 +615,8 @@ function load_database_rem($v, $i){ function load_database($db) { - - $str = file_get_contents('install/database.sql'); + file_put_contents('debug-foo.log', 'Loading schema: '.$db->get_install_script()); + $str = file_get_contents($db->get_install_script()); $arr = explode(';',$str); $errors = false; foreach($arr as $a) { diff --git a/mod/share.php b/mod/share.php index 8b0403663..78a25ee10 100644 --- a/mod/share.php +++ b/mod/share.php @@ -14,10 +14,12 @@ function share_init(&$a) { killme(); - $r = q("SELECT * from item WHERE id = %d LIMIT 1", + $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1", intval($post_id) ); - if((! $r) || $r[0]['item_private']) + if(! $r) + killme(); + if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss')) killme(); $sql_extra = item_permissions_sql($r[0]['uid']); diff --git a/mod/siteinfo.php b/mod/siteinfo.php index bdf9b1af6..01804e62a 100644 --- a/mod/siteinfo.php +++ b/mod/siteinfo.php @@ -1,24 +1,39 @@ <?php function siteinfo_init(&$a) { - + global $db; + if ($a->argv[1]=="json"){ $register_policy = Array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN'); - + $directory_mode = Array('DIRECTORY_MODE_NORMAL', 'DIRECTORY_MODE_SECONDARY','DIRECTORY_MODE_PRIMARY', 'DIRECTORY_MODE_STANDALONE'); + $sql_extra = ''; - if(x($a->config,'admin_nickname')) { - $sql_extra = sprintf(" AND nickname = '%s' ",dbesc($a->config['admin_nickname'])); + + $r = q("select * from channel left join account on account_id = channel_account_id where ( account_roles & 4096 )>0 and account_default_channel = channel_id"); + + + if($r) { + $admin = array(); + foreach($r as $rr) { + if($rr['channel_pageflags'] & PAGE_HUBADMIN) + $admin[] = array( 'name' => $rr['channel_name'], 'address' => $rr['channel_address'] . '@' . get_app()->get_hostname(), 'channel' => z_root() . '/channel/' . $rr['channel_address']); + } + if(! $admin) { + foreach($r as $rr) { + $admin[] = array( 'name' => $rr['channel_name'], 'address' => $rr['channel_address'] . '@' . get_app()->get_hostname(), 'channel' => z_root() . '/channel/' . $rr['channel_address']); + } + } } - if (isset($a->config['admin_email']) && $a->config['admin_email']!=''){ - $r = q("SELECT username, nickname FROM user WHERE email='%s' $sql_extra", dbesc($a->config['admin_email'])); - $admin = array( - 'name' => $r[0]['username'], - 'profile'=> $a->get_baseurl().'/channel/'.$r[0]['nickname'], - ); - } else { + else { $admin = false; } + $def_service_class = get_config('system','default_service_class'); + if($def_service_class) + $service_class = get_config('service_class',$def_service_class); + else + $service_class = false; + $visible_plugins = array(); if(is_array($a->plugins) && count($a->plugins)) { $r = q("select * from addon where hidden = 0"); @@ -26,26 +41,47 @@ function siteinfo_init(&$a) { foreach($r as $rr) $visible_plugins[] = $rr['name']; } + sort($visible_plugins); if(@is_dir('.git') && function_exists('shell_exec')) - $commit = @shell_exec('git log -1 --format="%h"'); + $commit = trim(@shell_exec('git log -1 --format="%h"')); if(! isset($commit) || strlen($commit) > 16) $commit = ''; + $site_info = get_config('system','info'); + $site_name = get_config('system','sitename'); + + //Statistics + $channels_total_stat = intval(get_config('system','channels_total_stat')); + $channels_active_halfyear_stat = intval(get_config('system','channels_active_halfyear_stat')); + $channels_active_monthly_stat = intval(get_config('system','channels_active_monthly_stat')); + $local_posts_stat = intval(get_config('system','local_posts_stat')); + $hide_in_statistics = intval(get_config('system','hide_in_statistics')); + $data = Array( 'version' => RED_VERSION, 'commit' => $commit, 'url' => z_root(), 'plugins' => $visible_plugins, 'register_policy' => $register_policy[$a->config['system']['register_policy']], + 'directory_mode' => $directory_mode[$a->config['system']['directory_mode']], + 'language' => get_config('system','language'), + 'diaspora_emulation' => get_config('system','diaspora_enabled'), + 'rss_connections' => get_config('system','feed_contacts'), + 'default_service_restrictions' => $service_class, 'admin' => $admin, - 'site_name' => $a->config['sitename'], + 'site_name' => (($site_name) ? $site_name : ''), 'platform' => RED_PLATFORM, - 'info' => ((x($a->config,'info')) ? $a->config['info'] : '') + 'dbdriver' => $db->getdriver(), + 'lastpoll' => get_config('system','lastpoll'), + 'info' => (($site_info) ? $site_info : ''), + 'channels_total' => $channels_total_stat, + 'channels_active_halfyear' => $channels_active_halfyear_stat, + 'channels_active_monthly' => $channels_active_monthly_stat, + 'local_posts' => $local_posts_stat, + 'hide_in_statistics' => $hide_in_statistics ); - - echo json_encode($data); - killme(); + json_return_and_die($data); } } @@ -55,8 +91,10 @@ function siteinfo_content(&$a) { if(! get_config('system','hidden_version_siteinfo')) { $version = sprintf( t('Version %s'), RED_VERSION ); - if(@is_dir('.git') && function_exists('shell_exec')) + if(@is_dir('.git') && function_exists('shell_exec')) { $commit = @shell_exec('git log -1 --format="%h"'); + $tag = @shell_exec('git describe --tags --abbrev=0'); + } if(! isset($commit) || strlen($commit) > 16) $commit = ''; } @@ -95,11 +133,15 @@ function siteinfo_content(&$a) { $o = replace_macros(get_markup_template('siteinfo.tpl'), array( '$title' => t('Red'), - '$description' => t('This is a hub of the Red Matrix - a global cooperative network of decentralised privacy enhanced websites.'), + '$description' => t('This is a hub of the Red Matrix - a global cooperative network of decentralized privacy enhanced websites.'), '$version' => $version, + '$tag_txt' => t('Tag: '), + '$tag' => $tag, + '$polled' => t('Last background fetch: '), + '$lastpoll' => get_poller_runtime(), '$commit' => $commit, '$web_location' => t('Running at web location') . ' ' . z_root(), - '$visit' => t('Please visit <a href="http://getzot.com">GetZot.com</a> to learn more about the Red Matrix.'), + '$visit' => t('Please visit <a href="https://redmatrix.me">RedMatrix.me</a> to learn more about the Red Matrix.'), '$bug_text' => t('Bug reports and issues: please visit'), '$bug_link_url' => 'https://github.com/friendica/red/issues', '$bug_link_text' => 'redmatrix issues', diff --git a/mod/sitelist.php b/mod/sitelist.php index 1e6d0fcfb..95cf862df 100644 --- a/mod/sitelist.php +++ b/mod/sitelist.php @@ -18,6 +18,12 @@ function sitelist_init(&$a) { if($open) $sql_extra = " and site_register = " . intval(REGISTER_OPEN) . " "; + $realm = get_directory_realm(); + if($realm == DIRECTORY_REALM) { + $sql_extra .= " and ( site_realm = '" . dbesc($realm) . "' or site_realm = '') "; + } + else + $sql_extra .= " and site_realm = '" . dbesc($realm) . "' "; $result = array('success' => false); diff --git a/mod/smilies.php b/mod/smilies.php index c47f95da7..b22d0c6d2 100644 --- a/mod/smilies.php +++ b/mod/smilies.php @@ -1,3 +1,15 @@ <?php -function smilies_content(&$a) { return smilies('',true); } +function smilies_content(&$a) { + if ($a->argv[1]==="json"){ + $tmp = list_smilies(); + $results = array(); + for($i = 0; $i < count($tmp['texts']); $i++) { + $results[] = array('text' => $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]); + } + json_return_and_die($results); + } + else { + return smilies('',true); + } +} diff --git a/mod/sources.php b/mod/sources.php index f4b36508f..73d78bbbf 100644 --- a/mod/sources.php +++ b/mod/sources.php @@ -47,7 +47,7 @@ function sources_post(&$a) { goaway(z_root() . '/sources'); } else { - $r = q("update source set src_xchan = '%s', src_patt = '%s' where src_channel_id = %d and src_id = %d limit 1", + $r = q("update source set src_xchan = '%s', src_patt = '%s' where src_channel_id = %d and src_id = %d", dbesc($xchan), dbesc($words), intval(local_user()), @@ -150,7 +150,7 @@ function sources_content(&$a) { notice( t('Source not found.') . EOL); return ''; } - $r = q("delete from source where src_id = %d and src_channel_id = %d limit 1", + $r = q("delete from source where src_id = %d and src_channel_id = %d", intval(argv(1)), intval(local_user()) ); diff --git a/mod/sslify.php b/mod/sslify.php index ed06d87c1..f37a8e23e 100644 --- a/mod/sslify.php +++ b/mod/sslify.php @@ -3,7 +3,7 @@ function sslify_init(&$a) { $x = z_fetch_url($_REQUEST['url']); if($x['success']) { - $h = explode("\n",$x['headers']); + $h = explode("\n",$x['header']); foreach ($h as $l) { list($k,$v) = array_map("trim", explode(":", trim($l), 2)); $hdrs[$k] = $v; diff --git a/mod/starred.php b/mod/starred.php index ca7621b0f..05b45bea3 100644 --- a/mod/starred.php +++ b/mod/starred.php @@ -21,7 +21,7 @@ function starred_init(&$a) { $item_flags = ( $r[0]['item_flags'] ^ ITEM_STARRED ); - $r = q("UPDATE item SET item_flags = %d WHERE uid = %d and id = %d LIMIT 1", + $r = q("UPDATE item SET item_flags = %d WHERE uid = %d and id = %d", intval($item_flags), intval(local_user()), intval($message_id) diff --git a/mod/subthread.php b/mod/subthread.php index 5ef0615b1..f0f54f4a6 100755 --- a/mod/subthread.php +++ b/mod/subthread.php @@ -228,7 +228,7 @@ EOT; $post_id = $post['item_id']; if(! $item['visible']) { - $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d", intval($item['id']), intval($owner_uid) ); diff --git a/mod/tagrm.php b/mod/tagrm.php index 957cf0d71..38787cb0b 100644 --- a/mod/tagrm.php +++ b/mod/tagrm.php @@ -19,24 +19,27 @@ function tagrm_post(&$a) { intval(local_user()) ); - if(! count($r)) + if(! $r) goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); - $arr = explode(',', $r[0]['tag']); - for($x = 0; $x < count($arr); $x ++) { - if($arr[$x] === $tag) { - unset($arr[$x]); - break; + $r = fetch_post_tags($r,true); + + $item = $r[0]; + $new_tags = array(); + + if($item['term']) { + for($x = 0; $x < count($item['term']); $x ++) { + if($item['term'][$x]['term'] !== hex2bin($tag)) + $new_tags[] = $item['term'][$x]; } } - $tag_str = implode(',',$arr); + if($new_tags) + $item['term'] = $new_tags; + else + unset($item['term']); - q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", - dbesc($tag_str), - intval($item), - intval(local_user()) - ); + item_store_update($item); info( t('Tag removed') . EOL ); goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); @@ -49,51 +52,90 @@ function tagrm_post(&$a) { function tagrm_content(&$a) { - $o = ''; - if(! local_user()) { goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); // NOTREACHED } - $item = (($a->argc > 1) ? intval($a->argv[1]) : 0); - if(! $item) { + // remove tag on the fly if item and tag are provided + if((argc() == 4) && (argv(1) === 'drop') && intval(argv(2))) { + + $item = intval(argv(2)); + $tag = argv(3); + + $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", + intval($item), + intval(local_user()) + ); + + if(! $r) + goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); + + $r = fetch_post_tags($r,true); + + $item = $r[0]; + + $new_tags = array(); + + if($item['term']) { + for($x = 0; $x < count($item['term']); $x ++) { + if($item['term'][$x]['term'] !== hex2bin($tag)) + $new_tags[] = $item['term'][$x]; + } + } + + if($new_tags) + $item['term'] = $new_tags; + else + unset($item['term']); + + item_store_update($item); + + info( t('Tag removed') . EOL ); goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); - // NOTREACHED + } + //if we got only the item print a list of tags to select + if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { - $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", - intval($item), - intval(local_user()) - ); + $o = ''; - if(! count($r)) - goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); + $item = intval(argv(2)); - $arr = explode(',', $r[0]['tag']); + $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", + intval($item), + intval(local_user()) + ); - if(! count($arr)) - goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); + if(! $r) + goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); - $o .= '<h3>' . t('Remove Item Tag') . '</h3>'; + $r = fetch_post_tags($r,true); - $o .= '<p id="tag-remove-desc">' . t('Select a tag to remove: ') . '</p>'; + if(! count($r[0]['term'])) + goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); - $o .= '<form id="tagrm" action="tagrm" method="post" >'; - $o .= '<input type="hidden" name="item" value="' . $item . '" />'; - $o .= '<ul>'; + $o .= '<h3>' . t('Remove Item Tag') . '</h3>'; + $o .= '<p id="tag-remove-desc">' . t('Select a tag to remove: ') . '</p>'; - foreach($arr as $x) { - $o .= '<li><input type="checkbox" name="tag" value="' . bin2hex($x) . '" >' . bbcode($x) . '</input></li>'; - } + $o .= '<form id="tagrm" action="tagrm" method="post" >'; + $o .= '<input type="hidden" name="item" value="' . $item . '" />'; + $o .= '<ul>'; - $o .= '</ul>'; - $o .= '<input id="tagrm-submit" type="submit" name="submit" value="' . t('Remove') .'" />'; - $o .= '<input id="tagrm-cancel" type="submit" name="submit" value="' . t('Cancel') .'" />'; - $o .= '</form>'; - return $o; + foreach($r[0]['term'] as $x) { + $o .= '<li><input type="checkbox" name="tag" value="' . bin2hex($x['term']) . '" >' . bbcode($x['term']) . '</input></li>'; + } + + $o .= '</ul>'; + $o .= '<input id="tagrm-submit" type="submit" name="submit" value="' . t('Remove') .'" />'; + $o .= '<input id="tagrm-cancel" type="submit" name="submit" value="' . t('Cancel') .'" />'; + $o .= '</form>'; + + return $o; + + } } diff --git a/mod/thing.php b/mod/thing.php index b6d59a3ee..f53a6ab7b 100644 --- a/mod/thing.php +++ b/mod/thing.php @@ -67,8 +67,6 @@ function thing_init(&$a) { - - if($term_hash) { $t = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", intval(TERM_OBJ_THING), @@ -87,7 +85,7 @@ function thing_init(&$a) { else $local_photo = $orig_record['imgurl']; - $r = q("update term set term = '%s', url = '%s', imgurl = '%s' where term_hash = '%s' and uid = %d limit 1", + $r = q("update term set term = '%s', url = '%s', imgurl = '%s' where term_hash = '%s' and uid = %d", dbesc($name), dbesc(($url) ? $url : z_root() . '/thing/' . $term_hash), dbesc($local_photo), @@ -303,12 +301,12 @@ function thing_content(&$a) { } - $x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d limit 1", + $x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d", dbesc($thing_hash), intval(TERM_OBJ_THING), intval(local_user()) ); - $x = q("delete from term where term_hash = '%s' and uid = %d limit 1", + $x = q("delete from term where term_hash = '%s' and uid = %d", dbesc($thing_hash), intval(local_user()) ); @@ -321,7 +319,7 @@ function thing_content(&$a) { '$profile_lbl' => t('Select a profile'), '$profile_select' => contact_profile_assign(''), '$verb_lbl' => $channel['channel_name'], - '$activity' => array('activity',t('Post an activity'),true,t('Only sends to viewers of the applicable profile')), + '$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_REQUEST)) ? $_REQUEST['activity'] : true),t('Only sends to viewers of the applicable profile')), '$verb_select' => obj_verb_selector(), '$thing_lbl' => t('Name of thing e.g. something'), '$url_lbl' => t('URL of thing (optional)'), diff --git a/mod/uexport.php b/mod/uexport.php index f3a2ce67c..250a001a2 100644 --- a/mod/uexport.php +++ b/mod/uexport.php @@ -4,22 +4,37 @@ function uexport_init(&$a) { if(! local_user()) killme(); - $channel = $a->get_channel(); + if(argc() > 1) { + $channel = $a->get_channel(); - require_once('include/identity.php'); + require_once('include/identity.php'); - header('content-type: application/octet_stream'); - header('content-disposition: attachment; filename="' . $channel['channel_address'] . '.json"' ); + header('content-type: application/octet_stream'); + header('content-disposition: attachment; filename="' . $channel['channel_address'] . '.json"' ); - if(argc() > 1 && argv(1) === 'basic') { - echo json_encode(identity_basic_export(local_user())); - killme(); - } + if(argc() > 1 && argv(1) === 'basic') { + echo json_encode(identity_basic_export(local_user())); + killme(); + } - if(argc() > 1 && argv(1) === 'complete') { - echo json_encode('not yet implemented'); - killme(); + // FIXME - this basically doesn't work in the wild with a channel more than a few months old due to memory and execution time limits. + // It probably needs to be built at the CLI and offered to download as a tarball. Maybe stored in the members dav. + + if(argc() > 1 && argv(1) === 'complete') { + echo json_encode(identity_basic_export(local_user(),true)); + killme(); + } } +} -}
\ No newline at end of file +function uexport_content(&$a) { + $o = replace_macros(get_markup_template('uexport.tpl'), array( + '$title' => t('Export Channel'), + '$basictitle' => t('Export Channel'), + '$basic' => t('Export your basic channel information to a small file. This acts as a backup of your connections, permissions, profile and basic data, which can be used to import your data to a new hub, but does not contain your content.'), + '$fulltitle' => t('Export Content'), + '$full' => t('Export your channel information and all the content to a JSON backup. This backs up all of your connections, permissions, profile data and all of your content, but is generally not suitable for importing a channel to a new hub as this file may be VERY large. Please be patient - it may take several minutes for this download to begin.') + )); +return $o; +} diff --git a/mod/update_home.php b/mod/update_home.php new file mode 100644 index 000000000..c139682e1 --- /dev/null +++ b/mod/update_home.php @@ -0,0 +1,38 @@ +<?php + +// See update_profile.php for documentation + +require_once('mod/home.php'); + +function update_home_content(&$a) { + + $profile_uid = ((intval($_GET['p'])) ? intval($_GET['p']) : (-1)); + $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0); + header("Content-type: text/html"); + echo "<!DOCTYPE html><html><body>\r\n"; + echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>'); + + $text = home_content($a,$profile_uid, $load); + $pattern = "/<img([^>]*) src=\"([^\"]*)\"/"; + $replace = "<img\${1} dst=\"\${2}\""; + $text = preg_replace($pattern, $replace, $text); + + if(! $load) { + $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />'; + $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i"; + $text = preg_replace($pattern, $replace, $text); + $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i"; + $text = preg_replace($pattern, $replace, $text); + $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i"; + $text = preg_replace($pattern, $replace, $text); + $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i"; + $text = preg_replace($pattern, $replace, $text); + } + + echo str_replace("\t",' ',$text); + echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>'); + echo "</body></html>\r\n"; +// logger('update_home: ' . $text); + killme(); + +}
\ No newline at end of file diff --git a/mod/viewconnections.php b/mod/viewconnections.php index 40ce28efe..40d26c823 100644 --- a/mod/viewconnections.php +++ b/mod/viewconnections.php @@ -37,7 +37,7 @@ function viewconnections_content(&$a) { $xchan_flags = $xchan_flags | XCHAN_FLAGS_HIDDEN; } - $r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and not (abook_flags & %d ) and not ( xchan_flags & %d ) ", + $r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and not (abook_flags & %d )>0 and not ( xchan_flags & %d )>0 ", intval($a->profile['uid']), intval($abook_flags), intval($xchan_flags) @@ -46,12 +46,12 @@ function viewconnections_content(&$a) { $a->set_pager_total($r[0]['total']); } - $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and not ( abook_flags & %d ) and not ( xchan_flags & %d ) order by xchan_name LIMIT %d , %d ", + $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and not ( abook_flags & %d )>0 and not ( xchan_flags & %d )>0 order by xchan_name LIMIT %d OFFSET %d ", intval($a->profile['uid']), intval($abook_flags), intval($xchan_flags), - intval($a->pager['start']), - intval($a->pager['itemspage']) + intval($a->pager['itemspage']), + intval($a->pager['start']) ); if(! $r) { diff --git a/mod/viewsrc.php b/mod/viewsrc.php index 0f4df9b9b..982d1c417 100644 --- a/mod/viewsrc.php +++ b/mod/viewsrc.php @@ -5,6 +5,8 @@ function viewsrc_content(&$a) { $o = ''; + $sys = get_sys_channel(); + $item_id = ((argc() > 1) ? intval(argv(1)) : 0); $json = ((argc() > 2 && argv(2) === 'json') ? true : false); @@ -19,13 +21,17 @@ function viewsrc_content(&$a) { } if(local_user() && $item_id) { - $r = q("select body from item where item_restrict = 0 and uid = %d and id = %d limit 1", + $r = q("select item_flags, body from item where item_restrict = 0 and uid in (%d , %d) and id = %d limit 1", intval(local_user()), + intval($sys['channel_id']), intval($item_id) ); - if($r) + if($r) { + if($r[0]['item_flags'] & ITEM_OBSCURED) + $r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'],true),get_config('system','prvkey')); $o = (($json) ? json_encode($r[0]['body']) : str_replace("\n",'<br />',$r[0]['body'])); + } } if(is_ajax()) { diff --git a/mod/wall_upload.php b/mod/wall_upload.php index f83f4f7cf..7ed1859a8 100644 --- a/mod/wall_upload.php +++ b/mod/wall_upload.php @@ -8,6 +8,7 @@ require_once('include/photos.php'); function wall_upload_post(&$a) { + $using_api = ((x($_FILES,'media')) ? true : false); if($using_api) { @@ -43,10 +44,6 @@ function wall_upload_post(&$a) { killme(); } - $m = $ret['body']; - - - if($using_api) return("\n\n" . $ret['body'] . "\n\n"); else diff --git a/mod/webpages.php b/mod/webpages.php index 431caa628..baddebec8 100644 --- a/mod/webpages.php +++ b/mod/webpages.php @@ -1,37 +1,64 @@ <?php -function webpages_content(&$a) { +require_once('include/identity.php'); +require_once('include/conversation.php'); +require_once('include/acl_selectors.php'); + +function webpages_init(&$a) { + + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } if(argc() > 1) $which = argv(1); - else { + else + return; + + profile_load($a,$which); + +} + + +function webpages_content(&$a) { + + if(! $a->profile) { notice( t('Requested profile is not available.') . EOL ); $a->error = 404; return; } - $profile = 0; - $channel = $a->get_channel(); - - if((local_user()) && (argc() > 2) && (argv(2) === 'view')) { - $which = $channel['channel_address']; - $profile = argv(1); - } + $which = argv(1); - profile_load($a,$which,$profile); + $uid = local_user(); + $owner = 0; + $channel = null; + $observer = $a->get_observer(); + $channel = $a->get_channel(); - // Figure out who the page owner is. - $r = q("select channel_id from channel where channel_address = '%s'", - dbesc($which) - ); - if($r) { - $owner = intval($r[0]['channel_id']); + if($a->is_sys && is_site_admin()) { + $sys = get_sys_channel(); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } } - // Get the observer, check their permissions + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) + ); + if($r) { + $owner = intval($r[0]['channel_id']); + } + } - $observer = $a->get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); $perms = get_all_perms($owner,$ob_hash); @@ -41,28 +68,30 @@ function webpages_content(&$a) { return; } -// if(local_user() && local_user() == $owner) { -// $a->set_widget('design',design_tools()); -// } - - - $mimetype = get_config('system','page_mimetype'); - if(! $mimetype) - $mimetype = 'choose'; + if(feature_enabled($owner,'expert')) { + $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); + if(! $mimetype) + $mimetype = 'choose'; + } + else { + $mimetype = 'text/bbcode'; + } - $layout = get_config('system','page_layout'); + $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout')); if(! $layout) $layout = 'choose'; -// Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages -// Nickname is set to the observers xchan, and profile_uid to the owners. This lets you post pages at other people's channels. - require_once ('include/conversation.php'); - require_once('include/acl_selectors.php'); + // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages + // Nickname is set to the observers xchan, and profile_uid to the owner's. + // This lets you post pages at other people's channels. + - if(local_user() && local_user() == $a->profile_uid) { + if((! $channel) && ($uid) && ($uid == $a->profile_uid)) { $channel = $a->get_channel(); + } + if($channel) { $channel_acl = array( 'allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], @@ -73,31 +102,37 @@ function webpages_content(&$a) { else $channel_acl = array(); - require_once('include/conversation.php'); - $o = profile_tabs($a,true); - $o .= '<h2>' . t('Webpages') . '</h2>'; + $o = profile_tabs($a,true); $x = array( - 'webpage' => ITEM_WEBPAGE, - 'is_owner' => true, - 'nickname' => $a->profile['channel_address'], - 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'bang' => (($group || $cid) ? '!' : ''), - 'acl' => ((local_user() && local_user() == $owner) ? populate_acl($channel_acl,false) : ''), - 'visitor' => true, + 'webpage' => ITEM_WEBPAGE, + 'is_owner' => true, + 'nickname' => $a->profile['channel_address'], + 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'bang' => '', + 'acl' => (($uid && $uid == $owner) ? populate_acl($channel_acl,false) : ''), + 'visitor' => true, 'profile_uid' => intval($owner), - 'mimetype' => $mimetype, - 'layout' => $layout, + 'mimetype' => $mimetype, + 'layout' => $layout, ); + + if($_REQUEST['title']) + $x['title'] = $_REQUEST['title']; + if($_REQUEST['body']) + $x['body'] = $_REQUEST['body']; + if($_REQUEST['pagetitle']) + $x['pagetitle'] = $_REQUEST['pagetitle']; $o .= status_editor($a,$x); - - // Get a list of webpages. We can't display all them because endless scroll makes that unusable, so just list titles and an edit link. + // Get a list of webpages. We can't display all them because endless scroll makes that unusable, + // so just list titles and an edit link. //TODO - this should be replaced with pagelist_widget - $r = q("select * from item_id left join item on item_id.iid = item.id where item_id.uid = %d and service = 'WEBPAGE' order by item.created desc", + $r = q("select * from item_id left join item on item_id.iid = item.id + where item_id.uid = %d and service = 'WEBPAGE' order by item.created desc", intval($owner) ); @@ -107,28 +142,36 @@ function webpages_content(&$a) { $pages = array(); foreach($r as $rr) { unobscure($rr); - $pages[$rr['iid']][] = array('url' => $rr['iid'],'pagetitle' => $rr['sid'],'title' => $rr['title'],'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited'])); + $pages[$rr['iid']][] = array( + 'url' => $rr['iid'], + 'pagetitle' => $rr['sid'], + 'title' => $rr['title'], + 'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']), + 'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']) + ); } } -//Build the base URL for edit links - $url = z_root() . "/editwebpage/" . $which; -// This isn't pretty, but it works. Until I figure out what to do with the UI, it's Good Enough(TM). - return $o . replace_macros(get_markup_template("webpagelist.tpl"), array( - '$baseurl' => $url, - '$edit' => t('Edit'), - '$pages' => $pages, - '$channel' => $which, - '$view' => t('View'), - '$preview' => t('Preview'), - '$actions_txt' => t('Actions'), + //Build the base URL for edit links + $url = z_root() . '/editwebpage/' . $which; + + $o .= replace_macros(get_markup_template('webpagelist.tpl'), array( + '$listtitle' => t('Webpages'), + '$baseurl' => $url, + '$edit' => t('Edit'), + '$pages' => $pages, + '$channel' => $which, + '$view' => t('View'), + '$preview' => t('Preview'), + '$actions_txt' => t('Actions'), '$pagelink_txt' => t('Page Link'), - '$title_txt' => t('Title'), - '$created_txt' => t('Created'), - '$edited_txt' => t('Edited') + '$title_txt' => t('Title'), + '$created_txt' => t('Created'), + '$edited_txt' => t('Edited') -)); + )); + return $o; } diff --git a/mod/xchan.php b/mod/xchan.php index 9d4cdcc22..69fbdb77d 100644 --- a/mod/xchan.php +++ b/mod/xchan.php @@ -3,28 +3,39 @@ function xchan_content(&$a) { - - $o .= '<h3>Xchan Lookup</h3>'; + $o = '<h3>' . t('Xchan Lookup') . '</h3>'; $o .= '<form action="xchan" method="get">'; - $o .= 'Lookup xchan beginning with: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />'; - $o .= '<input type="submit" name="submit" value="Submit" /></form>'; - - $o .= '<br /><br />'; + $o .= t('Lookup xchan beginning with (or webbie): '); + $o .= '<input type="text" style="width:250px;" name="addr" value="' . $_GET['addr'] .'">'; + $o .= '<input type="submit" name="submit" value="' . t('Submit') .'"></form>'; + $o .= '<br><br>'; - if(x($_GET,'addr')) { + if(x($_GET, 'addr')) { $addr = trim($_GET['addr']); - $r = q("select xchan_name from xchan where xchan_hash like '%s%%'", + $r = q("select * from xchan where xchan_hash like '%s%%' or xchan_addr = '%s' group by xchan_hash", + dbesc($addr), dbesc($addr) ); if($r) { - foreach($r as $rr) - $o .= $rr['xchan_name'] . EOL; + foreach($r as $rr) { + $o .= str_replace(array("\n", " "), array("<br>", " "), print_r($rr, true)) . EOL; + + $s = q("select * from hubloc where hubloc_hash like '%s'", + dbesc($r[0]['xchan_hash']) + ); + + if($s) { + foreach($s as $rrr) + $o .= str_replace(array("\n", " "), array("<br>", " "), print_r($rrr, true)) . EOL; + } + } } else notice( t('Not found.') . EOL); + } return $o; } diff --git a/mod/xrd.php b/mod/xrd.php index 4d6a530e4..4fa81c7f3 100644 --- a/mod/xrd.php +++ b/mod/xrd.php @@ -22,7 +22,13 @@ function xrd_init(&$a) { if(! $r) killme(); -// $salmon_key = salmon_key($r[0]['pubkey']); + $dspr = replace_macros(get_markup_template('xrd_diaspora.tpl'),array( + '$baseurl' => $a->get_baseurl(), + '$dspr_guid' => $r[0]['channel_guid'], + '$dspr_key' => base64_encode(pemtorsa($r[0]['channel_pubkey'])) + )); + + $salmon_key = salmon_key($r[0]['channel_pubkey']); header('Access-Control-Allow-Origin: *'); header("Content-type: text/xml"); @@ -34,15 +40,15 @@ function xrd_init(&$a) { '$nick' => $r[0]['channel_address'], '$accturi' => $uri, '$profile_url' => $a->get_baseurl() . '/channel/' . $r[0]['channel_address'], -// '$hcard_url' => $a->get_baseurl() . '/hcard/' . $r[0]['channel_address'], + '$hcard_url' => $a->get_baseurl() . '/hcard/' . $r[0]['channel_address'], '$atom' => $a->get_baseurl() . '/feed/' . $r[0]['channel_address'], '$zot_post' => $a->get_baseurl() . '/post/' . $r[0]['channel_address'], '$poco_url' => $a->get_baseurl() . '/poco/' . $r[0]['channel_address'], '$photo' => $a->get_baseurl() . '/photo/profile/l/' . $r[0]['channel_id'], -// '$dspr' => $dspr, + '$dspr' => $dspr, // '$salmon' => $a->get_baseurl() . '/salmon/' . $r[0]['channel_address'], // '$salmen' => $a->get_baseurl() . '/salmon/' . $r[0]['channel_address'] . '/mention', -// '$modexp' => 'data:application/magic-public-key,' . $salmon_key, + '$modexp' => 'data:application/magic-public-key,' . $salmon_key, // '$bigkey' => salmon_key($r[0]['pubkey']) )); diff --git a/mod/zfinger.php b/mod/zfinger.php index d1493da03..6f4febc6f 100644 --- a/mod/zfinger.php +++ b/mod/zfinger.php @@ -74,12 +74,12 @@ function zfinger_init(&$a) { */ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where ( channel_pageflags & %d ) order by channel_id limit 1", + where ( channel_pageflags & %d )>0 order by channel_id limit 1", intval(PAGE_SYSTEM) ); if(! $r) { $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where not ( channel_pageflags & %d ) order by channel_id limit 1", + where not ( channel_pageflags & %d )>0 order by channel_id limit 1", intval(PAGE_REMOVED) ); } @@ -108,6 +108,21 @@ function zfinger_init(&$a) { if($deleted || $censored) $searchable = false; + $public_forum = false; + + $role = get_pconfig($e['channel_id'],'system','permissions_role'); + if($role === 'forum') { + $public_forum = true; + } + else { + // check if it has characteristics of a public forum based on custom permissions. + $t = q("select abook_my_perms from abook where abook_channel = %d and (abook_flags & %d)>0 limit 1", + intval($e['channel_id']), + intval(ABOOK_FLAG_SELF) + ); + if($t && ($t[0]['abook_my_perms'] & PERMS_W_TAGWALL)) + $public_forum = true; + } // This is for birthdays and keywords, but must check access permissions @@ -174,6 +189,7 @@ function zfinger_init(&$a) { $ret['target_sig'] = $zsig; $ret['searchable'] = $searchable; $ret['adult_content'] = $adult_channel; + $ret['public_forum'] = $public_forum; if($deleted) $ret['deleted'] = $deleted; @@ -203,33 +219,16 @@ function zfinger_init(&$a) { $permissions['connected'] = true; } - $ret['permissions'] = (($ztarget && $zkey) ? aes_encapsulate(json_encode($permissions),$zkey) : $permissions); + $ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey) : $permissions); if($permissions['view_profile']) $ret['profile'] = $profile; - // array of (verified) hubs this channel uses - $ret['locations'] = array(); - - $x = zot_get_hublocs($e['channel_hash']); - if($x && count($x)) { - foreach($x as $hub) { - if(! ($hub['hubloc_flags'] & HUBLOC_FLAGS_UNVERIFIED)) { - $ret['locations'][] = array( - 'host' => $hub['hubloc_host'], - 'address' => $hub['hubloc_addr'], - 'primary' => (($hub['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) ? true : false), - 'url' => $hub['hubloc_url'], - 'url_sig' => $hub['hubloc_url_sig'], - 'callback' => $hub['hubloc_callback'], - 'sitekey' => $hub['hubloc_sitekey'], - 'deleted' => (($hub['hubloc_flags'] & HUBLOC_FLAGS_DELETED) ? true : false) - ); - } - } - } + $x = zot_encode_locations($e); + if($x) + $ret['locations'] = $x; $ret['site'] = array(); $ret['site']['url'] = z_root(); @@ -273,7 +272,6 @@ function zfinger_init(&$a) { if($access_policy == ACCESS_TIERED) $ret['site']['access_policy'] = 'tiered'; - require_once('include/account.php'); $ret['site']['accounts'] = account_total(); require_once('include/identity.php'); @@ -297,6 +295,7 @@ function zfinger_init(&$a) { $ret['site']['sitename'] = get_config('system','sitename'); $ret['site']['sellpage'] = get_config('system','sellpage'); $ret['site']['location'] = get_config('system','site_location'); + $ret['site']['realm'] = get_directory_realm(); } call_hooks('zot_finger',$ret); diff --git a/mod/zotfeed.php b/mod/zotfeed.php index 480e886cd..9ad93c1d4 100644 --- a/mod/zotfeed.php +++ b/mod/zotfeed.php @@ -21,7 +21,7 @@ function zotfeed_init(&$a) { $channel_address = ((argc() > 1) ? argv(1) : ''); if($channel_address) { - $r = q("select channel_id, channel_name from channel where channel_address = '%s' and not (channel_pageflags & %d) limit 1", + $r = q("select channel_id, channel_name from channel where channel_address = '%s' and not (channel_pageflags & %d)>0 limit 1", dbesc(argv(1)), intval(PAGE_REMOVED) ); @@ -38,7 +38,7 @@ function zotfeed_init(&$a) { logger('zotfeed request: ' . $r[0]['channel_name'], LOGGER_DEBUG); - $result['messages'] = zot_feed($r[0]['channel_id'],$observer['xchan_hash'],$mindate); + $result['messages'] = zot_feed($r[0]['channel_id'],$observer['xchan_hash'],array('mindate' => $mindate)); $result['success'] = true; json_return_and_die($result); |