diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/Contact.php | 19 | ||||
-rw-r--r-- | include/ItemObject.php | 1 | ||||
-rw-r--r-- | include/acl_selectors.php | 2 | ||||
-rw-r--r-- | include/api.php | 3 | ||||
-rw-r--r-- | include/attach.php | 15 | ||||
-rw-r--r-- | include/bbcode.php | 11 | ||||
-rw-r--r-- | include/contact_widgets.php | 3 | ||||
-rw-r--r-- | include/conversation.php | 15 | ||||
-rw-r--r-- | include/crypto.php | 4 | ||||
-rw-r--r-- | include/deliver.php | 1 | ||||
-rw-r--r-- | include/dir_fns.php | 11 | ||||
-rw-r--r-- | include/enotify.php | 9 | ||||
-rw-r--r-- | include/event.php | 20 | ||||
-rw-r--r-- | include/features.php | 9 | ||||
-rw-r--r-- | include/group.php | 26 | ||||
-rw-r--r-- | include/identity.php | 127 | ||||
-rwxr-xr-x | include/items.php | 93 | ||||
-rw-r--r-- | include/nav.php | 4 | ||||
-rw-r--r-- | include/network.php | 4 | ||||
-rw-r--r-- | include/photo/photo_driver.php | 54 | ||||
-rw-r--r-- | include/photos.php | 19 | ||||
-rwxr-xr-x | include/plugin.php | 42 | ||||
-rw-r--r-- | include/reddav.php | 424 | ||||
-rw-r--r-- | include/security.php | 2 | ||||
-rw-r--r-- | include/taxonomy.php | 95 | ||||
-rwxr-xr-x | include/text.php | 61 | ||||
-rw-r--r-- | include/widgets.php | 282 | ||||
-rw-r--r-- | include/zot.php | 48 |
28 files changed, 1133 insertions, 271 deletions
diff --git a/include/Contact.php b/include/Contact.php index 5725e06f0..fd450033c 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -77,6 +77,23 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') { $a = get_app(); + if(! $xchan) { + if($a->poi) { + $xchan = $a->poi; + } + elseif($a->profile['channel_hash']) { + $r = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($a->profile['channel_hash']) + ); + if($r) + $xchan = $r[0]; + } + } + + if(! $xchan) + return; + +// FIXME - show connect button to observer if appropriate $connect = false; if(local_user()) { $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", @@ -238,7 +255,7 @@ function channel_remove($channel_id, $local = true) { } - q("DELETE FROM `group` WHERE `uid` = %d", intval($channel_id)); + q("DELETE FROM `groups` WHERE `uid` = %d", intval($channel_id)); q("DELETE FROM `group_member` WHERE `uid` = %d", intval($channel_id)); q("DELETE FROM `event` WHERE `uid` = %d", intval($channel_id)); q("DELETE FROM `item` WHERE `uid` = %d", intval($channel_id)); diff --git a/include/ItemObject.php b/include/ItemObject.php index 6088a2c1c..170f013a1 100644 --- a/include/ItemObject.php +++ b/include/ItemObject.php @@ -217,6 +217,7 @@ class Item extends BaseObject { 'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'), 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'), 'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''), + 'expiretime' => (($item['expires'] > 0) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''), 'lock' => $lock, 'verified' => $verified, 'unverified' => $unverified, diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 930f9967a..749ca75eb 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -14,7 +14,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) { $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n"; - $r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC", + $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC", intval(local_user()) ); diff --git a/include/api.php b/include/api.php index 093839875..463d29cf8 100644 --- a/include/api.php +++ b/include/api.php @@ -362,7 +362,8 @@ require_once('include/photos.php'); 'location' => ($usr) ? $usr[0]['channel_location'] : '', 'profile_image_url' => $uinfo[0]['xchan_photo_l'], 'url' => $uinfo[0]['xchan_url'], - 'contact_url' => $a->get_baseurl()."/connections/".$uinfo[0]['abook_id'], +//FIXME + 'contact_url' => $a->get_baseurl() . "/connections/".$uinfo[0]['abook_id'], 'protected' => false, 'friends_count' => intval($countfriends), 'created_at' => api_date($uinfo[0]['abook_created']), diff --git a/include/attach.php b/include/attach.php index 0c748cba6..3eb7a9366 100644 --- a/include/attach.php +++ b/include/attach.php @@ -79,17 +79,12 @@ function z_mime_content_type($filename) { if (array_key_exists($ext, $mime_types)) { return $mime_types[$ext]; } + + } -// can't use this because we're just passing a name, e.g. not a file that can be opened -// elseif (function_exists('finfo_open')) { -// $finfo = @finfo_open(FILEINFO_MIME); -// $mimetype = @finfo_file($finfo, $filename); -// @finfo_close($finfo); -// return $mimetype; -// } - else { - return 'application/octet-stream'; - } + + return 'application/octet-stream'; + } diff --git a/include/bbcode.php b/include/bbcode.php index 271cace73..6374675f1 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -105,21 +105,24 @@ function bb_parse_crypt($match) { $attributes = $match[1]; $algorithm = ""; + preg_match("/alg='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") - $algorithm = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8'); + $algorithm = $matches[1]; preg_match("/alg=\"\;(.*?)\"\;/ism", $attributes, $matches); if ($matches[1] != "") - $algorithm = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8'); + $algorithm = $matches[1]; $hint = ""; + + preg_match("/hint='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") - $hint = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8'); + $hint = $matches[1]; preg_match("/hint=\"\;(.*?)\"\;/ism", $attributes, $matches); if ($matches[1] != "") - $hint = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8'); + $hint = $matches[1]; $x = random_string(); diff --git a/include/contact_widgets.php b/include/contact_widgets.php index cc0a3d617..482bbed78 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -25,7 +25,8 @@ function findpeople_widget() { '$suggest' => t('Channel Suggestions'), '$similar' => '', // FIXME and uncomment when mod/match working // t('Similar Interests'), '$random' => t('Random Profile'), - '$inv' => t('Invite Friends') + '$inv' => t('Invite Friends'), + '$loggedin' => local_user() )); } diff --git a/include/conversation.php b/include/conversation.php index f5fc9da93..99252027d 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -908,14 +908,14 @@ function item_photo_menu($item){ } $profile_link = z_root() . "/chanview/?f=&hash=" . $item['author_xchan']; - $pm_url = $a->get_baseurl($ssl_state) . '/message/new/?f=&hash=' . $item['author_xchan']; + $pm_url = $a->get_baseurl($ssl_state) . '/mail/new/?f=&hash=' . $item['author_xchan']; if($a->contacts && array_key_exists($item['author_xchan'],$a->contacts)) $contact = $a->contacts[$item['author_xchan']]; if($contact) { $poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $contact['abook_id']; - $contact_url = $a->get_baseurl($ssl_state) . '/connections/' . $contact['abook_id']; + $contact_url = $a->get_baseurl($ssl_state) . '/connedit/' . $contact['abook_id']; $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $contact['abook_id']; $clean_url = normalise_link($item['author-link']); @@ -1108,7 +1108,7 @@ function status_editor($a,$x,$popup=false) { '$shortsetloc' => t('set location'), '$noloc' => t('Clear browser location'), '$shortnoloc' => t('clear location'), - '$title' => ((x($x,'title')) ? htmlspecialchars($x['title']) : ''), + '$title' => ((x($x,'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''), '$placeholdertitle' => t('Set title'), '$catsenabled' => ((feature_enabled($x['profile_uid'],'categories') && (! $webpage)) ? 'categories' : ''), '$category' => "", @@ -1117,7 +1117,7 @@ function status_editor($a,$x,$popup=false) { '$permset' => t('Permission settings'), '$shortpermset' => t('permissions'), '$ptyp' => (($notes_cid) ? 'note' : 'wall'), - '$content' => ((x($x,'body')) ? htmlspecialchars($x['body']) : ''), + '$content' => ((x($x,'body')) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8') : ''), '$post_id' => '', '$baseurl' => $a->get_baseurl(true), '$defloc' => $x['default_location'], @@ -1142,6 +1142,8 @@ function status_editor($a,$x,$popup=false) { '$feature_encrypt' => ((feature_enabled($x['profile_uid'],'content_encrypt') && (! $webpage)) ? 'block' : 'none'), '$encrypt' => t('Encrypt text'), '$cipher' => $cipher, + '$expiryModalOK' => t('OK'), + '$expiryModalCANCEL' => t('Cancel'), )); @@ -1294,15 +1296,18 @@ function prepare_page($item) { $a = get_app(); $naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0); + $observer = $a->get_observer(); + $zid = ($observer['xchan_addr']); + if(array_key_exists('webpage',$a->layout) && array_key_exists('authored',$a->layout['webpage'])) { if($a->layout['webpage']['authored'] === 'none') $naked = 1; // ... other possible options } - return replace_macros(get_markup_template('page_display.tpl'),array( '$author' => (($naked) ? '' : $item['author']['xchan_name']), '$auth_url' => (($naked) ? '' : $item['author']['xchan_url']), + '$zid' => $zid, '$date' => (($naked) ? '' : datetime_convert('UTC',date_default_timezone_get(),$item['created'],'Y-m-d H:i')), '$title' => smilies(bbcode($item['title'])), '$body' => prepare_body($item,true) diff --git a/include/crypto.php b/include/crypto.php index e9372fbb4..33cdc10c0 100644 --- a/include/crypto.php +++ b/include/crypto.php @@ -4,6 +4,8 @@ function rsa_sign($data,$key,$alg = 'sha256') { if(! $key) return 'no key'; $sig = ''; + if(intval(OPENSSL_ALGO_SHA256) && $alg === 'sha256') + $alg = OPENSSL_ALGO_SHA256; openssl_sign($data,$sig,$key,$alg); return $sig; } @@ -13,6 +15,8 @@ function rsa_verify($data,$sig,$key,$alg = 'sha256') { if(! $key) return false; + if(intval(OPENSSL_ALGO_SHA256) && $alg === 'sha256') + $alg = OPENSSL_ALGO_SHA256; $verify = openssl_verify($data,$sig,$key,$alg); return $verify; } diff --git a/include/deliver.php b/include/deliver.php index b1314ce39..b0d15e1ef 100644 --- a/include/deliver.php +++ b/include/deliver.php @@ -26,6 +26,7 @@ function deliver_run($argv, $argc) { // If there is no outq_msg, this is a refresh_all message which does not require local handling if($r[0]['outq_msg']) { $msg = array('body' => json_encode(array('pickup' => array(array('notify' => json_decode($r[0]['outq_notify'],true),'message' => json_decode($r[0]['outq_msg'],true)))))); + zot_import($msg,z_root()); $r = q("delete from outq where outq_hash = '%s' limit 1", dbesc($argv[$x]) diff --git a/include/dir_fns.php b/include/dir_fns.php index 0c9a6bd9f..ab8b67985 100644 --- a/include/dir_fns.php +++ b/include/dir_fns.php @@ -22,7 +22,8 @@ function dir_sort_links() { function dir_safe_mode() { $observer = get_observer_hash(); - + if (! $observer) + return; if ($observer) $safe_mode = get_xconfig($observer,'directory','safe_mode'); if($safe_mode === '0') @@ -166,6 +167,10 @@ function syncdirs($uid) { $profile['region'] = $p[0]['region']; $profile['postcode'] = $p[0]['postal_code']; $profile['country'] = $p[0]['country_name']; + $profile['about'] = $p[0]['about']; + $profile['homepage'] = $p[0]['homepage']; + $profile['hometown'] = $p[0]['hometown']; + if($p[0]['keywords']) { $tags = array(); $k = explode(' ',$p[0]['keywords']); @@ -200,10 +205,10 @@ function syncdirs($uid) { } + $address = $p[0]['channel_address'] . '@' . get_app()->get_hostname(); if(perm_is_allowed($uid,'','view_profile')) { - import_directory_profile($hash,$profile); - + import_directory_profile($hash,$profile,$address,0); } else { // they may have made it private diff --git a/include/enotify.php b/include/enotify.php index 011a1cde2..49d690511 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -86,8 +86,8 @@ function notification($params) { $preamble = sprintf( t('%1$s, %2$s sent you a new private message at %3$s.'),$recip['channel_name'], $sender['xchan_name'],$sitename); $epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]'); $sitelink = t('Please visit %s to view and/or reply to your private messages.'); - $tsitelink = sprintf( $sitelink, $siteurl . '/message/' . $params['item']['id'] ); - $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/message/' . $params['item']['id'] . '">' . $sitename . '</a>'); + $tsitelink = sprintf( $sitelink, $siteurl . '/mail/' . $params['item']['id'] ); + $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>'); $itemlink = $siteurl . '/message/' . $params['item']['id']; } @@ -183,9 +183,6 @@ function notification($params) { $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $params['link']); - - // FIXME - check the item privacy - $private = false; $sitelink = t('Please visit %s to view and/or reply to the conversation.'); $tsitelink = sprintf( $sitelink, $siteurl ); @@ -455,6 +452,8 @@ function notification($params) { if(! $datarray['email_secure']) { switch($params['type']) { case NOTIFY_WALL: + case NOTIFY_TAGSELF: + case NOTIFY_POKE: case NOTIFY_COMMENT: if(! $private) break; diff --git a/include/event.php b/include/event.php index 7873de1ef..20c5de09c 100644 --- a/include/event.php +++ b/include/event.php @@ -15,7 +15,7 @@ function format_event_html($ev) { $o .= '<p class="summary event-summary">' . bbcode($ev['summary']) . '</p>' . "\r\n"; - $o .= '<p class="description event-description">' . bbcode($ev['desc']) . '</p>' . "\r\n"; + $o .= '<p class="description event-description">' . bbcode($ev['description']) . '</p>' . "\r\n"; $o .= '<p class="event-start">' . t('Starts:') . ' <abbr class="dtstart" title="' . datetime_convert('UTC','UTC',$ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )) @@ -52,8 +52,8 @@ function format_event_bbcode($ev) { if($ev['summary']) $o .= '[event-summary]' . $ev['summary'] . '[/event-summary]'; - if($ev['desc']) - $o .= '[event-description]' . $ev['desc'] . '[/event-description]'; + if($ev['description']) + $o .= '[event-description]' . $ev['description'] . '[/event-description]'; if($ev['start']) $o .= '[event-start]' . $ev['start'] . '[/event-start]'; @@ -75,7 +75,7 @@ function format_event_bbcode($ev) { function bbtovcal($s) { $o = ''; $ev = bbtoevent($s); - if($ev['desc']) + if($ev['description']) $o = format_event_html($ev); return $o; } @@ -90,7 +90,7 @@ function bbtoevent($s) { $ev['summary'] = $match[1]; $match = ''; if(preg_match("/\[event\-description\](.*?)\[\/event\-description\]/is",$s,$match)) - $ev['desc'] = $match[1]; + $ev['description'] = $match[1]; $match = ''; if(preg_match("/\[event\-start\](.*?)\[\/event\-start\]/is",$s,$match)) $ev['start'] = $match[1]; @@ -122,7 +122,7 @@ function ev_compare($a,$b) { $date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']); if($date_a === $date_b) - return strcasecmp($a['desc'],$b['desc']); + return strcasecmp($a['description'],$b['description']); return strcmp($date_a,$date_b); } @@ -178,7 +178,7 @@ function event_store($arr) { `start` = '%s', `finish` = '%s', `summary` = '%s', - `desc` = '%s', + `description` = '%s', `location` = '%s', `type` = '%s', `adjust` = %d, @@ -193,7 +193,7 @@ function event_store($arr) { dbesc($arr['start']), dbesc($arr['finish']), dbesc($arr['summary']), - dbesc($arr['desc']), + dbesc($arr['description']), dbesc($arr['location']), dbesc($arr['type']), intval($arr['adjust']), @@ -266,7 +266,7 @@ function event_store($arr) { $arr['mid'] = item_message_id(); - $r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary, `desc`,location,type, + $r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type, adjust,nofinish,allow_cid,allow_gid,deny_cid,deny_gid) VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' ) ", intval($arr['uid']), @@ -278,7 +278,7 @@ function event_store($arr) { dbesc($arr['start']), dbesc($arr['finish']), dbesc($arr['summary']), - dbesc($arr['desc']), + dbesc($arr['description']), dbesc($arr['location']), dbesc($arr['type']), intval($arr['adjust']), diff --git a/include/features.php b/include/features.php index 05206106a..1f83eb319 100644 --- a/include/features.php +++ b/include/features.php @@ -24,9 +24,11 @@ function get_features() { array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles')), array('webpages', t('Web Pages'), t('Provide managed web pages on your channel')), array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders')), - array('prettyphoto', t('Enhanced Photo Albums'), t('Enable photo album with enhanced features')), +// prettyphoto has licensing issues and will no longer be provided in core - +// in any event this setting should probably be a theme option or plugin +// array('prettyphoto', t('Enhanced Photo Albums'), t('Enable photo album with enhanced features')), //FIXME - needs a description, but how the hell do we explain this to normals? - array('sendzid', t('Extended Identity Sharing'), t(' ')), + array('sendzid', t('Extended Identity Sharing'), t('Share your identity with all websites on the internet. When disabled, identity is only shared with sites in the matrix.')), array('expert', t('Expert Mode'), t('Enable Expert Mode to provide advanced configuration options')), array('premium_channel', t('Premium Channel'), t('Allows you to set restrictions and terms on those that connect with your channel')), ), @@ -37,7 +39,7 @@ function get_features() { array('richtext', t('Richtext Editor'), t('Enable richtext editor')), array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them')), array('channel_sources', t('Channel Sources'), t('Automatically import channel content from other channels or feeds')), - array('content_encrypt', t('Even More Encryption'), t('Allow encryption of content end-to-end with a shared secret key')), + array('content_encrypt', t('Even More Encryption'), t('Allow optional encryption of content end-to-end with a shared secret key')), ), // Network Tools @@ -49,6 +51,7 @@ function get_features() { array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on')), array('new_tab', t('Network New Tab'), t('Enable tab to display all new Network activity')), array('affinity', t('Affinity Tool'), t('Filter stream activity by depth of relationships')), + array('suggest', t('Suggest Channels'), t('Show channel suggestions')), ), // Item tools diff --git a/include/group.php b/include/group.php index 8f690785d..cdd779df2 100644 --- a/include/group.php +++ b/include/group.php @@ -14,11 +14,11 @@ function group_add($uid,$name,$public = 0) { // access lists. What we're doing here is reviving the dead group, but old content which // was restricted to this group may now be seen by the new group members. - $z = q("SELECT * FROM `group` WHERE `id` = %d LIMIT 1", + $z = q("SELECT * FROM `groups` WHERE `id` = %d LIMIT 1", intval($r) ); if(count($z) && $z[0]['deleted']) { - $r = q("UPDATE `group` SET `deleted` = 0 WHERE `uid` = %d AND `name` = '%s' LIMIT 1", + $r = q("UPDATE `groups` SET `deleted` = 0 WHERE `uid` = %d AND `name` = '%s' LIMIT 1", intval($uid), dbesc($name) ); @@ -31,13 +31,13 @@ function group_add($uid,$name,$public = 0) { $dups = false; $hash = random_string() . $name; - $r = q("SELECT id FROM `group` WHERE hash = '%s' LIMIT 1", dbesc($hash)); + $r = q("SELECT id FROM `groups` WHERE hash = '%s' LIMIT 1", dbesc($hash)); if($r) $dups = true; } while($dups == true); - $r = q("INSERT INTO `group` ( hash, uid, visible, name ) + $r = q("INSERT INTO `groups` ( hash, uid, visible, name ) VALUES( '%s', %d, %d, '%s' ) ", dbesc($hash), intval($uid), @@ -53,7 +53,7 @@ function group_add($uid,$name,$public = 0) { function group_rmv($uid,$name) { $ret = false; if(x($uid) && x($name)) { - $r = q("SELECT id, hash FROM `group` WHERE `uid` = %d AND `name` = '%s' LIMIT 1", + $r = q("SELECT id, hash FROM `groups` WHERE `uid` = %d AND `name` = '%s' LIMIT 1", intval($uid), dbesc($name) ); @@ -104,7 +104,7 @@ function group_rmv($uid,$name) { ); // remove group - $r = q("UPDATE `group` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s' LIMIT 1", + $r = q("UPDATE `groups` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s' LIMIT 1", intval($uid), dbesc($name) ); @@ -119,7 +119,7 @@ function group_rmv($uid,$name) { function group_byname($uid,$name) { if((! $uid) || (! strlen($name))) return false; - $r = q("SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' LIMIT 1", + $r = q("SELECT * FROM `groups` WHERE `uid` = %d AND `name` = '%s' LIMIT 1", intval($uid), dbesc($name) ); @@ -132,7 +132,7 @@ function group_byname($uid,$name) { function group_rec_byhash($uid,$hash) { if((! $uid) || (! strlen($hash))) return false; - $r = q("SELECT * FROM `group` WHERE `uid` = %d AND `hash` = '%s' LIMIT 1", + $r = q("SELECT * FROM `groups` WHERE `uid` = %d AND `hash` = '%s' LIMIT 1", intval($uid), dbesc($hash) ); @@ -207,7 +207,7 @@ function mini_group_select($uid,$group = '') { $grps = array(); $o = ''; - $r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC", + $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC", intval($uid) ); $grps[] = array('name' => '', 'hash' => '0', 'selected' => ''); @@ -229,7 +229,7 @@ function mini_group_select($uid,$group = '') { -function group_side($every="contacts",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) { +function group_side($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) { $o = ''; @@ -246,7 +246,7 @@ function group_side($every="contacts",$each="group",$edit = false, $group_id = 0 ); - $r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC", + $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC", intval($_SESSION['uid']) ); $member_of = array(); @@ -302,7 +302,7 @@ function expand_groups($a) { $groups = implode(',', $x); if($groups) - $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from `group` where hash in ( $groups ))"); + $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from `groups` where hash in ( $groups ))"); $ret = array(); if($r) @@ -314,7 +314,7 @@ function expand_groups($a) { function member_of($c) { - $r = q("SELECT `group`.`name`, `group`.`id` FROM `group` LEFT JOIN `group_member` ON `group_member`.`gid` = `group`.`id` WHERE `group_member`.`xchan` = '%s' AND `group`.`deleted` = 0 ORDER BY `group`.`name` ASC ", + $r = q("SELECT `groups`.`name`, `groups`.`id` FROM `groups` LEFT JOIN `group_member` ON `group_member`.`gid` = `groups`.`id` WHERE `group_member`.`xchan` = '%s' AND `groups`.`deleted` = 0 ORDER BY `groups`.`name` ASC ", dbesc($c) ); diff --git a/include/identity.php b/include/identity.php index b25594c87..5e25244e6 100644 --- a/include/identity.php +++ b/include/identity.php @@ -71,23 +71,34 @@ function validate_channelname($name) { /** - * @function create_dir_account() + * @function create_sys_channel() * Create a system channel - which has no account attached * - * Currently unused. - * */ -function create_dir_account() { +function create_sys_channel() { + if(get_sys_channel()) + return; create_identity(array( 'account_id' => 'xxx', // This will create an identity with an (integer) account_id of 0, but account_id is required - 'nickname' => 'dir', - 'name' => 'Directory', - 'pageflags' => PAGE_DIRECTORY_CHANNEL|PAGE_HIDDEN, - 'publish' => 0 + 'nickname' => 'sys', + 'name' => 'System', + 'pageflags' => PAGE_SYSTEM, + 'publish' => 0, + 'xchanflags' => XCHAN_FLAGS_SYSTEM )); } +function get_sys_channel() { + $r = q("select * from channel left join xchan on channel_hash = xchan_hash where (channel_pageflags & %d) limit 1", + intval(PAGE_SYSTEM) + ); + if($r) + return $r[0]; + return false; +} + + /** * @channel_total() * Return the total number of channels on this site. No filtering is performed. @@ -145,7 +156,7 @@ function create_identity($arr) { $name = escape_tags($arr['name']); $pageflags = ((x($arr,'pageflags')) ? intval($arr['pageflags']) : PAGE_NORMAL); - + $xchanflags = ((x($arr,'xchanflags')) ? intval($arr['xchanflags']) : XCHAN_FLAGS_NORMAL); $name_error = validate_channelname($arr['name']); if($name_error) { $ret['message'] = $name_error; @@ -243,7 +254,7 @@ function create_identity($arr) { $newuid = $ret['channel']['channel_id']; - $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", + $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", dbesc($hash), dbesc($guid), dbesc($sig), @@ -258,7 +269,8 @@ function create_identity($arr) { dbesc($ret['channel']['channel_name']), dbesc('zot'), dbesc(datetime_convert()), - dbesc(datetime_convert()) + dbesc(datetime_convert()), + intval($xchanflags) ); // Not checking return value. @@ -396,7 +408,7 @@ function identity_basic_export($channel_id) { $ret['hubloc'] = $r; } - $r = q("select * from `group` where uid = %d ", + $r = q("select * from `groups` where uid = %d ", intval($channel_id) ); @@ -655,6 +667,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { } } + if((x($profile,'address') == 1) || (x($profile,'locality') == 1) || (x($profile,'region') == 1) @@ -666,6 +679,10 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { $marital = ((x($profile,'marital') == 1) ? t('Status:') : False); $homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False); + if(! perm_is_allowed($profile['uid'],((is_array($observer)) ? $observer['xchan_hash'] : ''),'view_profile')) { + $block = true; + } + if(($profile['hidewall'] || $block) && (! local_user()) && (! remote_user())) { $location = $pdesc = $gender = $marital = $homepage = False; } @@ -688,7 +705,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { $channel_menu = menu_render($m); } $menublock = get_pconfig($profile['uid'],'system','channel_menublock'); - if ($menublock) { + if ($menublock && (! $block)) { require_once('include/comanche.php'); $channel_menu .= comanche_block($menublock); } @@ -949,44 +966,15 @@ function advanced_profile(&$a) { if($txt = prepare_text($a->profile['education'])) $profile['education'] = array( t('School/education:'), $txt ); - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_page = '%s' and uid = %d and obj_type = %d - order by obj_verb, term", - dbesc($a->profile['profile_guid']), - intval($a->profile['profile_uid']), - intval(TERM_OBJ_THING) - ); - - $things = null; - if($r) { - $things = array(); - - // Use the system obj_verbs array as a sort key, since we don't really - // want an alphabetic sort. To change the order, use a plugin to - // alter the obj_verbs() array or alter it in code. Unknown verbs come - // after the known ones - in no particular order. - - $v = obj_verbs(); - foreach($v as $k => $foo) - $things[$k] = null; - foreach($r as $rr) { - if(! $things[$rr['obj_verb']]) - $things[$rr['obj_verb']] = array(); - $things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl']); - } - $sorted_things = array(); - if($things) - foreach($things as $k => $v) - if(is_array($things[$k])) - $sorted_things[$k] = $v; - } + $things = get_things($a->profile['profile_guid'],$a->profile['profile_uid']); - logger('mod_profile: things: ' . print_r($sorted_things,true), LOGGER_DATA); + logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA); return replace_macros($tpl, array( '$title' => t('Profile'), '$profile' => $profile, - '$things' => $sorted_things + '$things' => $things )); } @@ -1104,3 +1092,52 @@ function get_theme_uid() { } return $uid; } + +/** +* @function get_default_profile_photo($size = 175) +* Retrieves the path of the default_profile_photo for this system +* with the specified size. +* @param int $size +* one of (175, 80, 48) +* @returns string +* +*/ + +function get_default_profile_photo($size = 175) { + $scheme = get_config('system','default_profile_photo'); + if(! $scheme) + $scheme = 'rainbow_man'; + return 'images/default_profile_photos/' . $scheme . '/' . $size . '.jpg'; +} + + +/** + * + * @function is_foreigner($s) + * Test whether a given identity is NOT a member of the Red Matrix + * @param string $s; + * xchan_hash of the identity in question + * + * @returns boolean true or false + * + */ + +function is_foreigner($s) { + return((strpbrk($s,':@')) ? true : false); +} + + +/** + * + * @function is_member($s) + * Test whether a given identity is a member of the Red Matrix + * @param string $s; + * xchan_hash of the identity in question + * + * @returns boolean true or false + * + */ + +function is_member($s) { + return((is_foreigner($s)) ? false : true); +}
\ No newline at end of file diff --git a/include/items.php b/include/items.php index dd3cf7644..9824d2434 100755 --- a/include/items.php +++ b/include/items.php @@ -564,9 +564,9 @@ function title_is_body($title, $body) { function get_item_elements($x) { -// logger('get_item_elements'); + $arr = array(); - $arr['body'] = (($x['body']) ? htmlentities($x['body'],ENT_COMPAT,'UTF-8',false) : ''); + $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : ''); $arr['created'] = datetime_convert('UTC','UTC',$x['created']); $arr['edited'] = datetime_convert('UTC','UTC',$x['edited']); @@ -584,27 +584,27 @@ function get_item_elements($x) { ? datetime_convert('UTC','UTC',$x['commented']) : $arr['created']); - $arr['title'] = (($x['title']) ? htmlentities($x['title'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['title'] = (($x['title']) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8',false) : ''); if(mb_strlen($arr['title']) > 255) $arr['title'] = mb_substr($arr['title'],0,255); - $arr['app'] = (($x['app']) ? htmlentities($x['app'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['mid'] = (($x['message_id']) ? htmlentities($x['message_id'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['parent_mid'] = (($x['message_top']) ? htmlentities($x['message_top'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['thr_parent'] = (($x['message_parent']) ? htmlentities($x['message_parent'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['app'] = (($x['app']) ? htmlspecialchars($x['app'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['parent_mid'] = (($x['message_top']) ? htmlspecialchars($x['message_top'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['thr_parent'] = (($x['message_parent']) ? htmlspecialchars($x['message_parent'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['plink'] = (($x['permalink']) ? htmlentities($x['permalink'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['location'] = (($x['location']) ? htmlentities($x['location'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['coord'] = (($x['longlat']) ? htmlentities($x['longlat'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['verb'] = (($x['verb']) ? htmlentities($x['verb'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['mimetype'] = (($x['mimetype']) ? htmlentities($x['mimetype'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['obj_type'] = (($x['object_type']) ? htmlentities($x['object_type'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['tgt_type'] = (($x['target_type']) ? htmlentities($x['target_type'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['comment_policy'] = (($x['comment_scope']) ? htmlentities($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts'); + $arr['plink'] = (($x['permalink']) ? htmlspecialchars($x['permalink'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['location'] = (($x['location']) ? htmlspecialchars($x['location'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['coord'] = (($x['longlat']) ? htmlspecialchars($x['longlat'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['verb'] = (($x['verb']) ? htmlspecialchars($x['verb'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['mimetype'] = (($x['mimetype']) ? htmlspecialchars($x['mimetype'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['obj_type'] = (($x['object_type']) ? htmlspecialchars($x['object_type'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['tgt_type'] = (($x['target_type']) ? htmlspecialchars($x['target_type'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['comment_policy'] = (($x['comment_scope']) ? htmlspecialchars($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts'); - $arr['sig'] = (($x['signature']) ? htmlentities($x['signature'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['sig'] = (($x['signature']) ? htmlspecialchars($x['signature'], ENT_COMPAT,'UTF-8',false) : ''); $arr['object'] = activity_sanitise($x['object']); @@ -667,7 +667,6 @@ function get_item_elements($x) { $arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key)); } - return $arr; } @@ -832,8 +831,8 @@ function decode_tags($t) { $ret = array(); foreach($t as $x) { $tag = array(); - $tag['term'] = htmlentities($x['tag'], ENT_COMPAT,'UTF-8',false); - $tag['url'] = htmlentities($x['url'], ENT_COMPAT,'UTF-8',false); + $tag['term'] = htmlspecialchars($x['tag'], ENT_COMPAT,'UTF-8',false); + $tag['url'] = htmlspecialchars($x['url'], ENT_COMPAT,'UTF-8',false); switch($x['type']) { case 'hashtag': $tag['type'] = TERM_HASHTAG; @@ -876,12 +875,12 @@ function activity_sanitise($arr) { if(is_array($x)) $ret[$k] = activity_sanitise($x); else - $ret[$k] = htmlentities($x, ENT_COMPAT,'UTF-8',false); + $ret[$k] = htmlspecialchars($x, ENT_COMPAT,'UTF-8',false); } return $ret; } else { - return htmlentities($arr, ENT_COMPAT,'UTF-8', false); + return htmlspecialchars($arr, ENT_COMPAT,'UTF-8', false); } } return ''; @@ -893,7 +892,7 @@ function array_sanitise($arr) { if($arr) { $ret = array(); foreach($arr as $x) { - $ret[] = htmlentities($x, ENT_COMPAT,'UTF-8',false); + $ret[] = htmlspecialchars($x, ENT_COMPAT,'UTF-8',false); } return $ret; } @@ -958,8 +957,8 @@ function get_mail_elements($x) { $arr = array(); - $arr['body'] = (($x['body']) ? htmlentities($x['body'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['title'] = (($x['title'])? htmlentities($x['title'],ENT_COMPAT,'UTF-8',false) : ''); + $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['title'] = (($x['title'])? htmlspecialchars($x['title'],ENT_COMPAT,'UTF-8',false) : ''); $arr['created'] = datetime_convert('UTC','UTC',$x['created']); if((! array_key_exists('expires',$x)) || ($x['expires'] === '0000-00-00 00:00:00')) @@ -977,18 +976,18 @@ function get_mail_elements($x) { $key = get_config('system','pubkey'); $arr['mail_flags'] |= MAIL_OBSCURED; - $arr['body'] = htmlentities($arr['body'],ENT_COMPAT,'UTF-8',false); + $arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false); if($arr['body']) $arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key)); - $arr['title'] = htmlentities($arr['title'],ENT_COMPAT,'UTF-8',false); + $arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false); if($arr['title']) $arr['title'] = json_encode(crypto_encapsulate($arr['title'],$key)); if($arr['created'] > datetime_convert()) $arr['created'] = datetime_convert(); - $arr['mid'] = (($x['message_id']) ? htmlentities($x['message_id'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['parent_mid'] = (($x['message_parent']) ? htmlentities($x['message_parent'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['parent_mid'] = (($x['message_parent']) ? htmlspecialchars($x['message_parent'], ENT_COMPAT,'UTF-8',false) : ''); if($x['attach']) $arr['attach'] = activity_sanitise($x['attach']); @@ -1017,18 +1016,18 @@ function get_profile_elements($x) { else return array(); - $arr['desc'] = (($x['title']) ? htmlentities($x['title'],ENT_COMPAT,'UTF-8',false) : ''); + $arr['desc'] = (($x['title']) ? htmlspecialchars($x['title'],ENT_COMPAT,'UTF-8',false) : ''); $arr['dob'] = datetime_convert('UTC','UTC',$x['birthday'],'Y-m-d'); $arr['age'] = (($x['age']) ? intval($x['age']) : 0); - $arr['gender'] = (($x['gender']) ? htmlentities($x['gender'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['marital'] = (($x['marital']) ? htmlentities($x['marital'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['sexual'] = (($x['sexual']) ? htmlentities($x['sexual'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['locale'] = (($x['locale']) ? htmlentities($x['locale'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['region'] = (($x['region']) ? htmlentities($x['region'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['postcode'] = (($x['postcode']) ? htmlentities($x['postcode'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['country'] = (($x['country']) ? htmlentities($x['country'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['gender'] = (($x['gender']) ? htmlspecialchars($x['gender'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['marital'] = (($x['marital']) ? htmlspecialchars($x['marital'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['sexual'] = (($x['sexual']) ? htmlspecialchars($x['sexual'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['locale'] = (($x['locale']) ? htmlspecialchars($x['locale'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['region'] = (($x['region']) ? htmlspecialchars($x['region'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['postcode'] = (($x['postcode']) ? htmlspecialchars($x['postcode'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['country'] = (($x['country']) ? htmlspecialchars($x['country'], ENT_COMPAT,'UTF-8',false) : ''); $arr['keywords'] = (($x['keywords'] && is_array($x['keywords'])) ? array_sanitise($x['keywords']) : array()); @@ -2149,6 +2148,13 @@ function tag_deliver($uid,$item_id) { $item = $i[0]; + if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK) && ($item['item_flags'] & ITEM_THREAD_TOP) && ($item['edited'] != $item['created'])) { + // this is an update to a post which was already processed by us and has a second delivery chain + // Just start the second delivery chain to deliver the updated post + proc_run('php','include/notifier.php','tgroup',$item['id']); + return; + } + if($item['obj_type'] === ACTIVITY_OBJ_TAGTERM) { @@ -2278,7 +2284,7 @@ function tag_deliver($uid,$item_id) { $body = preg_replace('/\[share(.*?)\[\/share\]/','',$body); - $pattern = '/@\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/'; + $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/'; if(! preg_match($pattern,$body,$matches)) { logger('tag_deliver: mention was in a reshare - ignoring'); @@ -2363,12 +2369,13 @@ function tgroup_check($uid,$item) { $mention = false; // check that the message originated elsewhere and is a top-level post - // or is a followup and we have already accepted the top level post + // or is a followup and we have already accepted the top level post as an uplink if($item['mid'] != $item['parent_mid']) { - $r = q("select id from item where mid = '%s' and uid = %d limit 1", + $r = q("select id from item where mid = '%s' and uid = %d and ( item_flags & %d ) limit 1", dbesc($item['parent_mid']), - intval($uid) + intval($uid), + intval(ITEM_UPLINK) ); if($r) return true; @@ -2411,7 +2418,7 @@ function tgroup_check($uid,$item) { $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']); - $pattern = '/@\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/'; + $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/'; if(! preg_match($pattern,$body,$matches)) { logger('tgroup_check: mention was in a reshare - ignoring'); @@ -2444,7 +2451,7 @@ function check_item_source($uid,$item) { $r = q("select * from source where src_channel_id = %d and src_xchan = '%s' limit 1", intval($uid), - dbesc($item['owner_xchan']) + dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan']) ); if(! $r) @@ -3711,7 +3718,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ") $sql_options ) "; if($arr['gid'] && $uid) { - $r = q("SELECT * FROM `group` WHERE id = %d AND uid = %d LIMIT 1", + $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1", intval($arr['group']), intval($uid) ); diff --git a/include/nav.php b/include/nav.php index f89de2de0..008899c47 100644 --- a/include/nav.php +++ b/include/nav.php @@ -165,7 +165,7 @@ EOT; $nav['messages']['mark'] = array('', t('Mark all private messages seen'), '',''); $nav['messages']['inbox'] = array('message', t('Inbox'), "", t('Inbox')); $nav['messages']['outbox']= array('message/sent', t('Outbox'), "", t('Outbox')); - $nav['messages']['new'] = array('message/new', t('New Message'), "", t('New Message')); + $nav['messages']['new'] = array('mail/new', t('New Message'), "", t('New Message')); $nav['all_events'] = array('events', t('Events'), "", t('Event Calendar')); @@ -196,7 +196,7 @@ EOT; $banner = get_config('system','banner'); if($banner === false) - $banner = 'red'; + $banner = get_config('system','sitename'); $x = array('nav' => $nav, 'usermenu' => $userinfo ); call_hooks('nav', $x); diff --git a/include/network.php b/include/network.php index 50f853ca0..3fe7f5400 100644 --- a/include/network.php +++ b/include/network.php @@ -548,7 +548,7 @@ function avatar_img($email) { call_hooks('avatar_lookup', $avatar); if(! $avatar['success']) - $avatar['url'] = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/175.jpg'; + $avatar['url'] = $a->get_baseurl() . '/' . get_default_profile_photo(); logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG); return $avatar['url']; @@ -582,7 +582,7 @@ function scale_external_images($s, $include_link = true, $scale_replace = false) $a = get_app(); // Picture addresses can contain special characters - $s = htmlspecialchars_decode($s); + $s = htmlspecialchars_decode($s, ENT_COMPAT); $matches = null; $c = preg_match_all('/\[img(.*?)\](.*?)\[\/img\]/ism',$s,$matches,PREG_SET_ORDER); diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 8730b4298..debe1bc38 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -513,20 +513,28 @@ function guess_image_type($filename, $headers = '') { } -function import_profile_photo($photo,$xchan) { +function import_profile_photo($photo,$xchan,$thing = false) { $a = get_app(); + $flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN); + $album = (($thing) ? 'Things' : 'Contact Photos'); + logger('import_profile_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG); - $r = q("select resource_id from photo where xchan = '%s' and scale = 4 limit 1", - dbesc($xchan) - ); - if($r) { - $hash = $r[0]['resource_id']; - } - else { + if($thing) $hash = photo_new_resource(); + else { + $r = q("select resource_id from photo where xchan = '%s' and (photo_flags & %d ) scale = 4 limit 1", + dbesc($xchan), + intval(PHOTO_XCHAN) + ); + if($r) { + $hash = $r[0]['resource_id']; + } + else { + $hash = photo_new_resource(); + } } $photo_failure = false; @@ -541,10 +549,30 @@ function import_profile_photo($photo,$xchan) { $img = photo_factory($img_str, $type); if($img->is_valid()) { + $width = $img->getWidth(); + $height = $img->getHeight(); + + if($width && $height) { + if(($width / $height) > 1.2) { + // crop out the sides + $margin = $width - $height; + $img->cropImage(175,($margin / 2),0,$height,$height); + } + elseif(($height / $width) > 1.2) { + // crop out the bottom + $margin = $height - $width; + $img->cropImage(175,0,0,$width,$width); - $img->scaleImageSquare(175); + } + else { + $img->scaleImageSquare(175); + } + + } + else + $photo_failure = true; - $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => 'Contact Photos', 'photo_flags' => PHOTO_XCHAN, 'scale' => 4); + $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_flags' => $flags, 'scale' => 4); $r = $img->save($p); @@ -576,9 +604,9 @@ function import_profile_photo($photo,$xchan) { $photo_failure = true; } if($photo_failure) { - $photo = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/175.jpg'; - $thumb = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/80.jpg'; - $micro = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/48.jpg'; + $photo = $a->get_baseurl() . '/' . get_default_profile_photo(); + $thumb = $a->get_baseurl() . '/' . get_default_profile_photo(80); + $micro = $a->get_baseurl() . '/' . get_default_profile_photo(48); $type = 'image/jpeg'; } diff --git a/include/photos.php b/include/photos.php index ea4b494e0..e41d1059a 100644 --- a/include/photos.php +++ b/include/photos.php @@ -279,8 +279,16 @@ function photos_album_widget($channelx,$observer,$albums = null) { $o = ''; - if(! $albums) - $albums = photos_albums_list($channelx,$observer); + // If we weren't passed an album list, see if the photos module + // dropped one for us to find in $a->data['albums']. + // If all else fails, load it. + + if(! $albums) { + if(array_key_exists('albums', get_app()->data)) + $albums = get_app()->data['albums']; + else + $albums = photos_albums_list($channelx,$observer); + } if($albums) { $o = replace_macros(get_markup_template('photo_albums.tpl'),array( @@ -311,13 +319,16 @@ function photos_list_photos($channel,$observer,$album = '') { $ret = array('success' => false); - $r = q("select resource_id, created, edited, title, `desc`, album, filename, `type`, height, width, `size`, `scale`, profile, photo_flags, allow_cid, allow_gid, deny_cid, deny_gid from photo where uid = %d and ( photo_flags = %d or photo_flags = %d ) $sql_extra ", + $r = q("select 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 ( photo_flags = %d or photo_flags = %d ) $sql_extra ", intval($channel_id), intval(PHOTO_NORMAL), intval(PHOTO_PROFILE) ); - + if($r) { + for($x = 0; $x < count($r); $x ++) { + $r[$x]['src'] = z_root() . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['scale']; + } $ret['success'] = true; $ret['photos'] = $r; } diff --git a/include/plugin.php b/include/plugin.php index 5ed2a1736..9982a48a2 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -494,6 +494,15 @@ function head_add_css($src,$media = 'screen') { get_app()->css_sources[] = array($src,$media); } + +function head_remove_css($src,$media = 'screen') { + $a = get_app(); + $index = array_search(array($src,$media),$a->css_sources); + if($index !== false) + unset($a->css_sources[$index]); + +} + function head_get_css() { $str = ''; $sources = get_app()->css_sources; @@ -511,15 +520,44 @@ function format_css_if_exists($source) { $path = theme_include($source[0]); if($path) - return '<link rel="stylesheet" href="' . z_root() . '/' . $path . '" type="text/css" media="' . $source[1] . '" />' . "\r\n"; + return '<link rel="stylesheet" href="' . script_path() . '/' . $path . '" type="text/css" media="' . $source[1] . '" />' . "\r\n"; } +function script_path() { + if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) + $scheme = 'https'; + elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) + $scheme = 'https'; + else + $scheme = 'http'; + + if(x($_SERVER,'SERVER_NAME')) { + $hostname = $_SERVER['SERVER_NAME']; + } + else { + return z_root(); + } + + if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) { + $hostname .= ':' . $_SERVER['SERVER_PORT']; + } + + return $scheme . '://' . $hostname; +} function head_add_js($src) { get_app()->js_sources[] = $src; } +function head_remove_js($src) { + $a = get_app(); + $index = array_search($src,$a->js_sources); + if($index !== false) + unset($a->js_sources[$index]); + +} + function head_get_js() { $str = ''; $sources = get_app()->js_sources; @@ -536,7 +574,7 @@ function format_js_if_exists($source) { else $path = theme_include($source); if($path) - return '<script src="' . z_root() . '/' . $path . '" ></script>' . "\r\n" ; + return '<script src="' . script_path() . '/' . $path . '" ></script>' . "\r\n" ; } diff --git a/include/reddav.php b/include/reddav.php index c24414610..79c68a000 100644 --- a/include/reddav.php +++ b/include/reddav.php @@ -1,7 +1,9 @@ <?php /** @file */ use Sabre\DAV; - require_once('vendor/autoload.php'); +require_once('vendor/autoload.php'); + +require_once('include/attach.php'); class RedInode implements DAV\INode { @@ -70,65 +72,146 @@ class RedInode implements DAV\INode { } -abstract class RedDirectory extends DAV\Node implements DAV\ICollection { +class RedDirectory extends DAV\Node implements DAV\ICollection { private $red_path; - private $dir_key; + private $ext_path; + private $root_dir = ''; private $auth; - private $channel_id; - function __construct($red_path,$auth_plugin) { - $this->red_path = $red_path; + + + function __construct($ext_path,&$auth_plugin) { + logger('RedDirectory::__construct() ' . $ext_path); + $this->ext_path = $ext_path; + $this->red_path = ((strpos($ext_path,'/cloud') === 0) ? substr($ext_path,6) : $ext_path); + if(! $this->red_path) + $this->red_path = '/'; $this->auth = $auth_plugin; + logger('Red_Directory: ' . print_r($this,true)); + + } function getChildren() { - if(! perm_is_allowed($this->channel_id,'','view_storage')) - return array(); + logger('RedDirectory::getChildren : ' . print_r($this,true)); - $ret = array(); - $r = q("select distinct filename from attach where folder = '%s' and uid = %d group by filename", - dbesc($this->dir_key), - intval($this->channel_id) - ); - if($r) { - foreach($r as $rr) { - $ret[] = $rr['filename']; - } + if(get_config('system','block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'view_storage')) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; } - return $ret; + + return RedCollectionData($this->red_path,$this->auth); } function getChild($name) { - if(! perm_is_allowed($this->channel_id,'','view_storage')) { + + + logger('RedDirectory::getChild : ' . $name); + logger('RedDirectory::getChild : ' . print_r($this,true)); + + if(get_config('system','block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'view_storage')) { throw new DAV\Exception\Forbidden('Permission denied.'); return; } -// FIXME check revisions - - $r = q("select * from attach where folder = '%s' and filename = '%s' and uid = %d limit 1", - dbesc($this->dir_key), - dbesc($name), - dbesc($this->channel_id) - ); - if(! $r) { - throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found'); - } + if($this->red_path === '/' && $name === 'cloud') { + return new RedDirectory('/cloud', $this->auth); + } + $x = RedFileData($this->ext_path . '/' . $name, $this->auth); + logger('RedFileData returns: ' . print_r($x,true)); + if($x) + return $x; + throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found'); } + function getName() { + logger('RedDirectory::getName : ' . print_r($this,true)); + logger('RedDirectory::getName returns: ' . basename($this->red_path)); + + return (basename($this->red_path)); + } + + + function createFile($name,$data = null) { + logger('RedDirectory::createFile : ' . $name); + logger('RedDirectory::createFile : ' . print_r($this,true)); + + logger('createFile():' . stream_get_contents($data)); + + + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'write_storage')) { + logger('createFile: permission denied'); + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + $mimetype = z_mime_content_type($name); + + + $c = q("select * from channel where channel_id = %d limit 1", + intval($this->auth->channel_id) + ); + + + $filesize = 0; + $hash = random_string(); +dbg(1); + $r = q("INSERT INTO attach ( aid, uid, hash, filename, filetype, filesize, revision, data, created, edited ) + VALUES ( %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s' ) ", + intval($c[0]['channel_account_id']), + intval($c[0]['channel_id']), + dbesc($hash), + dbesc($name), + dbesc($mimetype), + intval($filesize), + intval(0), + dbesc(stream_get_contents($data)), + dbesc(datetime_convert()), + dbesc(datetime_convert()) + ); + + $r = q("update attach set filesize = length(data) where hash = '%s' and uid = %d limit 1", + dbesc($hash), + intval($c[0]['channel_id']) + ); + + +dbg(0); + } + function createDirectory($name) { + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'write_storage')) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + + + + + @@ -136,12 +219,17 @@ abstract class RedDirectory extends DAV\Node implements DAV\ICollection { function childExists($name) { - $r = q("select distinct filename from attach where folder = '%s' and filename = '%s' and uid = %d group by filename", - dbesc($this->dir_key), - dbesc($name), - intval($this->channel_id) - ); - if($r) + + logger('RedDirectory::childExists : ' . print_r($this->auth,true)); + + if($this->red_path === '/' && $name === 'cloud') { + logger('RedDirectory::childExists /cloud: true'); + return true; + } + + $x = RedFileData($this->ext_path . '/' . $name, $this->auth,true); + logger('RedFileData returns: ' . print_r($x,true)); + if($x) return true; return false; @@ -150,31 +238,81 @@ abstract class RedDirectory extends DAV\Node implements DAV\ICollection { } -abstract class RedFile extends DAV\Node implements DAV\IFile { +class RedFile extends DAV\Node implements DAV\IFile { private $data; + private $auth; + private $name; - - function __construct($data) { + function __construct($name, $data, &$auth) { + logger('RedFile::_construct: ' . $name); + $this->name = $name; $this->data = $data; + $this->auth = $auth; + + logger('RedFile::_construct: ' . print_r($this->data,true)); + } + + + function getName() { + logger('RedFile::getName: ' . basename($this->name)); + return basename($this->name); + + } + + + function setName($newName) { + logger('RedFile::setName: ' . basename($this->name) . ' -> ' . $newName); + + if((! $newName) || (! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'write_storage'))) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + $newName = str_replace('/','%2F',$newName); + + $r = q("update attach set filename = '%s' where hash = '%s' and id = %d limit 1", + dbesc($this->data['filename']), + intval($this->data['id']) + ); } function put($data) { + logger('RedFile::put: ' . basename($this->name)); + logger('put():' . stream_get_contents($data)); + +dbg(1); + $r = q("update attach set data = '%s' where hash = '%s' and uid = %d limit 1", + dbesc(stream_get_contents($data)), + dbesc($this->data['hash']), + intval($this->data['uid']) + ); + $r = q("update attach set filesize = length(data) where hash = '%s' and uid = %d limit 1", + dbesc($this->data['hash']), + intval($this->data['uid']) + ); +dbg(0); } function get() { + logger('RedFile::get: ' . basename($this->name)); + $r = q("select data from attach where hash = '%s' and uid = %d limit 1", + dbesc($this->data['hash']), + intval($this->data['uid']) + ); + if($r) return $r[0]['data']; } function getETag() { - - + logger('RedFile::getETag: ' . basename($this->name)); + return $this->data['hash']; } @@ -188,9 +326,215 @@ abstract class RedFile extends DAV\Node implements DAV\IFile { return $this->data['filesize']; } + + function getLastModified() { + logger('RedFile::getLastModified: ' . basename($this->name)); + return $this->data['edited']; + } + + +} + +function RedChannelList(&$auth) { + + $ret = array(); + + $r = q("select channel_id, channel_address from channel where not (channel_pageflags & %d)", + intval(PAGE_REMOVED) + ); + + if($r) { + foreach($r as $rr) { + if(perm_is_allowed($rr['channel_id'],$auth->observer,'view_storage')) { + $ret[] = new RedDirectory('/cloud/' . $rr['channel_address'],$auth); + } + } + } + return $ret; + } +function RedCollectionData($file,&$auth) { + + $ret = array(); + + $x = strpos($file,'/cloud'); + if($x === 0) { + $file = substr($file,6); + } + + +logger('RedCollectionData: ' . $file); + + if((! $file) || ($file === '/')) { + return RedChannelList($auth); + + } + + $file = trim($file,'/'); + $path_arr = explode('/', $file); + + if(! $path_arr) + return null; + + $channel_name = $path_arr[0]; + + $r = q("select channel_id from channel where channel_address = '%s' limit 1", + dbesc($channel_name) + ); + +logger('dbg1: ' . print_r($r,true)); + + if(! $r) + return null; + + $channel_id = $r[0]['channel_id']; + + $path = '/' . $channel_name; + + $folder = ''; + + for($x = 1; $x < count($path_arr); $x ++) { + $r = q("select id, hash, filename, flags from attach where folder = '%s' and (flags & %d)", + dbesc($folder), + intval($channel_id), + intval(ATTACH_FLAG_DIR) + ); + if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) { + $folder = $r[0]['hash']; + $path = $path . '/' . $r[0]['filename']; + } + } + +logger('dbg2: ' . print_r($r,true)); + + if($path !== '/' . $file) { + logger("RedCollectionData: Path mismatch: $path !== /$file"); + return NULL; + } + + $ret = array(); + + + $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach where folder = '%s' and uid = %d group by filename", + dbesc($folder), + intval($channel_id) + ); + +logger('dbg2: ' . print_r($r,true)); + foreach($r as $rr) { + if($rr['flags'] & ATTACH_FLAG_DIR) + $ret[] = new RedDirectory('/cloud' . $path . '/' . $rr['filename'],$auth); + else + $ret[] = new RedFile('/cloud' . $path . '/' . $rr['filename'],$rr,$auth); + } + + return $ret; + +} + +function RedFileData($file, &$auth,$test = false) { + +logger('RedFileData:' . $file); + + + $x = strpos($file,'/cloud'); + if($x === 0) { + $file = substr($file,6); + } + +logger('RedFileData2: ' . $file); + + if((! $file) || ($file === '/')) { + return RedDirectory('/',$auth); + + } + + $file = trim($file,'/'); + +logger('file=' . $file); + + $path_arr = explode('/', $file); + + if(! $path_arr) + return null; + + logger("file = $file - path = " . print_r($path_arr,true)); + + $channel_name = $path_arr[0]; + + + $r = q("select channel_id from channel where channel_address = '%s' limit 1", + dbesc($channel_name) + ); + + logger('dbg0: ' . print_r($r,true)); + + if(! $r) + return null; + + $channel_id = $r[0]['channel_id']; + + $path = '/' . $channel_name; + + $folder = ''; +//dbg(1); + + require_once('include/security.php'); + $perms = permissions_sql($channel_id); + + $errors = false; + + for($x = 1; $x < count($path_arr); $x ++) { +dbg(1); + $r = q("select id, hash, filename, flags from attach where folder = '%s' and uid = %d and (flags & %d) $perms", + dbesc($folder), + intval($channel_id), + intval(ATTACH_FLAG_DIR) + ); +dbg(0); + logger('dbg1: ' . print_r($r,true)); + + if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) { + $folder = $r[0]['hash']; + $path = $path . '/' . $r[0]['filename']; + } + if(! $r) { + $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach + where folder = '%s' and filename = '%s' and uid = %d $perms group by filename limit 1", + dbesc($folder), + basename($file), + intval($channel_id) + + ); + } + if(! $r) + $errors = true; + } + + logger('dbg1: ' . print_r($r,true)); + + if($path === '/' . $file) { + // final component was a directory. + return new RedDirectory('/cloud/' . $file,$auth); + } + + if($errors) { + if($test) + return false; + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + if($r) { + if($r[0]['flags'] & ATTACH_FLAG_DIR) + return new RedDirectory('/cloud' . $path . '/' . $r[0]['filename'],$auth); + else + return new RedFile('/cloud' . $path . '/' . $r[0]['filename'],$r[0],$auth); + } + return false; +} diff --git a/include/security.php b/include/security.php index 296fa450f..138efe3ab 100644 --- a/include/security.php +++ b/include/security.php @@ -386,7 +386,7 @@ function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'f if(! function_exists('init_groups_visitor')) { function init_groups_visitor($contact_id) { $groups = array(); - $r = q("SELECT hash FROM `group` left join group_member on group.id = group_member.gid WHERE xchan = '%s' ", + $r = q("SELECT hash FROM `groups` left join group_member on groups.id = group_member.gid WHERE xchan = '%s' ", dbesc($contact_id) ); if(count($r)) { diff --git a/include/taxonomy.php b/include/taxonomy.php index 5159dad02..4f2b5e8fd 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -87,9 +87,9 @@ function format_term_for_display($term) { return $s; if($term['url']) - $s .= '<a href="' . $term['url'] . '">' . htmlspecialchars($term['term']) . '</a>'; + $s .= '<a href="' . $term['url'] . '">' . htmlspecialchars($term['term'], ENT_COMPAT,'UTF-8') . '</a>'; else - $s .= htmlspecialchars($term['term']); + $s .= htmlspecialchars($term['term'], ENT_COMPAT,'UTF-8'); return $s; } @@ -217,16 +217,19 @@ function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$ } function dir_tagblock($link,$r) { - $o = ''; - $tab = 0; + $o = ''; + $tab = 0; - if($r) { - $o = '<div class="dirtagblock widget"><h3>' . t('Keywords') . '</h3><div class="tags" align="center">'; - foreach($r as $rr) { - $o .= '<a href="'.$link .'/' . '?f=&keywords=' . urlencode($rr['term']).'" class="tag'.$rr['normalise'].'" rel="nofollow" >'.$rr['term'].'</a> ' . "\r\n"; + if(! $r) + $r = get_app()->data['directory_keywords']; + + if($r) { + $o = '<div class="dirtagblock widget"><h3>' . t('Keywords') . '</h3><div class="tags" align="center">'; + foreach($r as $rr) { + $o .= '<a href="'.$link .'/' . '?f=&keywords=' . urlencode($rr['term']).'" class="tag'.$rr['normalise'].'" rel="nofollow" >'.$rr['term'].'</a> ' . "\r\n"; + } + $o .= '</div></div>'; } - $o .= '</div></div>'; - } return $o; } @@ -258,13 +261,81 @@ function obj_verbs() { } -function obj_verb_selector() { +function obj_verb_selector($current = '') { $verbs = obj_verbs(); $o .= '<select class="obj-verb-selector" name="verb" >'; foreach($verbs as $k => $v) { - $o .= '<option value="' . urlencode($k) . '">' . $v[0] . '</option>'; + $selected = (($k == $current) ? ' selected="selected" ' : ''); + $o .= '<option value="' . urlencode($k) . '"' . $selected . '>' . $v[0] . '</option>'; } $o .= '</select>'; return $o; +} + +function get_things($profile_hash,$uid) { + + $sql_extra = (($profile_hash) ? " and obj_page = '" . $profile_hash . "' " : ''); + + $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and uid = %d and obj_type = %d $sql_extra order by obj_verb, term", + intval($uid), + intval(TERM_OBJ_THING) + ); + + $things = $sorted_things = null; + + $profile_hashes = array(); + + if($r) { + + // if no profile_hash was specified (display on profile page mode), match each of the things to a profile name + // (list all my things mode). This is harder than it sounds. + + foreach($r as $rr) { + $rr['profile_name'] = ''; + if(! in_array($rr['term_hash'],$profile_hashes)) + $profile_hashes[] = $rr['term_hash']; + } + stringify_array_elms($profile_hashes); + if(! $profile_hash) { + $exp = explode(',',$profile_hashes); + $p = q("select profile_guid as hash, profile_name as name from profile where profile_guid in ( $exp ) "); + if($p) { + foreach($r as $rr) { + foreach($p as $pp) { + if($rr['obj_page'] == $pp['hash']) { + $rr['profile_name'] == $pp['name']; + } + } + } + } + } + + $things = array(); + + // Use the system obj_verbs array as a sort key, since we don't really + // want an alphabetic sort. To change the order, use a plugin to + // alter the obj_verbs() array or alter it in code. Unknown verbs come + // after the known ones - in no particular order. + + $v = obj_verbs(); + foreach($v as $k => $foo) + $things[$k] = null; + foreach($r as $rr) { + if(! $things[$rr['obj_verb']]) + $things[$rr['obj_verb']] = array(); + $things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl'], 'profile' => $rr['profile_name']); + } + $sorted_things = array(); + if($things) { + foreach($things as $k => $v) { + if(is_array($things[$k])) { + $sorted_things[$k] = $v; + } + } + } + } + + return $sorted_things; + }
\ No newline at end of file diff --git a/include/text.php b/include/text.php index aa23f96b0..8b71fbddf 100755 --- a/include/text.php +++ b/include/text.php @@ -781,6 +781,34 @@ function linkify($s) { return($s); } +/** + * @function sslify($s) + * Replace media element using http url with https to a local redirector if using https locally + * @param string $s + * + * Looks for HTML tags containing src elements that are http when we're viewing an https page + * Typically this throws an insecure content violation in the browser. So we redirect them + * to a local redirector which uses https and which redirects to the selected content + * + * @returns string + */ + + +function sslify($s) { + if(strpos(z_root(),'https:') === false) + return $s; + $matches = null; + $cnt = preg_match_all("/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/",$s,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $match) { + $s = str_replace($match[2],z_root() . '/sslify?f=&url=' . urlencode($match[2]),$s); + } + } + return $s; +} + + + function get_poke_verbs() { // index is present tense verb @@ -1065,7 +1093,7 @@ function theme_attachments(&$item) { break; } - $title = htmlentities($r['title'], ENT_COMPAT,'UTF-8'); + $title = htmlspecialchars($r['title'], ENT_COMPAT,'UTF-8'); if(! $title) $title = t('unknown.???'); $title .= ' ' . $r['length'] . ' ' . t('bytes'); @@ -1095,7 +1123,7 @@ function format_categories(&$item,$writeable) { if($terms) { $categories = array(); foreach($terms as $t) { - $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8') ; + $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ; if(! trim($term)) continue; $removelink = (($writeable) ? z_root() . '/filerm/' . $item['id'] . '?f=&cat=' . urlencode($t['term']) : ''); @@ -1117,7 +1145,7 @@ function format_filer(&$item) { if($terms) { $categories = array(); foreach($terms as $t) { - $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8') ; + $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ; if(! trim($term)) continue; $removelink = z_root() . '/filerm/' . $item['id'] . '?f=&term=' . urlencode($t['term']); @@ -1166,6 +1194,10 @@ function prepare_body(&$item,$attach = false) { if(local_user() == $item['uid']) $s .= format_filer($item); + + $s = sslify($s); + + // Look for spoiler $spoilersearch = '<blockquote class="spoiler">'; @@ -1889,18 +1921,17 @@ function json_decode_plus($s) { function design_tools() { -$channel = get_app()->get_channel(); -$who = $channel['channel_address']; - -return replace_macros(get_markup_template('design_tools.tpl'), array( - '$title' => t('Design'), - '$who' => $who, - '$blocks' => t('Blocks'), - '$menus' => t('Menus'), - '$layout' => t('Layouts'), - '$pages' => t('Pages') - )); - + $channel = get_app()->get_channel(); + $who = $channel['channel_address']; + + return replace_macros(get_markup_template('design_tools.tpl'), array( + '$title' => t('Design'), + '$who' => $who, + '$blocks' => t('Blocks'), + '$menus' => t('Menus'), + '$layout' => t('Layouts'), + '$pages' => t('Pages') + )); } /* case insensitive in_array() */ diff --git a/include/widgets.php b/include/widgets.php index cea5a6ce2..a1ff756ff 100644 --- a/include/widgets.php +++ b/include/widgets.php @@ -1,17 +1,7 @@ <?php /** @file */ -function list_widgets() { - $widgets = array( - 'profile' => t('Displays a full channel profile'), - 'tagcloud' => t('Tag cloud of webpage categories'), - 'collections' => t('List and filter by collection'), - 'suggestions' => t('Show a couple of channel suggestion'), - 'follow' => t('Provide a channel follow form') - ); - $arr = array('widgets' => $widgets); - call_hooks('list_widgets',$arr); - return $arr['widgets']; -} +require_once('include/dir_fns.php'); +require_once('include/contact_widgets.php'); function widget_profile($args) { @@ -47,16 +37,48 @@ function widget_tagcloud($args) { function widget_collections($args) { require_once('include/group.php'); - $page = argv(0); - $gid = $_REQUEST['gid']; - return group_side($page,$page,true,$_REQUEST['gid'],'',0); + $mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation'); + switch($mode) { + case 'conversation': + $every = argv(0); + $each = argv(0); + $edit = true; + $current = $_REQUEST['gid']; + $abook_id = 0; + $wmode = 0; + break; + case 'groups': + $every = 'connections'; + $each = argv(0); + $edit = false; + $current = intval(argv(1)); + $abook_id = 0; + $wmode = 1; + break; + case 'abook': + $every = 'connections'; + $each = 'group'; + $edit = false; + $current = 0; + $abook_id = get_app()->poi['abook_xchan']; + $wmode = 1; + break; + default: + return ''; + break; + } + + return group_side($every, $each, $edit, $current, $abook_id, $wmode); } function widget_suggestions($arr) { + if((! local_user()) || (! feature_enabled(local_user(),'suggest'))) + return ''; + require_once('include/socgraph.php'); $r = suggestion_query(local_user(),get_observer_hash(),0,20); @@ -143,7 +165,7 @@ function widget_notes($arr) { if(! feature_enabled(local_user(),'private_notes')) return ''; - $text = htmlspecialchars(get_pconfig(local_user(),'notes','text')); + $text = get_pconfig(local_user(),'notes','text'); $o = replace_macros(get_markup_template('notes.tpl'), array( '$banner' => t('Notes'), @@ -216,7 +238,7 @@ function widget_savedsearch($arr) { 'term' => $rr['term'], 'dellink' => z_root() . '/' . $srchurl . (($hasq) ? '' : '?f=') . '&searchremove=1&search=' . urlencode($rr['term']), 'srchlink' => z_root() . '/' . $srchurl . (($hasq) ? '' : '?f=') . '&search=' . urlencode($rr['term']), - 'displayterm' => htmlspecialchars($rr['term']), + 'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'), 'encodedterm' => urlencode($rr['term']), 'delete' => t('Remove term'), 'selected' => ($search==$rr['term']), @@ -314,7 +336,7 @@ function widget_fullprofile($arr) { function widget_categories($arr) { $a = get_app(); - $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat']) : ''); + $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); $srchurl = $a->query_string; $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); @@ -330,4 +352,226 @@ function widget_tagcloud_wall($arr) { if(feature_enabled($a->profile['profile_uid'],'tagadelic')) return tagblock('search',$a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL); return ''; -}
\ No newline at end of file +} + + +function widget_affinity($arr) { + + if(! local_user()) + return ''; + + $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : 0); + $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : 99); + + if(feature_enabled(local_user(),'affinity')) { + $tpl = get_markup_template('main_slider.tpl'); + $x = replace_macros($tpl,array( + '$val' => $cmin . ';' . $cmax, + '$refresh' => t('Refresh'), + '$me' => t('Me'), + '$intimate' => t('Best Friends'), + '$friends' => t('Friends'), + '$coworkers' => t('Co-workers'), + '$oldfriends' => t('Former Friends'), + '$acquaintances' => t('Acquaintances'), + '$world' => t('Everybody') + )); + $arr = array('html' => $x); + call_hooks('main_slider',$arr); + return $arr['html']; + } + return ''; +} + + +function widget_settings_menu($arr) { + + if(! local_user()) + return; + + $a = get_app(); + $channel = $a->get_channel(); + + $abook_self_id = 0; + + // Retrieve the 'self' address book entry for use in the auto-permissions link + + $abk = q("select abook_id from abook where abook_channel = %d and ( abook_flags & %d ) limit 1", + intval(local_user()), + intval(ABOOK_FLAG_SELF) + ); + if($abk) + $abook_self_id = $abk[0]['abook_id']; + + + $tabs = array( + array( + 'label' => t('Account settings'), + 'url' => $a->get_baseurl(true).'/settings/account', + 'selected' => ((argv(1) === 'account') ? 'active' : ''), + ), + + array( + 'label' => t('Channel settings'), + 'url' => $a->get_baseurl(true).'/settings/channel', + 'selected' => ((argv(1) === 'channel') ? 'active' : ''), + ), + + array( + 'label' => t('Additional features'), + 'url' => $a->get_baseurl(true).'/settings/features', + 'selected' => ((argv(1) === 'features') ? 'active' : ''), + ), + + array( + 'label' => t('Feature settings'), + 'url' => $a->get_baseurl(true).'/settings/featured', + 'selected' => ((argv(1) === 'featured') ? 'active' : ''), + ), + + array( + 'label' => t('Display settings'), + 'url' => $a->get_baseurl(true).'/settings/display', + 'selected' => ((argv(1) === 'display') ? 'active' : ''), + ), + + array( + 'label' => t('Connected apps'), + 'url' => $a->get_baseurl(true) . '/settings/oauth', + 'selected' => ((argv(1) === 'oauth') ? 'active' : ''), + ), + + array( + 'label' => t('Export channel'), + 'url' => $a->get_baseurl(true) . '/uexport/basic', + 'selected' => '' + ), + +// array( +// 'label' => t('Export account'), +// 'url' => $a->get_baseurl(true) . '/uexport/complete', +// 'selected' => '' +// ), + + array( + 'label' => t('Automatic Permissions (Advanced)'), + 'url' => $a->get_baseurl(true) . '/connedit/' . $abook_self_id, + 'selected' => '' + ), + + + ); + + if(feature_enabled(local_user(),'premium_channel')) { + $tabs[] = array( + 'label' => t('Premium Channel Settings'), + 'url' => $a->get_baseurl(true) . '/connect/' . $channel['channel_address'], + 'selected' => '' + ); + + } + + if(feature_enabled(local_user(),'channel_sources')) { + $tabs[] = array( + 'label' => t('Channel Sources'), + 'url' => $a->get_baseurl(true) . '/sources', + 'selected' => '' + ); + + } + + + + $tabtpl = get_markup_template("generic_links_widget.tpl"); + return replace_macros($tabtpl, array( + '$title' => t('Settings'), + '$class' => 'settings-widget', + '$items' => $tabs, + )); + +} + + +function widget_mailmenu($arr) { + if (! local_user()) + return; + + $a = get_app(); + return replace_macros(get_markup_template('message_side.tpl'), array( + '$tabs'=> array(), + + '$check'=>array( + 'label' => t('Check Mail'), + 'url' => $a->get_baseurl(true) . '/message', + 'sel' => (argv(1) == ''), + ), + '$new'=>array( + 'label' => t('New Message'), + 'url' => $a->get_baseurl(true) . '/mail/new', + 'sel'=> (argv(1) == 'new'), + ) + + )); + +} + +function widget_design_tools($arr) { + $a = get_app(); + + // mod menu doesn't load a profile. For any modules which load a profile, check it. + // otherwise local_user() is sufficient for permissions. + + if($a->profile['profile_uid']) + if($a->profile['profile_uid'] != local_user()) + return ''; + + if(! local_user()) + return ''; + + return design_tools(); +} + +function widget_findpeople($arr) { + return findpeople_widget(); +} + + +function widget_photo_albums($arr) { + $a = get_app(); + if(! $a->profile['profile_uid']) + return ''; + $channelx = channelx_by_n($a->profile['profile_uid']); + if((! $channelx) || (! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_photos'))) + return ''; + return photos_album_widget($channelx[0],$a->get_observer()); + +} + + +function widget_vcard($arr) { + return vcard_from_xchan('',get_app()->get_observer()); +} + + +/** + * The following directory widgets are only useful on the directory page + */ + +function widget_dirsafemode($arr) { + return dir_safe_mode(); +} + +function widget_dirsort($arr) { + return dir_sort_links(); +} + +function widget_dirtags($arr) { + return dir_tagblock(z_root() . '/directory',null); +} + +function widget_menu_preview($arr) { + if(! get_app()->data['menu_item']) + return; + require_once('include/menu.php'); + return menu_render(get_app()->data['menu_item']); +} diff --git a/include/zot.php b/include/zot.php index 77d82f110..9d6f462fe 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1384,7 +1384,7 @@ function process_delivery($sender,$arr,$deliveries,$relay) { if((x($arr,'obj_type')) && (activity_match($arr['obj_type'],ACTIVITY_OBJ_EVENT))) { require_once('include/event.php'); $ev = bbtoevent($arr['body']); - if(x($ev,'desc') && x($ev,'start')) { + if(x($ev,'desc') && x($ev,'start')) { $ev['event_xchan'] = $arr['author_xchan']; $ev['uid'] = $channel['channel_id']; $ev['account'] = $channel['channel_account_id']; @@ -1539,6 +1539,9 @@ function delete_imported_item($sender,$item,$uid) { require_once('include/items.php'); drop_item($r[0]['id'],false); + + tag_deliver($uid,$r[0]['id']); + return $r[0]['id']; } @@ -1633,22 +1636,26 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_ $arr = array(); $arr['xprof_hash'] = $hash; - $arr['xprof_desc'] = (($profile['description']) ? htmlentities($profile['description'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : ''); $arr['xprof_dob'] = datetime_convert('','',$profile['birthday'],'Y-m-d'); // !!!! check this for 0000 year $arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0); - $arr['xprof_gender'] = (($profile['gender']) ? htmlentities($profile['gender'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['xprof_marital'] = (($profile['marital']) ? htmlentities($profile['marital'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['xprof_sexual'] = (($profile['sexual']) ? htmlentities($profile['sexual'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['xprof_locale'] = (($profile['locale']) ? htmlentities($profile['locale'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['xprof_region'] = (($profile['region']) ? htmlentities($profile['region'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['xprof_postcode'] = (($profile['postcode']) ? htmlentities($profile['postcode'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['xprof_country'] = (($profile['country']) ? htmlentities($profile['country'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_postcode'] = (($profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : ''); + + $arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : ''); + $arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : ''); $clean = array(); if(array_key_exists('keywords',$profile) and is_array($profile['keywords'])) { import_directory_keywords($hash,$profile['keywords']); foreach($profile['keywords'] as $kw) { - $kw = trim(htmlentities($kw,ENT_COMPAT,'UTF-8',false)); + $kw = trim(htmlspecialchars($kw,ENT_COMPAT,'UTF-8',false)); $kw = trim($kw,','); $clean[] = $kw; } @@ -1692,6 +1699,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_ xprof_region = '%s', xprof_postcode = '%s', xprof_country = '%s', + xprof_about = '%s', + xprof_homepage = '%s', + xprof_hometown = '%s', xprof_keywords = '%s' where xprof_hash = '%s' limit 1", dbesc($arr['xprof_desc']), @@ -1704,6 +1714,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_ dbesc($arr['xprof_region']), dbesc($arr['xprof_postcode']), dbesc($arr['xprof_country']), + dbesc($arr['xprof_about']), + dbesc($arr['xprof_homepage']), + dbesc($arr['xprof_hometown']), dbesc($arr['xprof_keywords']), dbesc($arr['xprof_hash']) ); @@ -1712,7 +1725,7 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_ else { $update = true; logger('import_directory_profile: new profile'); - $x = q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", + $x = q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xrpof_about, xprof_homepage, xprof_hometown, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", dbesc($arr['xprof_hash']), dbesc($arr['xprof_desc']), dbesc($arr['xprof_dob']), @@ -1724,6 +1737,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_ dbesc($arr['xprof_region']), dbesc($arr['xprof_postcode']), dbesc($arr['xprof_country']), + dbesc($arr['xprof_about']), + dbesc($arr['xprof_homepage']), + dbesc($arr['xprof_hometown']), dbesc($arr['xprof_keywords']) ); } @@ -1750,7 +1766,7 @@ function import_directory_keywords($hash,$keywords) { $clean = array(); foreach($keywords as $kw) { - $kw = trim(htmlentities($kw,ENT_COMPAT,'UTF-8',false)); + $kw = trim(htmlspecialchars($kw,ENT_COMPAT,'UTF-8',false)); $kw = trim($kw,','); $clean[] = $kw; } @@ -1849,10 +1865,10 @@ function import_site($arr,$pubkey) { $access_policy = ACCESS_TIERED; } - $directory_url = htmlentities($arr['directory_url'],ENT_COMPAT,'UTF-8',false); - $url = htmlentities($arr['url'],ENT_COMPAT,'UTF-8',false); - $sellpage = htmlentities($arr['sellpage'],ENT_COMPAT,'UTF-8',false); - $site_location = htmlentities($arr['location'],ENT_COMPAT,'UTF-8',false); + $directory_url = htmlspecialchars($arr['directory_url'],ENT_COMPAT,'UTF-8',false); + $url = htmlspecialchars($arr['url'],ENT_COMPAT,'UTF-8',false); + $sellpage = htmlspecialchars($arr['sellpage'],ENT_COMPAT,'UTF-8',false); + $site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false); if($exists) { if(($siterecord['site_flags'] != $site_directory) |