diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/attach.php | 133 | ||||
-rw-r--r-- | include/bbcode.php | 1 | ||||
-rw-r--r-- | include/channel.php | 117 | ||||
-rw-r--r-- | include/conversation.php | 112 | ||||
-rwxr-xr-x | include/dba/dba_driver.php | 8 | ||||
-rwxr-xr-x | include/dba/dba_pdo.php | 14 | ||||
-rw-r--r-- | include/event.php | 10 | ||||
-rw-r--r-- | include/help.php | 2 | ||||
-rw-r--r-- | include/import.php | 40 | ||||
-rwxr-xr-x | include/items.php | 269 | ||||
-rw-r--r-- | include/markdown.php | 431 | ||||
-rw-r--r-- | include/network.php | 595 | ||||
-rw-r--r-- | include/photo/photo_driver.php | 88 | ||||
-rw-r--r-- | include/photos.php | 151 | ||||
-rw-r--r-- | include/text.php | 57 | ||||
-rw-r--r-- | include/widgets.php | 1778 |
16 files changed, 457 insertions, 3349 deletions
diff --git a/include/attach.php b/include/attach.php index 79313ab1a..ac50b05b1 100644 --- a/include/attach.php +++ b/include/attach.php @@ -209,7 +209,7 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $ // Retrieve all columns except 'data' - $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, os_storage, is_dir, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d $sql_extra ORDER BY $orderby $limit", + $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, os_path, display_path, os_storage, is_dir, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d $sql_extra ORDER BY $orderby $limit", intval($channel_id) ); @@ -284,6 +284,7 @@ function attach_by_hash($hash, $observer_hash, $rev = 0) { return $ret; } + function attach_can_view_folder($uid,$ob_hash,$folder_hash) { $sql_extra = permissions_sql($uid,$ob_hash); @@ -348,7 +349,7 @@ function attach_by_hash_nodata($hash, $observer_hash, $rev = 0) { // Now we'll see if we can access the attachment - $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, is_dir, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_extra limit 1", + $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, os_path, display_path, is_dir, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_extra limit 1", intval($r[0]['uid']), dbesc($hash) ); @@ -531,7 +532,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { if($options === 'update' && $arr && array_key_exists('revision',$arr)) $sql_options = " and revision = " . intval($arr['revision']) . " "; - $x = q("select id, aid, uid, filename, filetype, filesize, hash, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d $sql_options limit 1", + $x = q("select id, aid, uid, filename, filetype, filesize, hash, revision, folder, os_storage, is_photo, os_path, display_path, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d $sql_options limit 1", dbesc($arr['hash']), intval($channel_id) ); @@ -702,11 +703,11 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $os_relpath .= $folder_hash . '/'; } - $os_relpath .= $hash; + $os_relpath .= $hash; + $os_relpath = ltrim($os_relpath,'/'); - // not yet used - $os_path = ''; - $display_path = ''; + $os_path = $os_relpath; + $display_path = $pathname . '/' . $filename; if($src) @file_put_contents($os_basepath . $os_relpath,@file_get_contents($src)); @@ -810,7 +811,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { if($is_photo) { - $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct, 'options' => $options ); + $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => $pathname, 'os_syspath' => $os_basepath . $os_relpath, 'os_path' => $os_path, 'display_path' => $display_path, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct, 'options' => $options ); if($arr['contact_allow']) $args['contact_allow'] = $arr['contact_allow']; if($arr['group_allow']) @@ -914,7 +915,7 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { if(count($paths) > 1) { $curpath = array_shift($paths); - $r = q("select hash, id, is_dir from attach where uid = %d and filename = '%s' and is_dir != 0 " . permissions_sql($channel_id) . " limit 1", + $r = q("select hash, id, is_dir from attach where uid = %d and filename = '%s' and is_dir != 0 " . permissions_sql($channel_id,$observer_hash) . " limit 1", intval($channel_id), dbesc($curpath) ); @@ -929,7 +930,7 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { else $paths = array($pathname); - $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, is_photo, is_dir, os_storage, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and folder = '%s' and filename = '%s' and is_dir != 0 " . permissions_sql($channel_id), + $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_path, display_path, is_photo, is_dir, os_storage, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and folder = '%s' and filename = '%s' and is_dir != 0 " . permissions_sql($channel_id), intval($channel_id), dbesc($parent_hash), dbesc($paths[0]) @@ -968,12 +969,15 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $sql_options = ''; - $basepath = 'store/' . $channel['channel_address']; + $os_basepath = 'store/' . $channel['channel_address']; - logger('attach_mkdir: basepath: ' . $basepath); + logger('attach_mkdir: basepath: ' . $os_basepath); - if(! is_dir($basepath)) - os_mkdir($basepath,STORAGE_DEFAULT_PERMISSIONS, true); + if(! is_dir($os_basepath)) + os_mkdir($os_basepath,STORAGE_DEFAULT_PERMISSIONS, true); + + + $os_basepath .= '/'; if(! perm_is_allowed($channel_id, $observer_hash, 'write_storage')) { $ret['message'] = t('Permission denied.'); @@ -1019,10 +1023,13 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $lpath = ''; $lfile = $arr['folder']; + $dpath = ''; + $sql_options = permissions_sql($channel['channel_id']); + do { - $r = q("select filename, hash, flags, is_dir, folder from attach where uid = %d and hash = '%s' and is_dir != 0 + $r = q("select filename, hash, flags, is_dir, folder, display_path from attach where uid = %d and hash = '%s' and is_dir = 1 $sql_options limit 1", intval($channel['channel_id']), dbesc($lfile) @@ -1032,22 +1039,26 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $ret['message'] = t('Path not found.'); return $ret; } + + $dpath = $r[0]['filename'] . (($dpath) ? '/' . $dpath : ''); + if($lfile) - $lpath = $r[0]['hash'] . '/' . $lpath; + $lpath = $r[0]['hash'] . (($lpath) ? '/' . $lpath : ''); + $lfile = $r[0]['folder']; + } while ( ($r[0]['folder']) && intval($r[0]['is_dir'])) ; - $path = $basepath . '/' . $lpath; + + $path = $lpath; } else - $path = $basepath . '/'; - - $path .= $arr['hash']; + $path = ''; $created = datetime_convert(); - // not yet used - $os_path = ''; - $display_path = ''; + $os_path = ltrim($path . '/' . $arr['hash'],'/'); + $display_path = ltrim($dpath . '/' . $arr['filename'],'/'); + $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_dir, content, created, edited, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid ) VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", @@ -1062,7 +1073,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { dbesc($arr['folder']), intval(1), intval(1), - dbescbin($path), + dbescbin($os_basepath . $os_path), dbesc($created), dbesc($created), dbesc($os_path), @@ -1074,7 +1085,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { ); if($r) { - if(os_mkdir($path, STORAGE_DEFAULT_PERMISSIONS, true)) { + if(os_mkdir($os_basepath . $os_path, STORAGE_DEFAULT_PERMISSIONS, true)) { $ret['success'] = true; // update the parent folder's lastmodified timestamp @@ -1092,7 +1103,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $ret['data'] = $z[0]; } else { - logger('attach_mkdir: ' . mkdir . ' ' . $path . ' failed.'); + logger('attach_mkdir: ' . mkdir . ' ' . $os_basepath . $os_path . ' failed.'); $ret['message'] = t('mkdir failed.'); } } @@ -2212,10 +2223,23 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { intval($r[0]['id']) ); + + $x = attach_syspaths($channel_id,$resource_id); + + $t1 = q("update attach set os_path = '%s', display_path = '%s' where id = %d", + dbesc($x['os_path']), + dbesc($x['path']), + intval($r[0]['id']) + ); + + if($r[0]['is_photo']) { - $t = q("update photo set album = '%s', filename = '%s' where resource_id = '%s' and uid = %d", + $t = q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s' + where resource_id = '%s' and uid = %d", dbesc($newdirname), dbesc($filename), + dbesc($x['os_path']), + dbesc($x['path']), dbesc($resource_id), intval($channel_id) ); @@ -2243,8 +2267,9 @@ function attach_folder_select_list($channel_id) { if($r) { foreach($r as $rv) { $x = attach_folder_rpaths($r,$rv); - if($x) + if($x) { $out[$x[0]] = $x[1]; + } } } @@ -2266,7 +2291,6 @@ function attach_folder_rpaths($all_folders,$that_folder) { continue; if($selected['hash'] == $parent_hash) { $path = '/' . $selected['filename'] . $path; - $current_hash = $selected['hash']; $parent_hash = $selected['folder']; $found = true; break; @@ -2280,3 +2304,54 @@ function attach_folder_rpaths($all_folders,$that_folder) { return (($error) ? false : [ $current_hash , $path ]); } + + +function attach_syspaths($channel_id,$attach_hash) { + + $os_path = ''; + $path = ''; + do { + + $r = q("select folder, filename, hash from attach where hash = '%s' and uid = %d", + dbesc($attach_hash), + intval($channel_id) + ); + if(! $r) + break; + + $os_path = $r[0]['hash'] . (($os_path) ? '/' . $os_path : ''); + $path = $r[0]['filename'] . (($path) ? '/' . $path : ''); + $attach_hash = $r[0]['folder']; + } + while($attach_hash); + + return [ 'os_path' => $os_path, 'path' => $path ]; + + +} + + + +function attach_upgrade() { + + $r = q("select id, uid, hash from attach where os_path = '' and display_path = '' limit 100"); + if($r) { + foreach($r as $rv) { + $x = attach_syspaths($rv['uid'],$rv['hash']); + if($x) { + $w = q("update attach set os_path = '%s', display_path = '%s' where id = %d", + dbesc($x['os_path']), + dbesc($x['path']), + intval($rv['id']) + ); + $y = q("update photo set os_path = '%s', display_path = '%s' where uid = %d and resource_id = '%s'", + dbesc($x['os_path']), + dbesc($x['path']), + intval($rv['uid']), + dbesc($rv['hash']) + ); + } + } + } +} + diff --git a/include/bbcode.php b/include/bbcode.php index c0033f280..5aa61760f 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1174,6 +1174,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) $Text = preg_replace("/\[event\-start\](.*?)\[\/event\-start\]/ism",$sub,$Text); + $Text = preg_replace("/\event\](.*?)\[\/event\]/ism",'',$Text); $Text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism",'',$Text); $Text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/ism",'',$Text); $Text = preg_replace("/\[event\-finish\](.*?)\[\/event\-finish\]/ism",'',$Text); diff --git a/include/channel.php b/include/channel.php index b838f8393..465a1524a 100644 --- a/include/channel.php +++ b/include/channel.php @@ -242,24 +242,22 @@ function create_identity($arr) { $expire = 0; - $r = q("insert into channel ( channel_account_id, channel_primary, - channel_name, channel_address, channel_guid, channel_guid_sig, - channel_hash, channel_prvkey, channel_pubkey, channel_pageflags, channel_system, channel_expire_days, channel_timezone ) - values ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' ) ", - - intval($arr['account_id']), - intval($primary), - dbesc($name), - dbesc($nick), - dbesc($guid), - dbesc($sig), - dbesc($hash), - dbesc($key['prvkey']), - dbesc($key['pubkey']), - intval($pageflags), - intval($system), - intval($expire), - dbesc(App::$timezone) + $r = channel_store_lowlevel( + [ + channel_account_id => intval($arr['account_id']), + channel_primary => intval($primary), + channel_name => $name, + channel_address => $nick, + channel_guid => $guid, + channel_guid_sig => $sig, + channel_hash => $hash, + channel_prvkey => $key['prvkey'], + channel_pubkey => $key['pubkey'], + channel_pageflags => intval($pageflags), + channel_system => intval($system), + channel_expire_days => intval($expire), + channel_timezone => App::$timezone + ] ); $r = q("select * from channel where channel_account_id = %d @@ -1153,25 +1151,6 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa // @fixme move this to the diaspora plugin itself - if(plugin_is_installed('diaspora')) { - $diaspora = array( - 'podloc' => z_root(), - 'guid' => $profile['channel_guid'] . str_replace('.','',App::get_hostname()), - 'pubkey' => pemtorsa($profile['channel_pubkey']), - 'searchable' => (($block) ? 'false' : 'true'), - 'nickname' => $profile['channel_address'], - 'fullname' => $profile['channel_name'], - 'firstname' => $firstname, - 'lastname' => $lastname, - 'photo300' => z_root() . '/photo/profile/300/' . $profile['uid'] . '.jpg', - 'photo100' => z_root() . '/photo/profile/100/' . $profile['uid'] . '.jpg', - 'photo50' => z_root() . '/photo/profile/50/' . $profile['uid'] . '.jpg', - ); - } - else - $diaspora = ''; - - $contact_block = contact_block(); $channel_menu = false; @@ -1193,11 +1172,6 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa else $tpl = get_markup_template('profile_vcard.tpl'); - require_once('include/widgets.php'); - -// if(! feature_enabled($profile['uid'],'hide_rating')) - $z = widget_rating(array('target' => $profile['channel_hash'])); - $o .= replace_macros($tpl, array( '$zcard' => $zcard, '$profile' => $profile, @@ -1209,9 +1183,8 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa '$marital' => $marital, '$homepage' => $homepage, '$chanmenu' => $channel_menu, - '$diaspora' => $diaspora, '$reddress' => $reddress, - '$rating' => $z, + '$rating' => '', '$contact_block' => $contact_block, '$editmenu' => profile_edit_menu($profile['uid']) )); @@ -1994,6 +1967,45 @@ function remote_login() { } +function channel_store_lowlevel($arr) { + $store = [ + 'channel_account_id' => ((array_key_exists('channel_account_id',$arr)) ? $arr['channel_account_id'] : '0'), + 'channel_primary' => ((array_key_exists('channel_primary',$arr)) ? $arr['channel_primary'] : '0'), + 'channel_name' => ((array_key_exists('channel_name',$arr)) ? $arr['channel_name'] : ''), + 'channel_address' => ((array_key_exists('channel_address',$arr)) ? $arr['channel_address'] : ''), + 'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''), + 'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''), + 'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''), + 'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'), + 'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''), + 'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''), + 'channel_startpage' => ((array_key_exists('channel_startpage',$arr)) ? $arr['channel_startpage'] : ''), + 'channel_pubkey' => ((array_key_exists('channel_pubkey',$arr)) ? $arr['channel_pubkey'] : ''), + 'channel_prvkey' => ((array_key_exists('channel_prvkey',$arr)) ? $arr['channel_prvkey'] : ''), + 'channel_notifyflags' => ((array_key_exists('channel_notifyflags',$arr)) ? $arr['channel_notifyflags'] : '65535'), + 'channel_pageflags' => ((array_key_exists('channel_pageflags',$arr)) ? $arr['channel_pageflags'] : '0'), + 'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : NULL_DATE), + 'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : NULL_DATE), + 'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : NULL_DATE), + 'channel_max_anon_mail' => ((array_key_exists('channel_max_anon_mail',$arr)) ? $arr['channel_max_anon_mail'] : '10'), + 'channel_max_friend_req' => ((array_key_exists('channel_max_friend_req',$arr)) ? $arr['channel_max_friend_req'] : '10'), + 'channel_expire_days' => ((array_key_exists('channel_expire_days',$arr)) ? $arr['channel_expire_days'] : '0'), + 'channel_passwd_reset' => ((array_key_exists('channel_passwd_reset',$arr)) ? $arr['channel_passwd_reset'] : ''), + 'channel_default_group' => ((array_key_exists('channel_default_group',$arr)) ? $arr['channel_default_group'] : ''), + 'channel_allow_cid' => ((array_key_exists('channel_allow_cid',$arr)) ? $arr['channel_allow_cid'] : ''), + 'channel_allow_gid' => ((array_key_exists('channel_allow_gid',$arr)) ? $arr['channel_allow_gid'] : ''), + 'channel_deny_cid' => ((array_key_exists('channel_deny_cid',$arr)) ? $arr['channel_deny_cid'] : ''), + 'channel_deny_gid' => ((array_key_exists('channel_deny_gid',$arr)) ? $arr['channel_deny_gid'] : ''), + 'channel_removed' => ((array_key_exists('channel_removed',$arr)) ? $arr['channel_removed'] : '0'), + 'channel_system' => ((array_key_exists('channel_system',$arr)) ? $arr['channel_system'] : '0'), + 'channel_moved' => ((array_key_exists('channel_moved',$arr)) ? $arr['channel_moved'] : '') + + ]; + + return create_table_from_array('channel',$store); + +} + function profile_store_lowlevel($arr) { @@ -2252,3 +2264,20 @@ function channel_remove($channel_id, $local = true, $unset_session=false) { } } + +/* + * This checks if a channel is allowed to publish executable code. + * It is up to the caller to determine if the observer or local_channel + * is in fact the resource owner whose channel_id is being checked + */ + +function channel_codeallowed($channel_id) { + + if(! intval($channel_id)) + return false; + + $x = channelx_by_n($channel_id); + if(($x) && ($x['channel_pageflags'] & PAGE_ALLOWCODE)) + return true; + return false; +}
\ No newline at end of file diff --git a/include/conversation.php b/include/conversation.php index da4f974a6..b4f959afa 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -2,10 +2,6 @@ require_once('include/items.php'); -// Note: the code in 'item_extract_images' and 'item_redir_and_replace_images' -// is identical to the code in mod/message.php for 'item_extract_images' and -// 'item_redir_and_replace_images' - function item_extract_images($body) { @@ -375,13 +371,14 @@ function localize_item(&$item){ * * \e array \b children * @return number */ + function count_descendants($item) { $total = count($item['children']); - if ($total > 0) { - foreach ($item['children'] as $child) { - if (! visible_activity($child)) + if($total > 0) { + foreach($item['children'] as $child) { + if(! visible_activity($child)) $total --; $total += count_descendants($child); @@ -408,8 +405,8 @@ function visible_activity($item) { if(intval($item['item_notshown'])) return false; - foreach ($hidden_activities as $act) { - if ((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) { + foreach($hidden_activities as $act) { + if((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) { return false; } } @@ -875,98 +872,6 @@ function best_link_url($item) { -function item_photo_menu($item){ - - $contact = null; - - $ssl_state = false; - - $sub_link=""; - $poke_link=""; - $contact_url=""; - $pm_url=""; - $vsrc_link = ""; - $follow_url = ""; - - $local_channel = local_channel(); - - if($local_channel) { - $ssl_state = true; - if(! count(App::$contacts)) - load_contact_links($local_channel); - $channel = App::get_channel(); - $channel_hash = (($channel) ? $channel['channel_hash'] : ''); - } - - if(($local_channel) && $local_channel == $item['uid']) { - $vsrc_link = 'javascript:viewsrc(' . $item['id'] . '); return false;'; - if($item['parent'] == $item['id'] && $channel && ($channel_hash != $item['author_xchan'])) { - $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;'; - } - if($channel) { - $unsub_link = 'javascript:dounsubthread(' . $item['id'] . '); return false;'; - } - } - - $profile_link = chanlink_hash($item['author_xchan']); - if($item['uid'] > 0) - $pm_url = z_root() . '/mail/new/?f=&hash=' . $item['author_xchan']; - - if(App::$contacts && array_key_exists($item['author_xchan'],App::$contacts)) - $contact = App::$contacts[$item['author_xchan']]; - else - if($local_channel && $item['author']['xchan_addr']) - $follow_url = z_root() . '/follow/?f=&url=' . $item['author']['xchan_addr']; - - if($contact) { - $poke_link = z_root() . '/poke/?f=&c=' . $contact['abook_id']; - if (! intval($contact['abook_self'])) - $contact_url = z_root() . '/connedit/' . $contact['abook_id']; - $posts_link = z_root() . '/network/?cid=' . $contact['abook_id']; - - $clean_url = normalise_link($item['author-link']); - } - - $rating_enabled = get_config('system','rating_enabled'); - - $ratings_url = (($rating_enabled) ? z_root() . '/ratings/' . urlencode($item['author_xchan']) : ''); - - $post_menu = Array( - t("View Source") => $vsrc_link, - t("Follow Thread") => $sub_link, - t("Unfollow Thread") => $unsub_link, - ); - - $author_menu = array( - t("View Profile") => $profile_link, - t("Activity/Posts") => $posts_link, - t("Connect") => $follow_url, - t("Edit Connection") => $contact_url, - t("Message") => $pm_url, - t('Ratings') => $ratings_url, - t("Poke") => $poke_link - ); - - - $args = array('item' => $item, 'post_menu' => $post_menu, 'author_menu' => $author_menu); - - call_hooks('item_photo_menu', $args); - - $menu = array_merge($args['post_menu'],$args['author_menu']); - - $o = ""; - foreach($menu as $k=>$v){ - if(strpos($v,'javascript:') === 0) { - $v = substr($v,11); - $o .= "<li><a href=\"#\" onclick=\"$v\">$k</a></li>\n"; - } - elseif ($v!="") $o .= "<li><a href=\"$v\">$k</a></li>\n"; - } - - return $o; -} - - function thread_action_menu($item,$mode = '') { $menu = []; @@ -1026,14 +931,15 @@ function thread_author_menu($item, $mode = '') { } $profile_link = chanlink_hash($item['author_xchan']); + if($item['uid'] > 0) - $pm_url = z_root() . '/mail/new/?f=&hash=' . $item['author_xchan']; + $pm_url = z_root() . '/mail/new/?f=&hash=' . urlencode($item['author_xchan']); if(App::$contacts && array_key_exists($item['author_xchan'],App::$contacts)) $contact = App::$contacts[$item['author_xchan']]; else if($local_channel && $item['author']['xchan_addr']) - $follow_url = z_root() . '/follow/?f=&url=' . $item['author']['xchan_addr']; + $follow_url = z_root() . '/follow/?f=&url=' . urlencode($item['author']['xchan_addr']); if($contact) { $poke_link = z_root() . '/poke/?f=&c=' . $contact['abook_id']; diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php index e47f97387..ad1d9d194 100755 --- a/include/dba/dba_driver.php +++ b/include/dba/dba_driver.php @@ -15,7 +15,7 @@ class DBA { static public $scheme = 'mysql'; static public $logging = false; - static public $install_script = 'install/schema_mysql.sql'; + static public $install_script = 'schema_mysql.sql'; static public $null_date = '0001-01-01 00:00:00'; static public $utc_now = 'UTC_TIMESTAMP()'; static public $tquot = "`"; @@ -46,7 +46,7 @@ class DBA { if(!($port)) $port = 5432; - self::$install_script = 'install/schema_postgres.sql'; + self::$install_script = 'schema_postgres.sql'; self::$utc_now = "now() at time zone 'UTC'"; self::$tquot = '"'; self::$scheme = 'pgsql'; @@ -163,7 +163,9 @@ abstract class dba_driver { } function get_install_script() { - return \DBA::$install_script; + if(file_exists('install/' . PLATFORM_NAME . '/' . \DBA::$install_script)) + return 'install/' . PLATFORM_NAME . '/' . \DBA::$install_script; + return 'install/' . \DBA::$install_script; } function get_table_quote() { diff --git a/include/dba/dba_pdo.php b/include/dba/dba_pdo.php index f76e6cdd7..f119d8926 100755 --- a/include/dba/dba_pdo.php +++ b/include/dba/dba_pdo.php @@ -74,19 +74,19 @@ class dba_pdo extends dba_driver { return $result; } - if($this->debug) { - db_logger('dba_pdo: DEBUG: ' . printable($sql) . ' returned ' . count($result) . ' results.', LOGGER_NORMAL, LOG_INFO); - } - $r = array(); if($result) { foreach($result as $x) { $r[] = $x; } - if($this->debug) { - db_logger('dba_pdo: ' . printable(print_r($r,true)), LOGGER_NORMAL, LOG_INFO); - } } + + if($this->debug) { + db_logger('dba_pdo: DEBUG: ' . printable($sql) . ' returned ' . count($r) . ' results.', LOGGER_NORMAL, LOG_INFO); + db_logger('dba_pdo: ' . printable(print_r($r,true)), LOGGER_NORMAL, LOG_INFO); + } + + return (($this->error) ? false : $r); } diff --git a/include/event.php b/include/event.php index a9634d7a5..001bd7dd3 100644 --- a/include/event.php +++ b/include/event.php @@ -210,6 +210,10 @@ function format_event_bbcode($ev) { $o = ''; + if($ev['event_vdata']) { + $o .= '[event]' . $ev['event_vdata'] . '[/event]'; + } + if($ev['summary']) $o .= '[event-summary]' . $ev['summary'] . '[/event-summary]'; @@ -610,7 +614,7 @@ function parse_vobject($ical, $type) { $ev['etype'] = $type; $dtstart = $ical->DTSTART->getDateTime(); - $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 1 : 0); + $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 0 : 1); $ev['dtstart'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC', $dtstart->format(\DateTime::W3C)); @@ -751,7 +755,7 @@ function event_import_ical($ical, $uid) { } $dtstart = $ical->DTSTART->getDateTime(); - $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 1 : 0); + $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 0 : 1); // logger('dtstart: ' . var_export($dtstart,true)); @@ -854,7 +858,7 @@ function event_import_ical_task($ical, $uid) { $dtstart = $ical->DTSTART->getDateTime(); - $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 1 : 0); + $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 0 : 1); // logger('dtstart: ' . var_export($dtstart,true)); diff --git a/include/help.php b/include/help.php index e4725575d..ab31e9400 100644 --- a/include/help.php +++ b/include/help.php @@ -57,7 +57,7 @@ function get_help_content($tocpath = false) { if(! $text) { $doctype = 'bbcode'; $text = load_doc_file('doc/main.bb'); - goaway('/help/about/about_hubzilla'); + goaway('/help/about/about'); \App::$page['title'] = t('Help'); } diff --git a/include/import.php b/include/import.php index 5c73b7ca3..d0e15c89d 100644 --- a/include/import.php +++ b/include/import.php @@ -85,12 +85,6 @@ function import_channel($channel, $account_id, $seize) { create_table_from_array('channel',$clean); } - if(! $r) { - logger('mod_import: channel clone failed. ' . print_r($channel,true)); - notice( t('Channel clone failed. Import failed.') . EOL); - return false; - } - $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", intval($account_id), $channel['channel_guid'] // Already dbesc'd @@ -534,16 +528,8 @@ function sync_chatrooms($channel,$chatrooms) { function import_items($channel,$items,$sync = false,$relocate = null) { if($channel && $items) { - $allow_code = false; - $r = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id - where channel_id = %d limit 1", - intval($channel['channel_id']) - ); - if($r) { - if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) { - $allow_code = true; - } - } + + $allow_code = channel_codeallowed($channel['channel_id']); $deliver = false; // Don't deliver any messages or notifications when importing @@ -1358,28 +1344,8 @@ function import_webpage_element($element, $channel, $type) { } // Verify ability to use html or php!!! - $execflag = false; - if($arr['mimetype'] === 'application/x-php' || $arr['mimetype'] === 'text/html') { - $z = q("select account_id, account_roles, channel_pageflags from account " - . "left join channel on channel_account_id = account_id where channel_id = %d limit 1", - intval(local_channel()) - ); - if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) { - $execflag = true; - } - else { - logger('Unable to import element "' . $name .'" because AllowCode permission is denied.'); - notice( t('Unable to import element "' . $name .'" because AllowCode permission is denied.') . EOL); - $element['import_success'] = 0; - return $element; - } - } - -// $z = q("select * from iconfig where v = '%s' and k = '%s' and cat = 'system' limit 1", -// dbesc($name), -// dbesc($namespace) -// ); + $execflag = channel_codeallowed(local_channel()); $i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1", dbesc($arr['mid']), diff --git a/include/items.php b/include/items.php index 36445a46b..3d0f380b4 100755 --- a/include/items.php +++ b/include/items.php @@ -248,8 +248,6 @@ function can_comment_on_post($observer_xchan, $item) { } if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'red')) return true; - if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'diaspora')) - return true; if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],App::get_hostname())) return true; @@ -336,18 +334,6 @@ function post_activity_item($arr,$allow_code = false,$deliver = true) { if(! array_key_exists('mimetype',$arr)) $arr['mimetype'] = 'text/bbcode'; - if(array_key_exists('item_private',$arr) && $arr['item_private']) { - - $arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype'])); - - if($channel) { - if($channel['channel_hash'] === $arr['author_xchan']) { - $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey'])); - $arr['item_verified'] = 1; - } - } - } - $arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : item_message_id()); $arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']); $arr['thr_parent'] = ((x($arr,'thr_parent')) ? $arr['thr_parent'] : $arr['mid']); @@ -542,12 +528,7 @@ function get_item_elements($x,$allow_code = false) { $arr = array(); - if($allow_code) - $arr['body'] = $x['body']; - else - $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : ''); - - $key = get_config('system','pubkey'); + $arr['body'] = $x['body']; $maxlen = get_max_import_size(); @@ -602,11 +583,6 @@ function get_item_elements($x,$allow_code = false) { $arr['sig'] = (($x['signature']) ? htmlspecialchars($x['signature'], ENT_COMPAT,'UTF-8',false) : ''); - if(array_key_exists('diaspora_signature',$x) && is_array($x['diaspora_signature'])) - $x['diaspora_signature'] = json_encode($x['diaspora_signature']); - - $arr['diaspora_meta'] = (($x['diaspora_signature']) ? $x['diaspora_signature'] : ''); - $arr['obj'] = activity_sanitise($x['object']); $arr['target'] = activity_sanitise($x['target']); @@ -659,7 +635,17 @@ function get_item_elements($x,$allow_code = false) { return array(); } + // Check signature on the body text received. + // This presents an issue that we aren't verifying the text that is actually displayed + // on this site. We are however verifying the received text was exactly as received. + // We have every right to strip content that poses a security risk. You are welcome to + // create a plugin to verify the content after filtering if this offends you. + if($arr['sig']) { + + // check the supplied signature against the supplied content. + // Note that we will purify the content which could change it. + $r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", dbesc($arr['author_xchan']) ); @@ -669,6 +655,14 @@ function get_item_elements($x,$allow_code = false) { logger('get_item_elements: message verification failed.'); } + // if the input is markdown, remove one level of html escaping. + // It will be re-applied in item_store() and/or item_store_update(). + // Do this after signature checking as the original signature + // was generated on the escaped content. + + if($arr['mimetype'] === 'text/markdown') + $arr['body'] = \Zotlabs\Lib\MarkdownSoap::unescape($arr['body']); + if(array_key_exists('revision',$x)) { // extended export encoding @@ -771,8 +765,6 @@ function import_author_xchan($x) { if((! array_key_exists('network', $x)) || ($x['network'] === 'zot')) { $y = import_author_zot($x); } - if(! $y) - $y = import_author_diaspora($x); if($x['network'] === 'rss') { $y = import_author_rss($x); @@ -786,36 +778,6 @@ function import_author_xchan($x) { } /** - * @brief Imports an author from Diaspora. - * - * @param array $x an associative array with - * * \e string \b address - * @return boolean|string false on error, otherwise xchan_hash of the new entry - */ -function import_author_diaspora($x) { - if(! $x['address']) - return false; - - $r = q("select * from xchan where xchan_addr = '%s' limit 1", - dbesc($x['address']) - ); - if($r) { - logger('in_cache: ' . $x['address'], LOGGER_DATA); - return $r[0]['xchan_hash']; - } - - if(discover_by_webbie($x['address'])) { - $r = q("select xchan_hash from xchan where xchan_addr = '%s' limit 1", - dbesc($x['address']) - ); - if($r) - return $r[0]['xchan_hash']; - } - - return false; -} - -/** * @brief Imports an author from a RSS feed. * * @param array $x an associative array with @@ -824,6 +786,7 @@ function import_author_diaspora($x) { * * \e string \b guid * @return boolean|string */ + function import_author_rss($x) { if(! $x['url']) return false; @@ -1037,17 +1000,7 @@ function encode_item($item,$mirror = false) { if($item['iconfig']) $x['meta'] = encode_item_meta($item['iconfig'],$mirror); - if($item['diaspora_meta']) { - $z = json_decode($item['diaspora_meta'],true); - if($z) { - if(is_array($z) && array_key_exists('iv',$z)) - $x['diaspora_signature'] = crypto_unencapsulate($z,$key); - else - $x['diaspora_signature'] = $z; - if(! is_array($z)) - logger('encode_item: diaspora meta is not an array: ' . print_r($z,true)); - } - } + logger('encode_item: ' . print_r($x,true), LOGGER_DATA); return $x; @@ -1326,7 +1279,6 @@ function encode_mail($item,$extended = false) { $x['message_parent'] = $item['parent_mid']; $x['created'] = $item['created']; $x['expires'] = $item['expires']; - $x['diaspora_meta'] = $item['diaspora_meta']; $x['title'] = $item['title']; $x['body'] = $item['body']; $x['from'] = encode_item_xchan($item['from']); @@ -1456,6 +1408,26 @@ function get_profile_elements($x) { } + + +function item_sign(&$item) { + + if(array_key_exists('sig',$item) && $item['sig']) + return; + + $r = q("select channel_prvkey from channel where channel_id = %d and channel_hash = '%s' ", + intval($item['uid']), + dbesc($item['author_xchan']) + ); + if(! $r) + return; + + $item['sig'] = base64url_encode(rsa_sign($item['body'],$r[0]['channel_prvkey'])); + $item['item_verified'] = 1; + +} + + /** * @brief * @@ -1519,7 +1491,6 @@ function item_store($arr, $allow_exec = false, $deliver = true) { $arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : ''); $arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : ''); - $arr['diaspora_meta'] = ((x($arr,'diaspora_meta')) ? $arr['diaspora_meta'] : ''); $arr['allow_cid'] = ((x($arr,'allow_cid')) ? trim($arr['allow_cid']) : ''); $arr['allow_gid'] = ((x($arr,'allow_gid')) ? trim($arr['allow_gid']) : ''); $arr['deny_cid'] = ((x($arr,'deny_cid')) ? trim($arr['deny_cid']) : ''); @@ -1533,35 +1504,30 @@ function item_store($arr, $allow_exec = false, $deliver = true) { // obsolete, but needed so as not to throw not-null constraints on some database driveres $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 ); - // only detect language if we have text content, and if the post is private but not yet - // obscured, make it so. - if((! array_key_exists('item_obscured',$arr)) || $arr['item_obscured'] == 0) { - $arr['lang'] = detect_language($arr['body']); - // apply the input filter here - if it is obscured it has been filtered already - $arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype'])); + $arr['lang'] = detect_language($arr['body']); - if(local_channel() && (local_channel() == $arr['uid']) && (! $arr['sig'])) { - $channel = App::get_channel(); - if($channel['channel_hash'] === $arr['author_xchan']) { - $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey'])); - $arr['item_verified'] = 1; - } - } + // apply the input filter here - $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); + $arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec)); - if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { - $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); - call_hooks('item_translate', $translate); - if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) { - logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); - $ret['message'] = 'language not accepted'; - return $ret; - } - $arr = $translate['item']; + item_sign($arr); + + if(! array_key_exists('sig',$arr)) + $arr['sig'] = ''; + + $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); + + if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { + $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); + call_hooks('item_translate', $translate); + if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) { + logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); + $ret['message'] = 'language not accepted'; + return $ret; } + $arr = $translate['item']; } if((x($arr,'obj')) && is_array($arr['obj'])) { @@ -1957,33 +1923,25 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { return $ret; } - if((! array_key_exists('item_obscured', $arr)) || $arr['item_obscured'] == 0) { + $arr['lang'] = detect_language($arr['body']); - $arr['lang'] = detect_language($arr['body']); + // apply the input filter here - // apply the input filter here - if it is obscured it has been filtered already - $arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype'])); + $arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec)); - if(local_channel() && (local_channel() == $arr['uid']) && (! $arr['sig'])) { - $channel = App::get_channel(); - if($channel['channel_hash'] === $arr['author_xchan']) { - $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey'])); - $arr['item_verified'] = 1; - } - } + item_sign($arr); - $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); + $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); - if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { - $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); - call_hooks('item_translate', $translate); - if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) { - logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); - $ret['message'] = 'language not accepted'; - return $ret; - } - $arr = $translate['item']; + if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { + $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); + call_hooks('item_translate', $translate); + if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) { + logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); + $ret['message'] = 'language not accepted'; + return $ret; } + $arr = $translate['item']; } if((x($arr,'obj')) && is_array($arr['obj'])) { @@ -2029,7 +1987,7 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { $arr['changed'] = $orig[0]['changed']; $arr['route'] = ((array_key_exists('route',$arr)) ? trim($arr['route']) : $orig[0]['route']); - $arr['diaspora_meta'] = ((x($arr,'diaspora_meta')) ? $arr['diaspora_meta'] : $orig[0]['diaspora_meta']); + $arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : $orig[0]['location']); $arr['coord'] = ((x($arr,'coord')) ? notags(trim($arr['coord'])) : $orig[0]['coord']); $arr['verb'] = ((x($arr,'verb')) ? notags(trim($arr['verb'])) : $orig[0]['verb']); @@ -2188,55 +2146,6 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { -function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $walltowall = false) { - - // We won't be able to sign Diaspora comments for authenticated visitors - // - we don't have their private key - - // since Diaspora doesn't handle edits we can only do this for the original text and not update it. - - require_once('include/markdown.php'); - $signed_body = bb2diaspora_itembody($datarray,$walltowall); - - if($walltowall) { - logger('wall to wall comment',LOGGER_DEBUG); - // post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author. - $signed_body = "\n\n" - . '![' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_photo_m'] . ')' - . '[' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_url'] . ')' . "\n\n" - . $signed_body; - } - - logger('storing diaspora comment signature',LOGGER_DEBUG); - - $diaspora_handle = channel_reddress($channel); - - $signed_text = $datarray['mid'] . ';' . $parent_item['mid'] . ';' . $signed_body . ';' . $diaspora_handle; - - - if( $channel && $channel['channel_prvkey'] ) - $authorsig = base64_encode(rsa_sign($signed_text, $channel['channel_prvkey'], 'sha256')); - else - $authorsig = ''; - - $x = array('signer' => $diaspora_handle, 'body' => $signed_body, 'signed_text' => $signed_text, 'signature' => $authorsig); - - $y = json_encode($x); - - $r = q("update item set diaspora_meta = '%s' where id = %d", - dbesc($y), - intval($post_id) - ); - - - if(! $r) - logger('store_diaspora_comment_sig: DB write failed'); - - return; -} - - - function send_status_notifications($post_id,$item) { // only send notifications for comments @@ -3773,7 +3682,7 @@ function zot_feed($uid,$observer_hash,$arr) { if(! is_sys_channel($uid)) $sql_extra = item_permissions_sql($uid,$observer_hash); - $limit = " LIMIT 100 "; + $limit = " LIMIT 5000 "; if($mindate > NULL_DATE) { $sql_extra .= " and ( created > '$mindate' or changed > '$mindate' ) "; @@ -3785,15 +3694,7 @@ function zot_feed($uid,$observer_hash,$arr) { } - $items = array(); - - /** @FIXME re-unite these SQL statements. There is no need for them to be separate. The mySQL is convoluted with misuse of group by. As it stands, there is a slight difference where the postgres version doesn't remove the duplicate parents up to 100. In practice this doesn't matter. It could be made to match behavior by adding "distinct on (parent) " to the front of the selection list, at a not-worth-it performance penalty (page temp results to disk). duplicates are still ignored in the in() clause, you just get less than 100 parents if there are many children. */ - - if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { - $groupby = ''; - } else { - $groupby = 'GROUP BY parent'; - } + $items = []; $item_normal = item_normal(); @@ -3802,7 +3703,7 @@ function zot_feed($uid,$observer_hash,$arr) { WHERE uid != %d $item_normal AND item_wall = 1 - and item_private = 0 $sql_extra $groupby ORDER BY created ASC $limit", + and item_private = 0 $sql_extra ORDER BY created ASC $limit", intval($uid) ); } @@ -3810,19 +3711,25 @@ function zot_feed($uid,$observer_hash,$arr) { $r = q("SELECT parent, created, postopts from item WHERE uid = %d $item_normal AND item_wall = 1 - $sql_extra $groupby ORDER BY created ASC $limit", + $sql_extra ORDER BY created ASC $limit", intval($uid) ); } + $parents = []; + if($r) { - for($x = 0; $x < count($r); $x ++) { - if(strpos($r[$x]['postopts'],'nodeliver') !== false) { - unset($r[$x]); - } + foreach($r as $rv) { + if(array_key_exists($rv['parent'],$parents)) + continue; + if(strpos($rv['postopts'],'nodeliver') !== false) + continue; + $parents[$rv['parent']] = $rv; + if(count($parents) > 200) + break; } - $parents_str = ids_to_querystr($r,'parent'); + $parents_str = ids_to_querystr($parents,'parent'); $sys_query = ((is_sys_channel($uid)) ? $sql_extra : ''); $item_normal = item_normal(); diff --git a/include/markdown.php b/include/markdown.php index 7e1f1c42c..841540357 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -81,70 +81,6 @@ function share_unshield($m) { return str_replace($m[1], base64url_decode($x), $m[0]); } - -function diaspora_mention_callback($matches) { - - $webbie = $matches[2] . '@' . $matches[3]; - $link = ''; - if($webbie) { - $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1", - dbesc($webbie) - ); - if(! $r) { - $x = discover_by_webbie($webbie); - if($x) { - $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1", - dbesc($webbie) - ); - } - } - if($r) - $link = $r[0]['xchan_url']; - } - if(! $link) - $link = 'https://' . $matches[3] . '/u/' . $matches[2]; - - if($r && $r[0]['hubloc_network'] === 'zot') - return '@[zrl=' . $link . ']' . trim($matches[1]) . ((substr($matches[0],-1,1) === '+') ? '+' : '') . '[/zrl]' ; - else - return '@[url=' . $link . ']' . trim($matches[1]) . ((substr($matches[0],-1,1) === '+') ? '+' : '') . '[/url]' ; - -} - -function diaspora_mention_callback2($matches) { - - $webbie = $matches[1] . '@' . $matches[2]; - $link = ''; - if($webbie) { - $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1", - dbesc($webbie) - ); - if(! $r) { - $x = discover_by_webbie($webbie); - if($x) { - $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1", - dbesc($webbie) - ); - } - } - if($r) - $link = $r[0]['xchan_url']; - } - - $name = (($r) ? $r[0]['xchan_name'] : $matches[1]); - - if(! $link) - $link = 'https://' . $matches[2] . '/u/' . $matches[1]; - - if($r && $r[0]['hubloc_network'] === 'zot') - return '@[zrl=' . $link . ']' . trim($name) . ((substr($matches[0],-1,1) === '+') ? '+' : '') . '[/zrl]' ; - else - return '@[url=' . $link . ']' . trim($name) . ((substr($matches[0],-1,1) === '+') ? '+' : '') . '[/url]' ; - -} - - - /** * @brief * @@ -157,28 +93,29 @@ function diaspora_mention_callback2($matches) { * @param boolean $use_zrl default false * @return string */ -function markdown_to_bb($s, $use_zrl = false) { - $s = str_replace("
","\r",$s); - $s = str_replace("
\n>","",$s); +function markdown_to_bb($s, $use_zrl = false, $options = []) { + if(is_array($s)) { btlogger('markdown_to_bb called with array. ' . print_r($s,true), LOGGER_NORMAL, LOG_WARNING); return ''; } + + $s = str_replace("
","\r",$s); + $s = str_replace("
\n>","",$s); + $s = html_entity_decode($s,ENT_COMPAT,'UTF-8'); // if empty link text replace with the url $s = preg_replace("/\[\]\((.*?)\)/ism",'[$1]($1)',$s); - // first try plustags + $x = [ 'text' => $s , 'zrl' => $use_zrl, 'options' => $options ]; - $s = preg_replace_callback('/\@\{(.+?)\; (.+?)\@(.+?)\}\+/','diaspora_mention_callback',$s); - $s = preg_replace_callback('/\@\{(.+?)\; (.+?)\@(.+?)\}/','diaspora_mention_callback',$s); + call_hooks('markdown_to_bb_init',$x); - $s = preg_replace_callback('/\@\{(.+?)\@(.+?)\}\+/','diaspora_mention_callback2',$s); - $s = preg_replace_callback('/\@\{(.+?)\@(.+?)\}/','diaspora_mention_callback2',$s); + $s = $x['text']; // Escaping the hash tags - doesn't always seem to work // $s = preg_replace('/\#([^\s\#])/','\\#$1',$s); @@ -193,9 +130,6 @@ function markdown_to_bb($s, $use_zrl = false) { $s = html2bbcode($s); - // protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands - $s = str_replace('♲',html_entity_decode('♲',ENT_QUOTES,'UTF-8'),$s); - // Convert everything that looks like a link to a link if($use_zrl) { $s = str_replace(array('[img','/img]'),array('[zmg','/zmg]'),$s); @@ -217,350 +151,3 @@ function markdown_to_bb($s, $use_zrl = false) { } -function stripdcode_br_cb($s) { - return '[code]' . str_replace('<br />', "\n\t", $s[1]) . '[/code]'; -} - - -////////////////////// -// The following "diaspora_ul" and "diaspora_ol" are only appropriate for the -// pre-Markdownify conversion. If Markdownify isn't used, use the non-Markdownify -// versions below -////////////////////// -/* -function diaspora_ul($s) { - // Replace "[*]" followed by any number (including zero) of - // spaces by "* " to match Diaspora's list format - if( strpos($s[0], "[list]") === 0 ) - return '<ul class="listbullet" style="list-style-type: circle;">' . preg_replace("/\[\*\]( *)/", "* ", $s[1]) . '</ul>'; - elseif( strpos($s[0], "[ul]") === 0 ) - return '<ul class="listbullet" style="list-style-type: circle;">' . preg_replace("/\[\*\]( *)/", "* ", $s[1]) . '</ul>'; - else - return $s[0]; -} - - -function diaspora_ol($s) { - // A hack: Diaspora will create a properly-numbered ordered list even - // if you use '1.' for each element of the list, like: - // 1. First element - // 1. Second element - // 1. Third element - if( strpos($s[0], "[list=1]") === 0 ) - return '<ul class="listdecimal" style="list-style-type: decimal;">' . preg_replace("/\[\*\]( *)/", "1. ", $s[1]) . '</ul>'; - elseif( strpos($s[0], "[list=i]") === 0 ) - return '<ul class="listlowerroman" style="list-style-type: lower-roman;">' . preg_replace("/\[\*\]( *)/", "1. ", $s[1]) . '</ul>'; - elseif( strpos($s[0], "[list=I]") === 0 ) - return '<ul class="listupperroman" style="list-style-type: upper-roman;">' . preg_replace("/\[\*\]( *)/", "1. ", $s[1]) . '</ul>'; - elseif( strpos($s[0], "[list=a]") === 0 ) - return '<ul class="listloweralpha" style="list-style-type: lower-alpha;">' . preg_replace("/\[\*\]( *)/", "1. ", $s[1]) . '</ul>'; - elseif( strpos($s[0], "[list=A]") === 0 ) - return '<ul class="listupperalpha" style="list-style-type: upper-alpha;">' . preg_replace("/\[\*\]( *)/", "1. ", $s[1]) . '</ul>'; - elseif( strpos($s[0], "[ol]") === 0 ) - return '<ul class="listdecimal" style="list-style-type: decimal;">' . preg_replace("/\[\*\]( *)/", "1. ", $s[1]) . '</ul>'; - else - return $s[0]; -} -*/ - -////////////////////// -// Non-Markdownify versions of "diaspora_ol" and "diaspora_ul" -////////////////////// -/** - * @brief - * - * Replace "[\\*]" followed by any number (including zero) of - * spaces by "* " to match Diaspora's list format. - * - * @param string $s - * @return string - */ -function diaspora_ul($s) { - return preg_replace("/\[\\\\\*\]( *)/", "* ", $s[1]); -} - -/** - * @brief - * - * A hack: Diaspora will create a properly-numbered ordered list even - * if you use '1.' for each element of the list, like: - * \code - * 1. First element - * 1. Second element - * 1. Third element - * \endcode - * @param string $s - * @return string - */ -function diaspora_ol($s) { - return preg_replace("/\[\\\\\*\]( *)/", "1. ", $s[1]); -} - -function bb2dmention_callback($match) { - - $r = q("select xchan_addr from xchan where xchan_url = '%s'", - dbesc($match[2]) - ); - - if($r) - return '@{' . $match[3] . ' ; ' . $r[0]['xchan_addr'] . '}'; - - return '@' . $match[3]; -} - - -function bb2diaspora_itemwallwall(&$item,$uplink = false) { - - // We will provide wallwall (embedded author on the Diaspora side) if - // 1. It is a wall-to-wall post - // 2. A comment arrived which has no Diaspora signature info - - - $wallwall = false; - $author_exists = true; - - if(! array_key_exists('author',$item)) { - $author_exists = false; - logger('bb2diaspora_itemwallwall: no author'); - $r = q("select * from xchan where xchan_hash = '%s' limit 1", - dbesc($item['author_xchan']) - ); - if($r) - $item['author'] = $r[0]; - } - - $has_meta = false; - if($item['diaspora_meta'] || get_iconfig($item,'diaspora','fields')) - $has_meta = true; - - if($item['author_xchan'] != $item['owner_xchan']) { - if($item['mid'] == $item['parent_mid']) - $wallwall = true; - else { - if(! $has_meta) { - $wallwall = true; - } - } - } - - if($uplink) - $wallwall = true; - - if(($wallwall) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_s']) { - logger('bb2diaspora_itemwallwall: wall to wall post',LOGGER_DEBUG); - // post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author. - $item['body'] = "\n\n" - . '[quote]' - . '[img]' . $item['author']['xchan_photo_s'] . '[/img]' - . ' ' - . '[url=' . $item['author']['xchan_url'] . '][b]' . $item['author']['xchan_name'] . '[/b][/url]' . "\n\n" - . $item['body'] - . '[/quote]'; - } - - // $item['author'] might cause a surprise further down the line if it wasn't expected to be here. - - if(! $author_exists) - unset($item['author']); -} - - -function bb2diaspora_itembody($item, $force_update = false, $have_channel = false, $uplink = false) { - - if(! get_iconfig($item,'diaspora','fields')) { - $force_update = true; - } - - $matches = array(); - - if(($item['diaspora_meta']) && (! $force_update)) { - $diaspora_meta = json_decode($item['diaspora_meta'],true); - if($diaspora_meta) { - if(array_key_exists('iv',$diaspora_meta)) { - $key = get_config('system','prvkey'); - $meta = json_decode(crypto_unencapsulate($diaspora_meta,$key),true); - } - else { - $meta = $diaspora_meta; - } - if($meta) { - logger('bb2diaspora_itembody: cached '); - $newitem = $item; - $newitem['body'] = $meta['body']; - return $newitem['body']; - } - } - } - - create_export_photo_body($item); - - $newitem = $item; - - if(array_key_exists('item_obscured',$item) && intval($item['item_obscured'])) { - $key = get_config('system','prvkey'); - $b = json_decode($item['body'],true); - // if called from diaspora_process_outbound, this decoding has already been done. - // Everything else that calls us will not yet be decoded. - if($b && is_array($b) && array_key_exists('iv',$b)) { - $newitem['title'] = (($item['title']) ? crypto_unencapsulate(json_decode($item['title'],true),$key) : ''); - $newitem['body'] = (($item['body']) ? crypto_unencapsulate(json_decode($item['body'],true),$key) : ''); - } - } - - if(! $have_channel) - bb2diaspora_itemwallwall($newitem,$uplink); - - $title = $newitem['title']; - $body = preg_replace('/\#\^http/i', 'http', $newitem['body']); - - // protect tags and mentions from hijacking - - if(intval(get_pconfig($item['uid'],'system','prevent_tag_hijacking'))) { - $new_tag = html_entity_decode('⋕',ENT_COMPAT,'UTF-8'); - $new_mention = html_entity_decode('@',ENT_COMPAT,'UTF-8'); - - // #-tags - $body = preg_replace('/\#\[url/i', $new_tag . '[url', $body); - $body = preg_replace('/\#\[zrl/i', $new_tag . '[zrl', $body); - // @-mentions - $body = preg_replace('/\@\!?\[url/i', $new_mention . '[url', $body); - $body = preg_replace('/\@\!?\[zrl/i', $new_mention . '[zrl', $body); - } - - // remove multiple newlines - do { - $oldbody = $body; - $body = str_replace("\n\n\n", "\n\n", $body); - } while ($oldbody != $body); - - $body = bb2diaspora($body); - - if(strlen($title)) - $body = "## " . $title . "\n\n" . $body; - - if($item['attach']) { - $cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item['attach'], $matches, PREG_SET_ORDER); - if($cnt) { - $body .= "\n" . t('Attachments:') . "\n"; - foreach($matches as $mtch) { - $body .= '[' . $mtch[3] . '](' . $mtch[1] . ')' . "\n"; - } - } - } - -// logger('bb2diaspora_itembody : ' . $body, LOGGER_DATA); - - return html_entity_decode($body); -} - -function bb2diaspora($Text, $preserve_nl = false, $fordiaspora = true) { - - // Re-enabling the converter again. - // The bbcode parser now handles youtube-links (and the other stuff) correctly. - // Additionally the html code is now fixed so that lists are now working. - - /* - * Transform #tags, strip off the [url] and replace spaces with underscore - */ - $Text = preg_replace_callback('/#\[([zu])rl\=(\w+.*?)\](\w+.*?)\[\/[(zu)]rl\]/i', create_function('$match', - 'return \'#\'. str_replace(\' \', \'_\', $match[3]);' - ), $Text); - - $Text = preg_replace('/#\^\[([zu])rl\=(\w+.*?)\](\w+.*?)\[\/([zu])rl\]/i', '[$1rl=$2]$3[/$4rl]', $Text); - - $Text = preg_replace_callback('/\@\!?\[([zu])rl\=(\w+.*?)\](\w+.*?)\[\/([zu])rl\]/i', 'bb2dmention_callback', $Text); - - // strip map tags, as the rendering is performed in bbcode() and the resulting output - // is not compatible with Diaspora (at least in the case of openstreetmap and probably - // due to the inclusion of an html iframe) - - $Text = preg_replace("/\[map\=(.*?)\]/ism", '$1', $Text); - $Text = preg_replace("/\[map\](.*?)\[\/map\]/ism", '$1', $Text); - - // Converting images with size parameters to simple images. Markdown doesn't know it. - $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $Text); - - // the following was added on 10-January-2012 due to an inability of Diaspora's - // new javascript markdown processor to handle links with images as the link "text" - // It is not optimal and may be removed if this ability is restored in the future - //if ($fordiaspora) - // $Text = preg_replace("/\[url\=([^\[\]]*)\]\s*\[img\](.*?)\[\/img\]\s*\[\/url\]/ism", - // "[url]$1[/url]\n[img]$2[/img]", $Text); - - // Convert it to HTML - don't try oembed - $Text = bbcode($Text, $preserve_nl, false); - - // Markdownify does not preserve previously escaped html entities such as <> and &. - - $Text = str_replace(array('<','>','&'),array('&_lt_;','&_gt_;','&_amp_;'),$Text); - - // Now convert HTML to Markdown - $md = new Converter(Converter::LINK_AFTER_CONTENT, false, false); - $Text = $md->parseString($Text); - - - // It also adds backslashes to our attempt at getting around the html entity preservation for some weird reason. - - $Text = str_replace(array('&\\_lt\\_;','&\\_gt\\_;','&\\_amp\\_;'),array('<','>','&'),$Text); - - // If the text going into bbcode() has a plain URL in it, i.e. - // with no [url] tags around it, it will come out of parseString() - // looking like: <http://url.com>, which gets removed by strip_tags(). - // So take off the angle brackets of any such URL - $Text = preg_replace("/<http(.*?)>/is", "http$1", $Text); - - // Remove empty zrl links - $Text = preg_replace("/\[zrl\=\].*?\[\/zrl\]/is", "", $Text); - - // Remove all unconverted tags - $Text = strip_tags($Text); - - // Remove any leading or trailing whitespace, as this will mess up - // the Diaspora signature verification and cause the item to disappear - - $Text = trim($Text); - - call_hooks('bb2diaspora', $Text); - - return $Text; -} - -function unescape_underscores_in_links($m) { - $y = str_replace('\\_','_', $m[2]); - return('[' . $m[1] . '](' . $y . ')'); -} - -function format_event_diaspora($ev) { - - if(! ((is_array($ev)) && count($ev))) - return ''; - - $bd_format = t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8 AM - - $o = t('$Projectname event notification:') . "\n"; - - $o .= '**' . (($ev['summary']) ? bb2diaspora($ev['summary']) : bb2diaspora($ev['desc'])) . '**' . "\n"; - - $o .= t('Starts:') . ' ' . '[' - . (($ev['adjust']) ? day_translate(datetime_convert('UTC', 'UTC', - $ev['start'] , $bd_format )) - : day_translate(datetime_convert('UTC', 'UTC', - $ev['start'] , $bd_format))) - . '](' . z_root() . '/localtime/?f=&time=' . urlencode(datetime_convert('UTC','UTC',$ev['start'])) . ")\n"; - - if(! $ev['nofinish']) - $o .= t('Finishes:') . ' ' . '[' - . (($ev['adjust']) ? day_translate(datetime_convert('UTC', 'UTC', - $ev['finish'] , $bd_format )) - : day_translate(datetime_convert('UTC', 'UTC', - $ev['finish'] , $bd_format ))) - . '](' . z_root() . '/localtime/?f=&time=' . urlencode(datetime_convert('UTC','UTC',$ev['finish'])) . ")\n"; - - if(strlen($ev['location'])) - $o .= t('Location:') . bb2diaspora($ev['location']) - . "\n"; - - $o .= "\n"; - - return $o; -} diff --git a/include/network.php b/include/network.php index 6d1a05e9f..bce59d38c 100644 --- a/include/network.php +++ b/include/network.php @@ -984,40 +984,6 @@ function email_header_encode($in_str, $charset = 'UTF-8') { return $out_str; } -function email_send($addr, $subject, $headers, $item) { - //$headers .= 'MIME-Version: 1.0' . "\n"; - //$headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; - //$headers .= 'Content-Type: text/plain; charset=UTF-8' . "\n"; - //$headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; - - $part = uniqid("", true); - - $html = prepare_body($item); - - $headers .= "Mime-Version: 1.0\n"; - $headers .= 'Content-Type: multipart/alternative; boundary="=_'.$part.'"'."\n\n"; - - $body = "\n--=_".$part."\n"; - $body .= "Content-Transfer-Encoding: 8bit\n"; - $body .= "Content-Type: text/plain; charset=utf-8; format=flowed\n\n"; - - $body .= html2plain($html)."\n"; - - $body .= "--=_".$part."\n"; - $body .= "Content-Transfer-Encoding: 8bit\n"; - $body .= "Content-Type: text/html; charset=utf-8\n\n"; - - $body .= '<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">'.$html."</body></html>\n"; - - $body .= "--=_".$part."--"; - - //$message = '<html><body>' . $html . '</body></html>'; - //$message = html2plain($html); - logger('notifier: email delivery to ' . $addr); - mail($addr, $subject, $body, $headers); -} - - function discover_by_url($url,$arr = null) { require_once('library/HTML5/Parser.php'); @@ -1027,10 +993,10 @@ function discover_by_url($url,$arr = null) { if(! $arr) return false; $network = (($arr['network']) ? $arr['network'] : 'unknown'); - $name = (($arr['name']) ? $arr['name'] : 'unknown'); - $photo = (($arr['photo']) ? $arr['photo'] : ''); - $addr = (($arr['addr']) ? $arr['addr'] : ''); - $guid = $url; + $name = (($arr['name']) ? $arr['name'] : 'unknown'); + $photo = (($arr['photo']) ? $arr['photo'] : ''); + $addr = (($arr['addr']) ? $arr['addr'] : ''); + $guid = $url; } $profile = $url; @@ -1067,8 +1033,8 @@ function discover_by_url($url,$arr = null) { if($feed->error()) logger('probe_url: scrape_feed: Error parsing XML: ' . $feed->error()); - $name = unxmlify(trim($feed->get_title())); - $photo = $feed->get_image_url(); + $name = unxmlify(trim($feed->get_title())); + $photo = $feed->get_image_url(); $author = $feed->get_author(); if($author) { @@ -1172,23 +1138,11 @@ function discover_by_url($url,$arr = null) { function discover_by_webbie($webbie) { - require_once('library/HTML5/Parser.php'); - $result = array(); + $result = []; $network = null; - $diaspora = false; - $gnusoc = false; - $dfrn = false; - - $has_salmon = false; - $salmon_key = false; - $atom_feed = false; - $diaspora_base = ''; - $diaspora_guid = ''; - $diaspora_key = ''; - $webbie = strtolower($webbie); $x = webfinger_rfc7033($webbie,true); @@ -1214,21 +1168,6 @@ function discover_by_webbie($webbie) { } } } - if($link['rel'] == NAMESPACE_DFRN) { - $dfrn = $link['href']; - } - if($link['rel'] == 'magic-public-key') { - if(substr($link['href'],0,5) === 'data:') { - $salmon_key = convert_salmon_key($link['href']); - } - } - if($link['rel'] == 'salmon') { - $has_salmon = true; - $salmon = $link['href']; - } - if($link['rel'] == 'http://schemas.google.com/g/2010#updates-from') { - $atom_feed = $link['href']; - } } } } @@ -1240,287 +1179,9 @@ function discover_by_webbie($webbie) { if($arr['success']) return true; - $aliases = array(); - - // Now let's make some decisions on what we may need - // to obtain further info - - $probe_atom = false; - $probe_old = false; - $probe_hcard = false; - - $address = ''; - $location = ''; - $nickname = ''; - $fullname = ''; - $avatar = ''; - $pubkey = ''; - - if(is_array($x)) { - if(array_key_exists('address',$x)) - $address = $x['address']; - if(array_key_exists('location',$x)) - $location = $x['location']; - if(array_key_exists('nickname',$x)) - $nickname = $x['nickname']; - } - - if(! $x) - $probe_old = true; - - - if((! $dfrn) && (! $has_salmon)) - $probe_old = true; - - if($probe_old) { - $y = old_webfinger($webbie); - if($y) { - logger('old_webfinger: ' . print_r($x,true)); - foreach($y as $link) { - if($link['@attributes']['rel'] === NAMESPACE_DFRN) - $dfrn = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'salmon') - $notify = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === NAMESPACE_FEED) - $poll = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') - $hcard = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') - $profile = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0') - $poco = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') { - $diaspora_base = unamp($link['@attributes']['href']); - $diaspora = true; - } - if($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') { - $diaspora_guid = unamp($link['@attributes']['href']); - $diaspora = true; - } - if($link['@attributes']['rel'] === 'diaspora-public-key') { - $diaspora_key = base64_decode(unamp($link['@attributes']['href'])); - if(strstr($diaspora_key,'RSA ')) - $pubkey = rsatopem($diaspora_key); - else - $pubkey = $diaspora_key; - $diaspora = true; - } - if($link['@attributes']['rel'] == 'magic-public-key') { - if(substr($link['@attributes']['href'],0,5) === 'data:') { - $salmon_key = convert_salmon_key($link['@attributes']['href']); - } - } - if($link['@attributes']['rel'] == 'salmon') { - $has_salmon = true; - $salmon = $link['@attributes']['href']; - } - - if($link['@attributes']['rel'] == 'http://schemas.google.com/g/2010#updates-from') { - $atom_feed = $link['@attributes']['href']; - } - if($link['@attributes']['rel'] === 'alias') { - $aliases[] = $link['@attributes']['href']; - } - if($link['@attributes']['rel'] === 'subject') { - $subject = $link['@attributes']['href']; - } - } - } - } - - if($subject || $aliases) { - if(strpos($webbie,'@')) { - $rhs = substr($webbie,strpos($webbie,'@')+1); - } - else { - $m = parse_url($webbie); - if($m) { - $rhs = $m['host'] . (($m['port']) ? ':' . $m['port'] : ''); - } - } - - $v = array('subject' => $subject,'aliases' => $aliases); - $address = find_webfinger_address($v,$rhs); - $location = find_webfinger_location($v,$rhs); - if($address) - $nickname = substr($address,0,strpos($address,'@')); - - } - - if($salmon_key && $has_salmon && $atom_feed && (! $dfrn) && (! $diaspora)) { - $gnusoc = true; - $probe_atom = true; - } - - if(! $pubkey) - $pubkey = $salmon_key; - - if(($dfrn || $diaspora) && $hcard) - $probe_hcard = true; - - if(! $fullname) - $fullname = $nickname; - - if($probe_atom) { - $k = z_fetch_url($atom_feed); - if($k['success']) - $feed_meta = feed_meta($k['body']); - if($feed_meta) { - - // stash any discovered pubsubhubbub hubs in case we need to follow them - // this will save an expensive lookup later - - if($feed_meta['hubs'] && $address) { - set_xconfig($address,'system','push_hubs',$feed_meta['hubs']); - set_xconfig($address,'system','feed_url',$atom_feed); - } - if($feed_meta['author']['author_name']) { - $fullname = $feed_meta['author']['author_name']; - } - if(! $avatar) { - if($feed_meta['author']['author_photo']) - $avatar = $feed_meta['author']['author_photo']; - } - - // for GNU-social over-ride any url aliases we may have picked up in webfinger - // The author.uri element in the feed is likely to be more accurate - - if($gnusoc && $feed_meta['author']['author_uri']) - $location = $feed_meta['author']['author_uri']; - } - } - else { - if($probe_hcard) { - $vcard = scrape_vcard($hcard); - if($vcard) { - logger('vcard: ' . print_r($vcard,true), LOGGER_DATA); - if($vcard['fn']) - $fullname = $vcard['fn']; - if($vcard['photo'] && (strpos($vcard['photo'],'http') !== 0)) - $vcard['photo'] = $diaspora_base . '/' . $vcard['photo']; - if(($vcard['public_key']) && (! $pubkey)) { - $diaspora_key = $vcard['public_key']; - if(strstr($diaspora_key,'RSA ')) - $pubkey = rsatopem($diaspora_key); - else - $pubkey = $diaspora_key; - } - if(! $avatar) - $avatar = $vcard['photo']; - if($diaspora) { - if(($vcard['uid']) && (! $diaspora_guid)) - $diaspora_guid = $vcard['uid']; - if(($vcard['url']) && (! $diaspora_base)) - $diaspora_base = $vcard['url']; - - - - - } - - } - } - } - - if(($profile) && (! $location)) - $location = $profile; - - if($location) { - $m = parse_url($location); - $base = $m['scheme'] . '://' . $m['host']; - $host = $m['host']; - } - - - if($diaspora && $diaspora_base && $diaspora_guid) { - if($dfrn) - $network = 'friendica-over-diaspora'; - else - $network = 'diaspora'; - - $base = trim($diaspora_base,'/'); - $notify = $base . '/receive'; - - } - else { - if($gnusoc) { - $network = 'gnusoc'; - $notify = $salmon; - } - } - - - logger('network: ' . $network); - logger('address: ' . $address); - logger('fullname: ' . $fullname); - logger('pubkey: ' . $pubkey); - logger('location: ' . $location); - - - - // if we have everything we need, let's create the records - - if($network && $address && $fullname && $pubkey && $location) { - $r = q("select * from xchan where xchan_hash = '%s' limit 1", - dbesc($address) - ); - if($r) { - $r = q("update xchan set xchan_name = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", - dbesc($fullname), - dbesc($network), - dbesc(datetime_convert()), - dbesc($address) - ); - } - else { - $r = xchan_store_lowlevel( - [ - 'xchan_hash' => $address, - 'xchan_guid' => (($diaspora_guid) ? $diaspora_guid : $location), - 'xchan_pubkey' => $pubkey, - 'xchan_addr' => $address, - 'xchan_url' => $location, - 'xchan_name' => $fullname, - 'xchan_name_date' => datetime_convert(), - 'xchan_network' => $network - ] - ); - } - - $r = q("select * from hubloc where hubloc_hash = '%s' limit 1", - dbesc($address) - ); - - if(! $r) { - $r = hubloc_store_lowlevel( - [ - 'hubloc_guid' => (($diaspora_guid) ? $diaspora_guid : $location), - 'hubloc_hash' => $address, - 'hubloc_addr' => $address, - 'hubloc_network' => $network, - 'hubloc_url' => $base, - 'hubloc_host' => $host, - 'hubloc_callback' => $notify, - 'hubloc_updated' => datetime_convert(), - 'hubloc_primary' => 1 - ] - ); - } - $photos = import_xchan_photo($avatar,$address); - $r = 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'", - dbescdate(datetime_convert()), - dbesc($photos[0]), - dbesc($photos[1]), - dbesc($photos[2]), - dbesc($photos[3]), - dbesc($address) - ); - return true; - } return false; -} - +} function webfinger_rfc7033($webbie,$zot = false) { @@ -1547,88 +1208,13 @@ function webfinger_rfc7033($webbie,$zot = false) { if($s['success']) { $j = json_decode($s['body'],true); - - // We could have a number of URL aliases and webbies - // make an executive decision about the most likely "best" of each - // by comparing against some examples from known networks we're likely to encounter. - // Otherwise we have to store every alias that we may ever encounter and - // validate every URL we ever find against every possible alias - - // @fixme pump.io is going to be a real bugger since it doesn't return subject or aliases - // or provide lookup by url - - $j['address'] = find_webfinger_address($j,$rhs); - $j['location'] = find_webfinger_location($j,$rhs); - if($j['address']) - $j['nickname'] = substr($j['address'],0,strpos($j['address'],'@')); - } - else - return false; - - return($j); -} - -function find_webfinger_address($j,$rhs) { - if(is_array($j) && ($j)) { - if(strpos($j['subject'],'acct:') !== false && strpos($j['subject'],'@' . $rhs)) - return str_replace('acct:','',$j['subject']); - if($j['aliases']) { - foreach($j['aliases'] as $alias) { - if(strpos($alias,'acct:') !== false && strpos($alias,'@' . $rhs)) { - return str_replace('acct:','',$alias); - } - } - } - } - return ''; -} - - -function find_webfinger_location($j,$rhs) { - if(is_array($j) && ($j)) { - if(strpos($j['subject'],'http') === 0) { - $x = match_webfinger_location($j['subject'],$rhs); - if($x) - return $x; - } - if($j['aliases']) { - foreach($j['aliases'] as $alias) { - if(strpos($alias,'http') === 0) { - $x = match_webfinger_location($alias,$rhs); - if($x) - return($x); - } - } - } + return($j); } - return ''; -} -function match_webfinger_location($s,$h) { - - // GNU-social and the older StatusNet - the $host/user/123 form doesn't work - if(preg_match('|' . $h . '/index.php/user/([0-9]*?)$|',$s)) - return $s; - // Redmatrix / hubzilla - if(preg_match('|' . $h . '/channel/|',$s)) - return $s; - // Friendica - if(preg_match('|' . $h . '/profile/|',$s)) - return $s; + return false; - $arr = array('test' => $s, 'host' => $h, 'success' => false); - call_hooks('match_webfinger_location',$arr); - if($arr['success']) - return $s; - return ''; } - - - - - - function old_webfinger($webbie) { $host = ''; @@ -1696,9 +1282,6 @@ function fetch_xrd_links($url) { if ((! $xml) || (! stristr($xml,'<xrd'))) return array(); - // fix diaspora's bad xml - $xml = str_replace(array('href="','"/>'),array('href="','"/>'),$xml); - $h = parse_xml_string($xml); if(! $h) return array(); @@ -1738,85 +1321,6 @@ function fetch_xrd_links($url) { } -function scrape_vcard($url) { - - $ret = array(); - - logger('scrape_vcard: url=' . $url); - - $x = z_fetch_url($url); - if(! $x['success']) - return $ret; - - $s = $x['body']; - - if(! $s) - return $ret; - - $headers = $x['header']; - $lines = explode("\n",$headers); - if(count($lines)) { - foreach($lines as $line) { - // don't try and run feeds through the html5 parser - if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml')))) - return ret; - } - } - - try { - $dom = HTML5_Parser::parse($s); - } catch (DOMException $e) { - logger('scrape_vcard: parse error: ' . $e); - } - - if(! $dom) - return $ret; - - // Pull out hCard profile elements - - $largest_photo = 0; - - $items = $dom->getElementsByTagName('*'); - foreach($items as $item) { - if(attribute_contains($item->getAttribute('class'), 'vcard')) { - $level2 = $item->getElementsByTagName('*'); - foreach($level2 as $x) { - if(attribute_contains($x->getAttribute('id'),'pod_location')) - $ret['pod_location'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'fn')) - $ret['fn'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'uid')) - $ret['uid'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'nickname')) - $ret['nick'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'searchable')) - $ret['searchable'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'key')) - $ret['public_key'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'given_name')) - $ret['given_name'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'family_name')) - $ret['family_name'] = $x->textContent; - if(attribute_contains($x->getAttribute('class'),'url')) - $ret['url'] = $x->textContent; - - if((attribute_contains($x->getAttribute('class'),'photo')) - || (attribute_contains($x->getAttribute('class'),'avatar'))) { - $size = intval($x->getAttribute('width')); - if(($size > $largest_photo) || (! $largest_photo)) { - $ret['photo'] = $x->getAttribute('src'); - $largest_photo = $size; - } - } - } - } - } - - return $ret; -} - - - function scrape_feed($url) { $ret = array(); @@ -1910,31 +1414,6 @@ function scrape_feed($url) { } - -function service_plink($contact, $guid) { - - $plink = ''; - - $m = parse_url($contact['xchan_url']); - if($m) { - $url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : ''); - } - else - $url = 'https://' . substr($contact['xchan_addr'],strpos($contact['xchan_addr'],'@')+1); - - $handle = substr($contact['xchan_addr'], 0, strpos($contact['xchan_addr'],'@')); - - if($contact['xchan_network'] === 'diaspora') - $plink = $url . '/posts/' . $guid; - if($contact['xchan_network'] === 'friendica-over-diaspora') - $plink = $url . '/display/' . $handle . '/' . $guid; - if($contact['xchan_network'] === 'zot') - $plink = $url . '/channel/' . $handle . '?f=&mid=' . $guid; - - return $plink; -} - - function format_and_send_email($sender,$xchan,$item) { $title = $item['title']; @@ -1944,7 +1423,7 @@ function format_and_send_email($sender,$xchan,$item) { $htmlversion = bbcode(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)); - $banner = t('$Projectname Notification'); + $banner = t('$Projectname Notification'); $product = t('$projectname'); // PLATFORM_NAME; $siteurl = z_root(); $thanks = t('Thank You,'); @@ -2132,33 +1611,33 @@ function get_site_info() { - $data = Array( - 'version' => $version, - 'version_tag' => $tag, - 'server_role' => Zotlabs\Lib\System::get_server_role(), - 'commit' => $commit, - 'url' => z_root(), - 'plugins' => $visible_plugins, - 'register_policy' => $register_policy[get_config('system','register_policy')], - 'invitation_only' => intval(get_config('system','invitation_only')), - 'directory_mode' => $directory_mode[get_config('system','directory_mode')], - 'language' => get_config('system','language'), - 'rss_connections' => intval(get_config('system','feed_contacts')), - 'expiration' => $site_expire, + $data = [ + 'url' => z_root(), + 'platform' => Zotlabs\Lib\System::get_platform_name(), + 'site_name' => (($site_name) ? $site_name : ''), + 'version' => $version, + 'version_tag' => $tag, + 'server_role' => Zotlabs\Lib\System::get_server_role(), + 'commit' => $commit, + 'plugins' => $visible_plugins, + 'register_policy' => $register_policy[get_config('system','register_policy')], + 'invitation_only' => intval(get_config('system','invitation_only')), + 'directory_mode' => $directory_mode[get_config('system','directory_mode')], + 'language' => get_config('system','language'), + 'rss_connections' => intval(get_config('system','feed_contacts')), + 'expiration' => $site_expire, 'default_service_restrictions' => $service_class, - 'locked_features' => $locked_features, - 'admin' => $admin, - 'site_name' => (($site_name) ? $site_name : ''), - 'platform' => Zotlabs\Lib\System::get_platform_name(), - 'dbdriver' => DBA::$dba->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 - ); + 'locked_features' => $locked_features, + 'admin' => $admin, + 'dbdriver' => DBA::$dba->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 + ]; return $data; } diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index c8b3c3782..923e34dbe 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -380,7 +380,7 @@ abstract class photo_driver { dbesc($p['album']), intval($this->getHeight()), intval($this->getWidth()), - (intval($p['os_storage']) ? dbescbin($p['os_path']) : dbescbin($this->imageString())), + (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), intval(strlen($this->imageString())), intval($p['imgscale']), @@ -411,7 +411,7 @@ abstract class photo_driver { dbesc($p['album']), intval($this->getHeight()), intval($this->getWidth()), - (intval($p['os_storage']) ? dbescbin($p['os_path']) : dbescbin($this->imageString())), + (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), intval(strlen($this->imageString())), intval($p['imgscale']), @@ -429,90 +429,6 @@ abstract class photo_driver { return $r; } - - // should be obsolete now - - public function store($aid, $uid, $xchan, $rid, $filename, $album, $scale, $usage = PHOTO_NORMAL, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '') { - - $x = q("select id from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1", - dbesc($rid), - intval($uid), - dbesc($xchan), - intval($scale) - ); - if(count($x)) { - $r = q("UPDATE photo - set aid = %d, - uid = %d, - xchan = '%s', - resource_id = '%s', - created = '%s', - edited = '%s', - filename = '%s', - mimetype = '%s', - album = '%s', - height = %d, - width = %d, - content = '%s', - filesize = %d, - imgscale = %d, - photo_usage = %d, - allow_cid = '%s', - allow_gid = '%s', - deny_cid = '%s', - deny_gid = '%s' - where id = %d", - - intval($aid), - intval($uid), - dbesc($xchan), - dbesc($rid), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc(basename($filename)), - dbesc($this->getType()), - dbesc($album), - intval($this->getHeight()), - intval($this->getWidth()), - dbescbin($this->imageString()), - intval(strlen($this->imageString())), - intval($scale), - intval($photo_usage), - dbesc($allow_cid), - dbesc($allow_gid), - dbesc($deny_cid), - dbesc($deny_gid), - intval($x[0]['id']) - ); - } - else { - $r = q("INSERT INTO photo - ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, filesize, imgscale, photo_usage, allow_cid, allow_gid, deny_cid, deny_gid ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s' )", - intval($aid), - intval($uid), - dbesc($xchan), - dbesc($rid), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc(basename($filename)), - dbesc($this->getType()), - dbesc($album), - intval($this->getHeight()), - intval($this->getWidth()), - dbescbin($this->imageString()), - intval(strlen($this->imageString())), - intval($scale), - intval($photo_usage), - dbesc($allow_cid), - dbesc($allow_gid), - dbesc($deny_cid), - dbesc($deny_gid) - ); - } - return $r; - } - } diff --git a/include/photos.php b/include/photos.php index c0f7dc8c4..eae9689a9 100644 --- a/include/photos.php +++ b/include/photos.php @@ -17,6 +17,7 @@ require_once('include/text.php'); * @param array $args * @return array */ + function photo_upload($channel, $observer, $args) { $ret = array('success' => false); @@ -28,9 +29,6 @@ function photo_upload($channel, $observer, $args) { return $ret; } - -//call_hooks('photo_upload_begin', $args); - /* * Determine the album to use */ @@ -67,8 +65,8 @@ function photo_upload($channel, $observer, $args) { $os_storage = 0; - if($args['os_path'] && $args['getimagesize']) { - $imagedata = @file_get_contents($args['os_path']); + if($args['os_syspath'] && $args['getimagesize']) { + $imagedata = @file_get_contents($args['os_syspath']); $filename = $args['filename']; $filesize = strlen($imagedata); // this is going to be deleted if it exists @@ -90,8 +88,6 @@ function photo_upload($channel, $observer, $args) { } else { $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); -// call_hooks('photo_upload_file',$f); - if (x($f,'src') && x($f,'filesize')) { $src = $f['src']; $filename = $f['filename']; @@ -153,7 +149,7 @@ function photo_upload($channel, $observer, $args) { return $ret; } - $exif = $ph->orient(($args['os_path']) ? $args['os_path'] : $src); + $exif = $ph->orient(($args['os_syspath']) ? $args['os_syspath'] : $src); @unlink($src); @@ -180,7 +176,8 @@ function photo_upload($channel, $observer, $args) { 'filename' => $filename, 'album' => $album, 'imgscale' => 0, 'photo_usage' => PHOTO_NORMAL, 'allow_cid' => $ac['allow_cid'], 'allow_gid' => $ac['allow_gid'], 'deny_cid' => $ac['deny_cid'], 'deny_gid' => $ac['deny_gid'], - 'os_storage' => $os_storage, 'os_path' => $args['os_path'] + 'os_storage' => $os_storage, 'os_syspath' => $args['os_syspath'], + 'os_path' => $args['os_path'], 'display_path' => $args['display_path'] ); if($args['created']) $p['created'] = $args['created']; @@ -205,7 +202,7 @@ function photo_upload($channel, $observer, $args) { $errors = true; unset($p['os_storage']); - unset($p['os_path']); + unset($p['os_syspath']); if(($width > 1024 || $height > 1024) && (! $errors)) $ph->scaleImage(1024); @@ -336,19 +333,13 @@ function photo_upload($channel, $observer, $args) { if($item['mid'] === $item['parent_mid']) { $item['body'] = $summary; + $item['mimetype'] = 'text/bbcode'; $item['obj_type'] = ACTIVITY_OBJ_PHOTO; $item['obj'] = json_encode($object); $item['tgt_type'] = ACTIVITY_OBJ_ALBUM; $item['target'] = json_encode($target); - if($item['author_xchan'] === $channel['channel_hash']) { - $item['sig'] = base64url_encode(rsa_sign($item['body'],$channel['channel_prvkey'])); - $item['item_verified'] = 1; - } - else { - $item['sig'] = ''; - } $force = true; } @@ -374,37 +365,37 @@ function photo_upload($channel, $observer, $args) { else { $mid = item_message_id(); - $arr = array(); + $arr = [ + 'aid' => $account_id, + 'uid' => $channel_id, + 'mid' => $mid, + 'parent_mid' => $mid, + 'item_hidden' => $item_hidden, + 'resource_type' => 'photo', + 'resource_id' => $photo_hash, + 'owner_xchan' => $channel['channel_hash'], + 'author_xchan' => $observer['xchan_hash'], + 'title' => $title, + 'allow_cid' => $ac['allow_cid'], + 'allow_gid' => $ac['allow_gid'], + 'deny_cid' => $ac['deny_cid'], + 'deny_gid' => $ac['deny_gid'], + 'verb' => ACTIVITY_POST, + 'obj_type' => ACTIVITY_OBJ_PHOTO, + 'obj' => json_encode($object), + 'tgt_type' => ACTIVITY_OBJ_ALBUM, + 'target' => json_encode($target), + 'item_wall' => $visible, + 'item_origin' => 1, + 'item_thread_top' => 1, + 'item_private' => intval($acl->is_private()), + 'body' => $summary + ]; - if($lat && $lon) - $arr['coord'] = $lat . ' ' . $lon; - - $arr['aid'] = $account_id; - $arr['uid'] = $channel_id; - $arr['mid'] = $mid; - $arr['parent_mid'] = $mid; - $arr['item_hidden'] = $item_hidden; - $arr['resource_type'] = 'photo'; - $arr['resource_id'] = $photo_hash; - $arr['owner_xchan'] = $channel['channel_hash']; - $arr['author_xchan'] = $observer['xchan_hash']; - $arr['title'] = $title; - $arr['allow_cid'] = $ac['allow_cid']; - $arr['allow_gid'] = $ac['allow_gid']; - $arr['deny_cid'] = $ac['deny_cid']; - $arr['deny_gid'] = $ac['deny_gid']; - $arr['verb'] = ACTIVITY_POST; - $arr['obj_type'] = ACTIVITY_OBJ_PHOTO; - $arr['obj'] = json_encode($object); - $arr['tgt_type'] = ACTIVITY_OBJ_ALBUM; - $arr['target'] = json_encode($target); - $arr['item_wall'] = 1; - $arr['item_origin'] = 1; - $arr['item_thread_top'] = 1; - $arr['item_private'] = intval($acl->is_private()); $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']); - $arr['body'] = $summary; + if($lat && $lon) + $arr['coord'] = $lat . ' ' . $lon; // this one is tricky because the item and the photo have the same permissions, those of the photo. // Use the channel read_stream permissions to get the correct public_policy for the item and recalculate the @@ -451,7 +442,8 @@ function photo_upload($channel, $observer, $args) { * * \e boolean \b success * * \e array \b albums */ -function photos_albums_list($channel, $observer, $sort_key = 'album', $direction = 'asc') { + +function photos_albums_list($channel, $observer, $sort_key = 'display_path', $direction = 'asc') { $channel_id = $channel['channel_id']; $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); @@ -464,17 +456,33 @@ function photos_albums_list($channel, $observer, $sort_key = 'album', $direction $sort_key = dbesc($sort_key); $direction = dbesc($direction); - //$albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and photo_usage IN ( %d, %d ) $sql_extra group by album order by $sort_key $direction", - // intval($channel_id), - // intval(PHOTO_NORMAL), - // intval(PHOTO_PROFILE) - //); - - // this query provides the same results but might perform better - $albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and os_storage = 1 $sql_extra group by album order by $sort_key $direction", + $r = q("select display_path, hash from attach where is_dir = 1 and uid = %d $sql_extra order by $sort_key $direction", intval($channel_id) ); + array_unshift($r,[ 'display_path' => '/', 'hash' => '' ]); + $str = ids_to_querystr($r,'hash',true); + + $albums = []; + + if($str) { + $x = q("select count( distinct hash ) as total, folder from attach where is_photo = 1 and uid = %d and folder in ( $str ) $sql_extra group by folder ", + intval($channel_id) + ); + if($x) { + foreach($r as $rv) { + foreach($x as $xv) { + if($xv['folder'] === $rv['hash']) { + if($xv['total'] != 0 && attach_can_view_folder($channel_id,$observer_xchan,$xv['folder'])) { + $albums[] = [ 'album' => $rv['display_path'], 'folder' => $xv['folder'], 'total' => $xv['total'] ]; + } + continue; + } + } + } + } + } + // add various encodings to the array so we can just loop through and pick them out in a template $ret = array('success' => false); @@ -485,11 +493,12 @@ function photos_albums_list($channel, $observer, $sort_key = 'album', $direction foreach($albums as $k => $album) { $entry = array( 'text' => (($album['album']) ? $album['album'] : '/'), + 'shorttext' => (($album['album']) ? ellipsify($album['album'],28) : '/'), 'jstext' => (($album['album']) ? addslashes($album['album']) : '/'), 'total' => $album['total'], - 'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album['album']), + 'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . $album['folder'], 'urlencode' => urlencode($album['album']), - 'bin2hex' => bin2hex($album['album']) + 'bin2hex' => $album['folder'] ); $ret['albums'][] = $entry; } @@ -500,7 +509,7 @@ function photos_albums_list($channel, $observer, $sort_key = 'album', $direction return $ret; } -function photos_album_widget($channelx,$observer,$sortkey = 'album',$direction = 'asc') { +function photos_album_widget($channelx,$observer,$sortkey = 'display_path',$direction = 'asc') { $o = ''; @@ -513,6 +522,7 @@ function photos_album_widget($channelx,$observer,$sortkey = 'album',$direction = $o = replace_macros(get_markup_template('photo_albums.tpl'),array( '$nick' => $channelx['channel_address'], '$title' => t('Photo Albums'), + '$recent' => t('Recent Photos'), '$albums' => $albums['albums'], '$baseurl' => z_root(), '$upload' => ((perm_is_allowed($channelx['channel_id'],(($observer) ? $observer['xchan_hash'] : ''),'write_storage')) @@ -531,6 +541,7 @@ function photos_album_widget($channelx,$observer,$sortkey = 'album',$direction = * @param string $album default empty * @return boolean|array */ + function photos_list_photos($channel, $observer, $album = '') { $channel_id = $channel['channel_id']; @@ -570,13 +581,17 @@ function photos_list_photos($channel, $observer, $album = '') { * @param string $album name of the album * @return boolean */ -function photos_album_exists($channel_id, $album) { - $r = q("SELECT id FROM photo WHERE album = '%s' AND uid = %d limit 1", + +function photos_album_exists($channel_id, $observer_hash, $album) { + + $sql_extra = permissions_sql($channel_id,$observer_hash); + + $r = q("SELECT folder, hash, is_dir, filename, os_path, display_path FROM attach WHERE hash = '%s' AND is_dir = 1 AND uid = %d $sql_extra limit 1", dbesc($album), intval($channel_id) ); - return (($r) ? true : false); + return (($r) ? $r[0] : false); } /** @@ -589,6 +604,7 @@ function photos_album_exists($channel_id, $album) { * @param string $newname The new name of the album * @return bool|array */ + function photos_album_rename($channel_id, $oldname, $newname) { return q("UPDATE photo SET album = '%s' WHERE album = '%s' AND uid = %d", dbesc($newname), @@ -607,16 +623,18 @@ function photos_album_rename($channel_id, $oldname, $newname) { * @param string $remote_xchan * @return string|boolean */ + function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { - if ($remote_xchan) { - $r = q("SELECT distinct resource_id from photo where xchan = '%s' and uid = %d and album = '%s' ", + if($remote_xchan) { + $r = q("SELECT hash from attach where creator = '%s' and uid = %d and folder = '%s' ", dbesc($remote_xchan), intval($channel_id), dbesc($album) ); - } else { - $r = q("SELECT distinct resource_id from photo where uid = %d and album = '%s' ", + } + else { + $r = q("SELECT hash from attach where uid = %d and folder = '%s' ", intval($channel_id), dbesc($album) ); @@ -624,7 +642,7 @@ function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { if ($r) { $arr = array(); foreach ($r as $rr) { - $arr[] = "'" . dbesc($rr['resource_id']) . "'" ; + $arr[] = "'" . dbesc($rr['hash']) . "'" ; } $str = implode(',',$arr); return $str; @@ -642,6 +660,7 @@ function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { * @param boolean $visible default false * @return int item_id */ + function photos_create_item($channel, $creator_hash, $photo, $visible = false) { // Create item container @@ -697,7 +716,7 @@ function getGps($exifCoord, $hemi) { function getGpstimestamp($exifCoord) { - $hours = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; + $hours = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; diff --git a/include/text.php b/include/text.php index 224ba17d0..2b22df2ea 100644 --- a/include/text.php +++ b/include/text.php @@ -3,6 +3,7 @@ * @file include/text.php */ +use \Zotlabs\Lib as Zlib; use \Michelf\MarkdownExtra; require_once("include/bbcode.php"); @@ -89,12 +90,10 @@ function escape_tags($string) { } -function z_input_filter($channel_id,$s,$type = 'text/bbcode') { +function z_input_filter($s,$type = 'text/bbcode',$allow_code = false) { if($type === 'text/bbcode') return escape_tags($s); - if($type === 'text/markdown') - return escape_tags($s); if($type == 'text/plain') return escape_tags($s); if($type == 'application/x-pdl') @@ -104,15 +103,15 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { return $s; } - $r = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", - intval($channel_id) - ); - if($r) { - if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) { - if(local_channel() && (get_account_id() == $r[0]['account_id'])) { - return $s; - } - } + if($allow_code) { + if($type === 'text/markdown') + return htmlspecialchars($s,ENT_QUOTES); + return $s; + } + + if($type === 'text/markdown') { + $x = new Zlib\MarkdownSoap($s); + return $x->clean(); } if($type === 'text/html') @@ -1183,8 +1182,7 @@ function list_smilies() { ':coffee', ':facepalm', ':like', - ':dislike', - ':hubzilla' + ':dislike' ); $icons = array( @@ -1219,8 +1217,7 @@ function list_smilies() { '<img class="smiley" src="' . z_root() . '/images/emoticons/coffee.gif" alt=":coffee" />', '<img class="smiley" src="' . z_root() . '/images/emoticons/smiley-facepalm.gif" alt=":facepalm" />', '<img class="smiley" src="' . z_root() . '/images/emoticons/like.gif" alt=":like" />', - '<img class="smiley" src="' . z_root() . '/images/emoticons/dislike.gif" alt=":dislike" />', - '<img class="smiley" src="' . z_root() . '/images/hz-16.png" alt=":hubzilla" />', + '<img class="smiley" src="' . z_root() . '/images/emoticons/dislike.gif" alt=":dislike" />' ); @@ -1639,6 +1636,7 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) { break; case 'text/markdown': + $text = Zlib\MarkdownSoap::unescape($text); $s = MarkdownExtra::defaultTransform($text); break; @@ -1794,23 +1792,9 @@ function mimetype_select($channel_id, $current = 'text/bbcode') { ); - if(App::$is_sys) { + if((App::$is_sys) || (channel_codeallowed($channel_id) && $channel_id == local_channel())){ $x[] = 'application/x-php'; } - else { - $r = q("select account_id, account_roles, channel_pageflags from account left join channel on account_id = channel_account_id where - channel_id = %d limit 1", - intval($channel_id) - ); - - if($r) { - if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) { - if(local_channel() && get_account_id() == $r[0]['account_id']) { - $x[] = 'application/x-php'; - } - } - } - } foreach($x as $y) { $selected = (($y == $current) ? ' selected="selected" ' : ''); @@ -3126,3 +3110,14 @@ function array_escape_tags(&$v,$k) { $v = escape_tags($v); } +function ellipsify($s,$maxlen) { + if($maxlen & 1) + $maxlen --; + if($maxlen < 4) + $maxlen = 4; + + if(mb_strlen($s) < $maxlen) + return $s; + + return mb_substr($s,0,$maxlen / 2) . '...' . mb_substr($s,mb_strlen($s) - ($maxlen / 2)); +}
\ No newline at end of file diff --git a/include/widgets.php b/include/widgets.php deleted file mode 100644 index c88c03f7e..000000000 --- a/include/widgets.php +++ /dev/null @@ -1,1778 +0,0 @@ -<?php -/** - * @file include/widgets.php - * - * @brief This file contains the widgets. - */ - -require_once('include/dir_fns.php'); -require_once('include/contact_widgets.php'); -require_once('include/attach.php'); - - -function widget_profile($args) { - - $block = observer_prohibited(); - return profile_sidebar(App::$profile, $block, true); -} - -function widget_zcard($args) { - - $block = observer_prohibited(); - $channel = channelx_by_n(App::$profile_uid); - return get_zcard($channel,get_observer_hash(),array('width' => 875)); -} - - - - -// FIXME The problem with the next widget is that we don't have a search function for webpages that we can send the links to. -// Then we should also provide an option to search webpages and conversations. - -function widget_tagcloud($args) { - - $o = ''; - //$tab = 0; - - $uid = App::$profile_uid; - $count = ((x($args,'count')) ? intval($args['count']) : 24); - $flags = 0; - $type = TERM_CATEGORY; - - // FIXME there exists no $authors variable - $r = tagadelic($uid, $count, $authors, $owner, $flags, ITEM_TYPE_WEBPAGE, $type); - - if($r) { - $o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">'; - foreach($r as $rr) { - $o .= '<span class="tag'.$rr[2].'">'.$rr[0].'</span> ' . "\r\n"; - } - $o .= '</div></div>'; - } - return $o; -} - -function widget_collections($args) { - require_once('include/group.php'); - - $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 'connections': - $every = 'connections'; - $each = 'group'; - $edit = true; - $current = $_REQUEST['gid']; - $abook_id = 0; - $wmode = 0; - 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 = 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_channel()) || (! feature_enabled(local_channel(),'suggest'))) - return ''; - - require_once('include/socgraph.php'); - - $r = suggestion_query(local_channel(),get_observer_hash(),0,20); - - if(! $r) { - return; - } - - $arr = array(); - - // Get two random entries from the top 20 returned. - // We'll grab the first one and the one immediately following. - // This will throw some entropy intot he situation so you won't - // be looking at the same two mug shots every time the widget runs - - $index = ((count($r) > 2) ? mt_rand(0,count($r) - 2) : 0); - - for($x = $index; $x <= ($index+1); $x ++) { - $rr = $r[$x]; - if(! $rr['xchan_url']) - break; - - $connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr']; - - $arr[] = array( - 'url' => chanlink_url($rr['xchan_url']), - 'profile' => $rr['xchan_url'], - 'name' => $rr['xchan_name'], - 'photo' => $rr['xchan_photo_m'], - 'ignlnk' => z_root() . '/directory?ignore=' . $rr['xchan_hash'], - 'conntxt' => t('Connect'), - 'connlnk' => $connlnk, - 'ignore' => t('Ignore/Hide') - ); - } - - $o = replace_macros(get_markup_template('suggest_widget.tpl'),array( - '$title' => t('Suggestions'), - '$more' => t('See more...'), - '$entries' => $arr - )); - - return $o; -} - - -function widget_follow($args) { - if(! local_channel()) - return ''; - - $uid = App::$channel['channel_id']; - $r = q("select count(*) as total from abook where abook_channel = %d and abook_self = 0 ", - intval($uid) - ); - if($r) - $total_channels = $r[0]['total']; - $limit = service_class_fetch($uid,'total_channels'); - if($limit !== false) { - $abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $total_channels, $limit); - } - else { - $abook_usage_message = ''; - } - return replace_macros(get_markup_template('follow.tpl'),array( - '$connect' => t('Add New Connection'), - '$desc' => t('Enter channel address'), - '$hint' => t('Examples: bob@example.com, https://example.com/barbara'), - '$follow' => t('Connect'), - '$abook_usage_message' => $abook_usage_message - )); -} - - -function widget_notes($arr) { - if(! local_channel()) - return ''; - if(! feature_enabled(local_channel(),'private_notes')) - return ''; - - $text = get_pconfig(local_channel(),'notes','text'); - - $o = replace_macros(get_markup_template('notes.tpl'), array( - '$banner' => t('Notes'), - '$text' => $text, - '$save' => t('Save'), - )); - - return $o; -} - - -function widget_savedsearch($arr) { - if((! local_channel()) || (! feature_enabled(local_channel(),'savedsearch'))) - return ''; - - $search = ((x($_GET,'netsearch')) ? $_GET['netsearch'] : ''); - if(! $search) - $search = ((x($_GET,'search')) ? $_GET['search'] : ''); - - if(x($_GET,'searchsave') && $search) { - $r = q("select * from term where uid = %d and ttype = %d and term = '%s' limit 1", - intval(local_channel()), - intval(TERM_SAVEDSEARCH), - dbesc($search) - ); - if(! $r) { - q("insert into term ( uid,ttype,term ) values ( %d, %d, '%s') ", - intval(local_channel()), - intval(TERM_SAVEDSEARCH), - dbesc($search) - ); - } - } - - if(x($_GET,'searchremove') && $search) { - q("delete from term where uid = %d and ttype = %d and term = '%s'", - intval(local_channel()), - intval(TERM_SAVEDSEARCH), - dbesc($search) - ); - $search = ''; - } - - $srchurl = App::$query_string; - - $srchurl = rtrim(preg_replace('/searchsave\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $hasq = ((strpos($srchurl,'?') !== false) ? true : false); - $srchurl = rtrim(preg_replace('/searchremove\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - - $srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); - - - $hasq = ((strpos($srchurl,'?') !== false) ? true : false); - $hasamp = ((strpos($srchurl,'&') !== false) ? true : false); - - if(($hasamp) && (! $hasq)) - $srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1); - - $o = ''; - - $r = q("select tid,term from term WHERE uid = %d and ttype = %d ", - intval(local_channel()), - intval(TERM_SAVEDSEARCH) - ); - - $saved = array(); - - if(count($r)) { - foreach($r as $rr) { - $saved[] = array( - 'id' => $rr['tid'], - 'term' => $rr['term'], - 'dellink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&searchremove=1&search=' . urlencode($rr['term']), - 'srchlink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&search=' . urlencode($rr['term']), - 'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'), - 'encodedterm' => urlencode($rr['term']), - 'delete' => t('Remove term'), - 'selected' => ($search==$rr['term']), - ); - } - } - - $tpl = get_markup_template("saved_searches.tpl"); - $o = replace_macros($tpl, array( - '$title' => t('Saved Searches'), - '$add' => t('add'), - '$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), true), - '$saved' => $saved, - )); - - return $o; -} - -function widget_sitesearch($arr) { - - $search = ((x($_GET,'search')) ? $_GET['search'] : ''); - - $srchurl = App::$query_string; - - $srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); - - - $hasq = ((strpos($srchurl,'?') !== false) ? true : false); - $hasamp = ((strpos($srchurl,'&') !== false) ? true : false); - - if(($hasamp) && (! $hasq)) - $srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1); - - $o = ''; - - $saved = array(); - - $tpl = get_markup_template("sitesearch.tpl"); - $o = replace_macros($tpl, array( - '$title' => t('Search'), - '$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), false), - '$saved' => $saved, - )); - - return $o; -} - - - - - -function widget_filer($arr) { - if(! local_channel()) - return ''; - - - $selected = ((x($_REQUEST,'file')) ? $_REQUEST['file'] : ''); - - $terms = array(); - $r = q("select distinct term from term where uid = %d and ttype = %d order by term asc", - intval(local_channel()), - intval(TERM_FILE) - ); - if(! $r) - return; - - foreach($r as $rr) - $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); - - return replace_macros(get_markup_template('fileas_widget.tpl'),array( - '$title' => t('Saved Folders'), - '$desc' => '', - '$sel_all' => (($selected == '') ? 'selected' : ''), - '$all' => t('Everything'), - '$terms' => $terms, - '$base' => z_root() . '/' . App::$cmd - )); -} - -function widget_archive($arr) { - - $o = ''; - - if(! App::$profile_uid) { - return ''; - } - - $uid = App::$profile_uid; - - if(! feature_enabled($uid,'archives')) - return ''; - - if(! perm_is_allowed($uid,get_observer_hash(),'view_stream')) - return ''; - - $wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0); - $style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select'); - $showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false); - $mindate = get_pconfig($uid,'system','archive_mindate'); - $visible_years = get_pconfig($uid,'system','archive_visible_years'); - if(! $visible_years) - $visible_years = 5; - - $url = z_root() . '/' . App::$cmd; - - $ret = list_post_dates($uid,$wall,$mindate); - - if(! count($ret)) - return ''; - - $cutoff_year = intval(datetime_convert('',date_default_timezone_get(),'now','Y')) - $visible_years; - $cutoff = ((array_key_exists($cutoff_year,$ret))? true : false); - - $o = replace_macros(get_markup_template('posted_date_widget.tpl'),array( - '$title' => t('Archives'), - '$size' => $visible_years, - '$cutoff_year' => $cutoff_year, - '$cutoff' => $cutoff, - '$url' => $url, - '$style' => $style, - '$showend' => $showend, - '$dates' => $ret - )); - return $o; -} - - -function widget_fullprofile($arr) { - - if(! App::$profile['profile_uid']) - return; - - $block = observer_prohibited(); - - return profile_sidebar(App::$profile, $block); -} - -function widget_shortprofile($arr) { - - if(! App::$profile['profile_uid']) - return; - - $block = observer_prohibited(); - - return profile_sidebar(App::$profile, $block, true, true); -} - - -function widget_categories($arr) { - - - if(App::$profile['profile_uid'] && (! perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(),'view_stream'))) - return ''; - - $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); - $srchurl = App::$query_string; - $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); - - return categories_widget($srchurl, $cat); - -} - -function widget_appcategories($arr) { - - if(! local_channel()) - return ''; - - $selected = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); - - $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); - - $srchurl = z_root() . '/apps'; - - $terms = array(); - - $r = q("select distinct(term.term) - from term join app on term.oid = app.id - where app_channel = %d - and term.uid = app_channel - and term.otype = %d - and term.term != 'nav_featured_app' - order by term.term asc", - intval(local_channel()), - intval(TERM_OBJ_APP) - ); - if($r) { - foreach($r as $rr) - $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); - - return replace_macros(get_markup_template('categories_widget.tpl'),array( - '$title' => t('Categories'), - '$desc' => '', - '$sel_all' => (($selected == '') ? 'selected' : ''), - '$all' => t('Everything'), - '$terms' => $terms, - '$base' => $srchurl, - - )); - } - - - -} - - - -function widget_appcloud($arr) { - if(! local_channel()) - return ''; - return app_tagblock(z_root() . '/apps'); -} - - -function widget_tagcloud_wall($arr) { - - - if((! App::$profile['profile_uid']) || (! App::$profile['channel_hash'])) - return ''; - if(! perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_stream')) - return ''; - - $limit = ((array_key_exists('limit', $arr)) ? intval($arr['limit']) : 50); - if(feature_enabled(App::$profile['profile_uid'], 'tagadelic')) - return wtagblock(App::$profile['profile_uid'], $limit, '', App::$profile['channel_hash'], 'wall'); - - return ''; -} - -function widget_catcloud_wall($arr) { - - - if((! App::$profile['profile_uid']) || (! App::$profile['channel_hash'])) - return ''; - if(! perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_stream')) - return ''; - - $limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50); - - return catblock(App::$profile['profile_uid'], $limit, '', App::$profile['channel_hash'], 'wall'); -} - - -function widget_affinity($arr) { - - if(! local_channel()) - return ''; - - // Get default cmin value from pconfig, but allow GET parameter to override - $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); - $cmin = (($cmin) ? $cmin : 0); - $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $cmin); - - // Get default cmax value from pconfig, but allow GET parameter to override - $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); - $cmax = (($cmax) ? $cmax : 99); - $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $cmax); - - - if(feature_enabled(local_channel(),'affinity')) { - - $labels = array( - t('Me'), - t('Family'), - t('Friends'), - t('Acquaintances'), - t('All') - ); - call_hooks('affinity_labels',$labels); - $label_str = ''; - - if($labels) { - foreach($labels as $l) { - if($label_str) { - $label_str .= ", '|'"; - $label_str .= ", '" . $l . "'"; - } - else - $label_str .= "'" . $l . "'"; - } - } - - $tpl = get_markup_template('main_slider.tpl'); - $x = replace_macros($tpl,array( - '$val' => $cmin . ',' . $cmax, - '$refresh' => t('Refresh'), - '$labels' => $label_str, - )); - $arr = array('html' => $x); - call_hooks('main_slider',$arr); - return $arr['html']; - } - - return ''; -} - - -function widget_settings_menu($arr) { - - if(! local_channel()) - return; - - - $channel = App::get_channel(); - - $abook_self_id = 0; - - // Retrieve the 'self' address book entry for use in the auto-permissions link - - $role = get_pconfig(local_channel(),'system','permissions_role'); - - $abk = q("select abook_id from abook where abook_channel = %d and abook_self = 1 limit 1", - intval(local_channel()) - ); - if($abk) - $abook_self_id = $abk[0]['abook_id']; - - $x = q("select count(*) as total from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 ", - dbesc($channel['channel_hash']) - ); - - $hublocs = (($x && $x[0]['total'] > 1) ? true : false); - - $tabs = array( - array( - 'label' => t('Account settings'), - 'url' => z_root().'/settings/account', - 'selected' => ((argv(1) === 'account') ? 'active' : ''), - ), - - array( - 'label' => t('Channel settings'), - 'url' => z_root().'/settings/channel', - 'selected' => ((argv(1) === 'channel') ? 'active' : ''), - ), - - ); - - if(get_account_techlevel() > 0 && get_features()) { - $tabs[] = array( - 'label' => t('Additional features'), - 'url' => z_root().'/settings/features', - 'selected' => ((argv(1) === 'features') ? 'active' : ''), - ); - } - - $tabs[] = array( - 'label' => t('Feature/Addon settings'), - 'url' => z_root().'/settings/featured', - 'selected' => ((argv(1) === 'featured') ? 'active' : ''), - ); - - $tabs[] = array( - 'label' => t('Display settings'), - 'url' => z_root().'/settings/display', - 'selected' => ((argv(1) === 'display') ? 'active' : ''), - ); - - if($hublocs) { - $tabs[] = array( - 'label' => t('Manage locations'), - 'url' => z_root() . '/locs', - 'selected' => ((argv(1) === 'locs') ? 'active' : ''), - ); - } - - $tabs[] = array( - 'label' => t('Export channel'), - 'url' => z_root() . '/uexport', - 'selected' => '' - ); - - $tabs[] = array( - 'label' => t('Connected apps'), - 'url' => z_root() . '/settings/oauth', - 'selected' => ((argv(1) === 'oauth') ? 'active' : ''), - ); - - if(get_account_techlevel() > 2) { - $tabs[] = array( - 'label' => t('Guest Access Tokens'), - 'url' => z_root() . '/settings/tokens', - 'selected' => ((argv(1) === 'tokens') ? 'active' : ''), - ); - } - - if(feature_enabled(local_channel(),'permcats')) { - $tabs[] = array( - 'label' => t('Permission Groups'), - 'url' => z_root() . '/settings/permcats', - 'selected' => ((argv(1) === 'permcats') ? 'active' : ''), - ); - } - - - if($role === false || $role === 'custom') { - $tabs[] = array( - 'label' => t('Connection Default Permissions'), - 'url' => z_root() . '/connedit/' . $abook_self_id, - 'selected' => '' - ); - } - - if(feature_enabled(local_channel(),'premium_channel')) { - $tabs[] = array( - 'label' => t('Premium Channel Settings'), - 'url' => z_root() . '/connect/' . $channel['channel_address'], - 'selected' => '' - ); - } - - if(feature_enabled(local_channel(),'channel_sources')) { - $tabs[] = array( - 'label' => t('Channel Sources'), - 'url' => z_root() . '/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_channel()) - return; - - - return replace_macros(get_markup_template('message_side.tpl'), array( - '$title' => t('Private Mail Menu'), - '$combined'=>array( - 'label' => t('Combined View'), - 'url' => z_root() . '/mail/combined', - 'sel' => (argv(1) == 'combined'), - ), - '$inbox'=>array( - 'label' => t('Inbox'), - 'url' => z_root() . '/mail/inbox', - 'sel' => (argv(1) == 'inbox'), - ), - '$outbox'=>array( - 'label' => t('Outbox'), - 'url' => z_root() . '/mail/outbox', - 'sel' => (argv(1) == 'outbox'), - ), - '$new'=>array( - 'label' => t('New Message'), - 'url' => z_root() . '/mail/new', - 'sel'=> (argv(1) == 'new'), - ) - )); -} - - -function widget_conversations($arr) { - if (! local_channel()) - return; - - if(argc() > 1) { - - switch(argv(1)) { - case 'combined': - $mailbox = 'combined'; - $header = t('Conversations'); - break; - case 'inbox': - $mailbox = 'inbox'; - $header = t('Received Messages'); - break; - case 'outbox': - $mailbox = 'outbox'; - $header = t('Sent Messages'); - break; - default: - $mailbox = 'combined'; - $header = t('Conversations'); - break; - } - - require_once('include/message.php'); - - // private_messages_list() can do other more complicated stuff, for now keep it simple - $r = private_messages_list(local_channel(), $mailbox, App::$pager['start'], App::$pager['itemspage']); - - if(! $r) { - info( t('No messages.') . EOL); - return $o; - } - - $messages = array(); - - foreach($r as $rr) { - - $messages[] = array( - 'mailbox' => $mailbox, - '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 conversation'), - 'body' => $rr['body'], - 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], 'c'), - 'seen' => $rr['seen'], - 'selected' => ((argv(2)) ? (argv(2) == $rr['id']) : ($r[0]['id'] == $rr['id'])) - ); - } - - $tpl = get_markup_template('mail_head.tpl'); - $o .= replace_macros($tpl, array( - '$header' => $header, - '$messages' => $messages - )); - - //$o .= alt_pager($a,count($r)); - - } - - return $o; -} - -function widget_eventstools($arr) { - if (! local_channel()) - return; - - return replace_macros(get_markup_template('events_tools_side.tpl'), array( - '$title' => t('Events Tools'), - '$export' => t('Export Calendar'), - '$import' => t('Import Calendar'), - '$submit' => t('Submit') - )); -} - -function widget_design_tools($arr) { - - // mod menu doesn't load a profile. For any modules which load a profile, check it. - // otherwise local_channel() is sufficient for permissions. - - if(App::$profile['profile_uid']) - if((App::$profile['profile_uid'] != local_channel()) && (! App::$is_sys)) - return ''; - - if(! local_channel()) - return ''; - - return design_tools(); -} - -function widget_website_portation_tools($arr) { - - // mod menu doesn't load a profile. For any modules which load a profile, check it. - // otherwise local_channel() is sufficient for permissions. - - if(App::$profile['profile_uid']) - if((App::$profile['profile_uid'] != local_channel()) && (! App::$is_sys)) - return ''; - - if(! local_channel()) - return ''; - - return website_portation_tools(); -} - -function widget_findpeople($arr) { - return findpeople_widget(); -} - - -function widget_photo_albums($arr) { - - if(! App::$profile['profile_uid']) - return ''; - $channelx = channelx_by_n(App::$profile['profile_uid']); - if((! $channelx) || (! perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_storage'))) - return ''; - require_once('include/photos.php'); - $sortkey = ((array_key_exists('sortkey',$arr)) ? $arr['sortkey'] : 'album'); - $direction = ((array_key_exists('direction',$arr)) ? $arr['direction'] : 'asc'); - - return photos_album_widget($channelx, App::get_observer(),$sortkey,$direction); -} - - -function widget_vcard($arr) { - return vcard_from_xchan('', App::get_observer()); -} - - -/* - * The following directory widgets are only useful on the directory page - */ - - -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(! App::$data['menu_item']) - return; - require_once('include/menu.php'); - - return menu_render(App::$data['menu_item']); -} - -function widget_chatroom_list($arr) { - - - $r = Zotlabs\Lib\Chatroom::roomlist(App::$profile['profile_uid']); - - if($r) { - return replace_macros(get_markup_template('chatroomlist.tpl'), array( - '$header' => t('Chatrooms'), - '$baseurl' => z_root(), - '$nickname' => App::$profile['channel_address'], - '$items' => $r, - '$overview' => t('Overview') - )); - } -} - -function widget_chatroom_members() { - $o = replace_macros(get_markup_template('chatroom_members.tpl'), array( - '$header' => t('Chat Members') - )); - - return $o; -} - -function widget_wiki_list($arr) { - - $channel = channelx_by_n(App::$profile_uid); - - $wikis = Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash()); - - if($wikis) { - return replace_macros(get_markup_template('wikilist_widget.tpl'), array( - '$header' => t('Wiki List'), - '$channel' => $channel['channel_address'], - '$wikis' => $wikis['wikis'] - )); - } - return ''; -} - -function widget_wiki_pages($arr) { - - $channelname = ((array_key_exists('channel',$arr)) ? $arr['channel'] : ''); - $c = channelx_by_nick($channelname); - - $wikiname = ''; - if (array_key_exists('refresh', $arr)) { - $not_refresh = (($arr['refresh']=== true) ? false : true); - } else { - $not_refresh = true; - } - $pages = array(); - if (! array_key_exists('resource_id', $arr)) { - $hide = true; - } else { - $p = Zotlabs\Lib\NativeWikiPage::page_list($c['channel_id'],get_observer_hash(),$arr['resource_id']); - - if($p['pages']) { - $pages = $p['pages']; - $w = $p['wiki']; - // Wiki item record is $w['wiki'] - $wikiname = $w['urlName']; - if (!$wikiname) { - $wikiname = ''; - } - } - } - $can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_wiki'); - - $can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false); - - return replace_macros(get_markup_template('wiki_page_list.tpl'), array( - '$hide' => $hide, - '$resource_id' => $arr['resource_id'], - '$not_refresh' => $not_refresh, - '$header' => t('Wiki Pages'), - '$channel' => $channelname, - '$wikiname' => $wikiname, - '$pages' => $pages, - '$canadd' => $can_create, - '$candel' => $can_delete, - '$addnew' => t('Add new page'), - '$pageName' => array('pageName', t('Page name')), - )); -} - -function widget_wiki_page_history($arr) { - - $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : ''); - $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : ''); - - $pageHistory = Zotlabs\Lib\NativeWikiPage::page_history(array('channel_id' => App::$profile_uid, 'observer_hash' => get_observer_hash(), 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); - return replace_macros(get_markup_template('nwiki_page_history.tpl'), array( - '$pageHistory' => $pageHistory['history'], - '$permsWrite' => $arr['permsWrite'], - '$name_lbl' => t('Name'), - '$msg_label' => t('Message','wiki_history') - )); - -} - -function widget_bookmarkedchats($arr) { - - if(! feature_enabled(App::$profile['profile_uid'],'ajaxchat')) - return ''; - - $h = get_observer_hash(); - if(! $h) - return; - $r = q("select xchat_url, xchat_desc from xchat where xchat_xchan = '%s' order by xchat_desc", - dbesc($h) - ); - if($r) { - for($x = 0; $x < count($r); $x ++) { - $r[$x]['xchat_url'] = zid($r[$x]['xchat_url']); - } - } - return replace_macros(get_markup_template('bookmarkedchats.tpl'),array( - '$header' => t('Bookmarked Chatrooms'), - '$rooms' => $r - )); -} - -function widget_suggestedchats($arr) { - - if(! feature_enabled(App::$profile['profile_uid'],'ajaxchat')) - return ''; - - // There are reports that this tool does not ever remove chatrooms on dead sites, - // and also will happily link to private chats which you cannot enter. - // For those reasons, it will be disabled until somebody decides it's worth - // fixing and comes up with a plan for doing so. - - return ''; - - - // probably should restrict this to your friends, but then the widget will only work - // if you are logged in locally. - - $h = get_observer_hash(); - if(! $h) - return; - $r = q("select xchat_url, xchat_desc, count(xchat_xchan) as total from xchat group by xchat_url, xchat_desc order by total desc, xchat_desc limit 24"); - if($r) { - for($x = 0; $x < count($r); $x ++) { - $r[$x]['xchat_url'] = zid($r[$x]['xchat_url']); - } - } - return replace_macros(get_markup_template('bookmarkedchats.tpl'),array( - '$header' => t('Suggested Chatrooms'), - '$rooms' => $r - )); -} - -function widget_item($arr) { - - $channel_id = 0; - if(array_key_exists('channel_id',$arr) && intval($arr['channel_id'])) - $channel_id = intval($arr['channel_id']); - if(! $channel_id) - $channel_id = App::$profile_uid; - if(! $channel_id) - return ''; - - - if((! $arr['mid']) && (! $arr['title'])) - return ''; - - if(! perm_is_allowed($channel_id, get_observer_hash(), 'view_pages')) - return ''; - - require_once('include/security.php'); - $sql_extra = item_permissions_sql($channel_id); - - if($arr['title']) { - $r = q("select item.* from item left join iconfig on item.id = iconfig.iid - where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s' - and iconfig.k = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1", - intval($channel_id), - dbesc($arr['title']), - intval(ITEM_TYPE_WEBPAGE) - ); - } - else { - $r = q("select * from item where mid = '%s' and uid = %d and item_type = " . intval(ITEM_TYPE_WEBPAGE) . " $sql_extra limit 1", - dbesc($arr['mid']), - intval($channel_id) - ); - } - - if(! $r) - return ''; - - xchan_query($r); - $r = fetch_post_tags($r, true); - - $o = prepare_page($r[0]); - return $o; -} - -function widget_clock($arr) { - - $miltime = 0; - if(isset($arr['military']) && $arr['military']) - $miltime = 1; - -$o = <<< EOT -<div class="widget"> -<h3 class="clockface"></h3> -<script> - -var timerID = null -var timerRunning = false - -function stopclock(){ - if(timerRunning) - clearTimeout(timerID) - timerRunning = false -} - -function startclock(){ - stopclock() - showtime() -} - -function showtime(){ - var now = new Date() - var hours = now.getHours() - var minutes = now.getMinutes() - var seconds = now.getSeconds() - var military = $miltime - var timeValue = "" - if(military) - timeValue = hours - else - timeValue = ((hours > 12) ? hours - 12 : hours) - timeValue += ((minutes < 10) ? ":0" : ":") + minutes -// timeValue += ((seconds < 10) ? ":0" : ":") + seconds - if(! military) - timeValue += (hours >= 12) ? " P.M." : " A.M." - $('.clockface').html(timeValue) - timerID = setTimeout("showtime()",1000) - timerRunning = true -} - -$(document).ready(function() { - startclock(); -}); - -</script> -</div> -EOT; -return $o; - -} - -/** - * @brief Widget to display a single photo. - * - * @param array $arr associative array with - * * \e string \b src URL of photo; URL must be an http or https URL - * * \e boolean \b zrl use zid in URL - * * \e string \b style CSS string - * - * @return string with parsed HTML - */ -function widget_photo($arr) { - - $style = $zrl = false; - - if(array_key_exists('src', $arr) && isset($arr['src'])) - $url = $arr['src']; - - if(strpos($url, 'http') !== 0) - return ''; - - if(array_key_exists('style', $arr) && isset($arr['style'])) - $style = $arr['style']; - - // ensure they can't sneak in an eval(js) function - - if(strpbrk($style, '(\'"<>') !== false) - $style = ''; - - if(array_key_exists('zrl', $arr) && isset($arr['zrl'])) - $zrl = (($arr['zrl']) ? true : false); - - if($zrl) - $url = zid($url); - - $o = '<div class="widget">'; - - $o .= '<img ' . (($zrl) ? ' class="zrl" ' : '') - . (($style) ? ' style="' . $style . '"' : '') - . ' src="' . $url . '" alt="' . t('photo/image') . '">'; - - $o .= '</div>'; - - return $o; -} - - -function widget_cover_photo($arr) { - - require_once('include/channel.php'); - $o = ''; - - if(App::$module == 'channel' && $_REQUEST['mid']) - return ''; - - $channel_id = 0; - if(array_key_exists('channel_id', $arr) && intval($arr['channel_id'])) - $channel_id = intval($arr['channel_id']); - if(! $channel_id) - $channel_id = App::$profile_uid; - if(! $channel_id) - return ''; - - $channel = channelx_by_n($channel_id); - - if(array_key_exists('style', $arr) && isset($arr['style'])) - $style = $arr['style']; - else - $style = 'width:100%; height: auto;'; - - // ensure they can't sneak in an eval(js) function - - if(strpbrk($style,'(\'"<>') !== false) - $style = ''; - - if(array_key_exists('title', $arr) && isset($arr['title'])) - $title = $arr['title']; - else - $title = $channel['channel_name']; - - if(array_key_exists('subtitle', $arr) && isset($arr['subtitle'])) - $subtitle = $arr['subtitle']; - else - $subtitle = str_replace('@','@',$channel['xchan_addr']); - - $c = get_cover_photo($channel_id,'html'); - - if($c) { - $photo_html = (($style) ? str_replace('alt=',' style="' . $style . '" alt=',$c) : $c); - - $o = replace_macros(get_markup_template('cover_photo_widget.tpl'),array( - '$photo_html' => $photo_html, - '$title' => $title, - '$subtitle' => $subtitle, - '$hovertitle' => t('Click to show more'), - )); - } - return $o; -} - - -function widget_photo_rand($arr) { - - require_once('include/photos.php'); - $style = false; - - if(array_key_exists('album', $arr) && isset($arr['album'])) - $album = $arr['album']; - else - $album = ''; - - $channel_id = 0; - if(array_key_exists('channel_id', $arr) && intval($arr['channel_id'])) - $channel_id = intval($arr['channel_id']); - if(! $channel_id) - $channel_id = App::$profile_uid; - if(! $channel_id) - return ''; - - $scale = ((array_key_exists('scale',$arr)) ? intval($arr['scale']) : 0); - - $ret = photos_list_photos(array('channel_id' => $channel_id),App::get_observer(),$album); - - $filtered = array(); - if($ret['success'] && $ret['photos']) - foreach($ret['photos'] as $p) - if($p['imgscale'] == $scale) - $filtered[] = $p['src']; - - if($filtered) { - $e = mt_rand(0, count($filtered) - 1); - $url = $filtered[$e]; - } - - if(strpos($url, 'http') !== 0) - return ''; - - if(array_key_exists('style', $arr) && isset($arr['style'])) - $style = $arr['style']; - - // ensure they can't sneak in an eval(js) function - - if(strpos($style,'(') !== false) - return ''; - - $url = zid($url); - - $o = '<div class="widget">'; - - $o .= '<img class="zrl" ' - . (($style) ? ' style="' . $style . '"' : '') - . ' src="' . $url . '" alt="' . t('photo/image') . '">'; - - $o .= '</div>'; - - return $o; -} - - -function widget_random_block($arr) { - - $channel_id = 0; - if(array_key_exists('channel_id',$arr) && intval($arr['channel_id'])) - $channel_id = intval($arr['channel_id']); - if(! $channel_id) - $channel_id = App::$profile_uid; - if(! $channel_id) - return ''; - - if(array_key_exists('contains',$arr)) - $contains = $arr['contains']; - - $o = ''; - - require_once('include/security.php'); - $sql_options = item_permissions_sql($channel_id); - - $randfunc = db_getfunc('RAND'); - - $r = q("select item.* from item left join iconfig on item.id = iconfig.iid - where item.uid = %d and iconfig.cat = 'system' and iconfig.v like '%s' and iconfig.k = 'BUILDBLOCK' and - item_type = %d $sql_options order by $randfunc limit 1", - intval($channel_id), - dbesc('%' . $contains . '%'), - intval(ITEM_TYPE_BLOCK) - ); - - if($r) { - $o = '<div class="widget bblock">'; - if($r[0]['title']) - $o .= '<h3>' . $r[0]['title'] . '</h3>'; - - $o .= prepare_text($r[0]['body'],$r[0]['mimetype']); - $o .= '</div>'; - } - - return $o; -} - - -function widget_rating($arr) { - - - $rating_enabled = get_config('system','rating_enabled'); - if(! $rating_enabled) { - return; - } - - if($arr['target']) - $hash = $arr['target']; - else - $hash = App::$poi['xchan_hash']; - - if(! $hash) - return; - - $url = ''; - $remote = false; - - if(remote_channel() && ! local_channel()) { - $ob = App::get_observer(); - if($ob && $ob['xchan_url']) { - $p = parse_url($ob['xchan_url']); - if($p) { - $url = $p['scheme'] . '://' . $p['host'] . (($p['port']) ? ':' . $p['port'] : ''); - $url .= '/rate?f=&target=' . urlencode($hash); - } - $remote = true; - } - } - - $self = false; - - if(local_channel()) { - $channel = App::get_channel(); - - if($hash == $channel['channel_hash']) - $self = true; - - head_add_js('ratings.js'); - - } - - - $o = '<div class="widget">'; - $o .= '<h3>' . t('Rating Tools') . '</h3>'; - - if((($remote) || (local_channel())) && (! $self)) { - if($remote) - $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</a>'; - else - $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</div>'; - } - - $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="fa fa-eye"></i> ' . t('View Ratings') . '</a>'; - $o .= '</div>'; - - return $o; - -} - -// used by site ratings pages to provide a return link -function widget_pubsites($arr) { - if(App::$poi) - return; - return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>'; -} - - -function widget_forums($arr) { - - if(! local_channel()) - return ''; - - $o = ''; - - if(is_array($arr) && array_key_exists('limit',$arr)) - $limit = " limit " . intval($limit) . " "; - else - $limit = ''; - - $unseen = 0; - if(is_array($arr) && array_key_exists('unseen',$arr) && intval($arr['unseen'])) - $unseen = 1; - - $perms_sql = item_permissions_sql(local_channel()) . item_normal(); - - $xf = false; - - $x1 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'send_stream' and v = '0'", - intval(local_channel()) - ); - if($x1) { - $xc = ids_to_querystr($x1,'xchan',true); - $x2 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'tag_deliver' and v = '1' and xchan in (" . $xc . ") ", - intval(local_channel()) - ); - if($x2) - $xf = ids_to_querystr($x2,'xchan',true); - } - - $sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 "); - - $r1 = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d $sql_extra order by xchan_name $limit ", - intval(local_channel()) - ); - if(! $r1) - return $o; - - $str = ''; - - // Trying to cram all this into a single query with joins and the proper group by's is tough. - // There also should be a way to update this via ajax. - - for($x = 0; $x < count($r1); $x ++) { - $r = q("select sum(item_unseen) as unseen from item where owner_xchan = '%s' and uid = %d and item_unseen = 1 $perms_sql ", - dbesc($r1[$x]['xchan_hash']), - intval(local_channel()) - ); - if($r) - $r1[$x]['unseen'] = $r[0]['unseen']; - -/** - * @FIXME - * This SQL makes the counts correct when you get forum posts arriving from different routes/sources - * (like personal channels). However the network query for these posts doesn't yet include this - * correction and it makes the SQL for that query pretty hairy so this is left as a future exercise. - * It may make more sense in that query to look for the mention in the body rather than another join, - * but that makes it very inefficient. - * - $r = q("select sum(item_unseen) as unseen from item left join term on oid = id where otype = %d and owner_xchan != '%s' and item.uid = %d and url = '%s' and ttype = %d $perms_sql ", - intval(TERM_OBJ_POST), - dbesc($r1[$x]['xchan_hash']), - intval(local_channel()), - dbesc($r1[$x]['xchan_url']), - intval(TERM_MENTION) - ); - if($r) - $r1[$x]['unseen'] = ((array_key_exists('unseen',$r1[$x])) ? $r1[$x]['unseen'] + $r[0]['unseen'] : $r[0]['unseen']); - * - * end @FIXME - */ - - } - - if($r1) { - $o .= '<div class="widget">'; - $o .= '<h3>' . t('Forums') . '</h3><ul class="nav nav-pills flex-column">'; - - foreach($r1 as $rr) { - if($unseen && (! intval($rr['unseen']))) - continue; - $o .= '<li class="nav-item"><a class="nav-link" href="network?f=&pf=1&cid=' . $rr['abook_id'] . '" ><span class="badge badge-default float-right">' . ((intval($rr['unseen'])) ? intval($rr['unseen']) : '') . '</span><img class ="menu-img-1" src="' . $rr['xchan_photo_s'] . '" /> ' . $rr['xchan_name'] . '</a></li>'; - } - $o .= '</ul></div>'; - } - return $o; - -} - - -function widget_activity($arr) { - - if(! local_channel()) - return ''; - - $o = ''; - - if(is_array($arr) && array_key_exists('limit',$arr)) - $limit = " limit " . intval($limit) . " "; - else - $limit = ''; - - $perms_sql = item_permissions_sql(local_channel()) . item_normal(); - - $r = q("select author_xchan from item where item_unseen = 1 and uid = %d $perms_sql", - intval(local_channel()) - ); - - $contributors = []; - $arr = []; - - if($r) { - foreach($r as $rv) { - if(array_key_exists($rv['author_xchan'],$contributors)) { - $contributors[$rv['author_xchan']] ++; - } - else { - $contributors[$rv['author_xchan']] = 1; - } - } - foreach($contributors as $k => $v) { - $arr[] = [ 'author_xchan' => $k, 'total' => $v ]; - } - usort($arr,'total_sort'); - xchan_query($arr); - } - - $x = [ 'entries' => $arr ]; - call_hooks('activity_widget',$x); - $arr = $x['entries']; - - if($arr) { - $o .= '<div class="widget">'; - $o .= '<h3>' . t('Activity','widget') . '</h3><ul class="nav nav-pills flex-column">'; - - foreach($arr as $rv) { - $o .= '<li class="nav-item"><a class="nav-link" href="network?f=&xchan=' . urlencode($rv['author_xchan']) . '" ><span class="badge badge-default float-right">' . ((intval($rv['total'])) ? intval($rv['total']) : '') . '</span><img src="' . $rv['author']['xchan_photo_s'] . '" class="menu-img-1" /> ' . $rv['author']['xchan_name'] . '</a></li>'; - } - $o .= '</ul></div>'; - } - return $o; - -} - - - - -function widget_tasklist($arr) { - - if (! local_channel()) - return; - - require_once('include/event.php'); - $o .= '<script>var tasksShowAll = 0; $(document).ready(function() { tasksFetch(); $("#tasklist-new-form").submit(function(event) { event.preventDefault(); $.post( "tasks/new", $("#tasklist-new-form").serialize(), function(data) { tasksFetch(); $("#tasklist-new-summary").val(""); } ); return false; } )});</script>'; - $o .= '<script>function taskComplete(id) { $.post("tasks/complete/"+id, function(data) { tasksFetch();}); } - function tasksFetch() { - $.get("tasks/fetch" + ((tasksShowAll) ? "/all" : ""), function(data) { - $(".tasklist-tasks").html(data.html); - }); - } - </script>'; - - $o .= '<div class="widget">' . '<h3>' . t('Tasks') . '</h3><div class="tasklist-tasks">'; - $o .= '</div><form id="tasklist-new-form" action="" ><input class="form-control" id="tasklist-new-summary" type="text" name="summary" value="" /></form>'; - $o .= '</div>'; - return $o; - -} - - -function widget_helpindex($arr) { - - $o .= '<div class="widget">'; - - $level_0 = get_help_content('sitetoc'); - if(! $level_0) - $level_0 = get_help_content('toc'); - - $level_0 = preg_replace('/\<ul(.*?)\>/','<ul class="nav nav-pills flex-column">',$level_0); - - $levels = array(); - - - if(argc() > 2) { - $path = ''; - for($x = 1; $x < argc(); $x ++) { - $path .= argv($x) . '/'; - $y = get_help_content($path . 'sitetoc'); - if(! $y) - $y = get_help_content($path . 'toc'); - if($y) - $levels[] = preg_replace('/\<ul(.*?)\>/','<ul class="nav nav-pills flex-column">',$y); - } - } - - if($level_0) - $o .= $level_0; - if($levels) { - foreach($levels as $l) { - $o .= '<br /><br />'; - $o .= $l; - } - } - - $o .= '</div>'; - - return $o; - -} - - - -function widget_admin($arr) { - - /* - * Side bar links - */ - - if(! is_site_admin()) { - return ''; - } - - $o = ''; - - // array( url, name, extra css classes ) - - $aside = array( - 'site' => array(z_root() . '/admin/site/', t('Site'), 'site'), - 'accounts' => array(z_root() . '/admin/accounts/', t('Accounts'), 'accounts', 'pending-update', t('Member registrations waiting for confirmation')), - 'channels' => array(z_root() . '/admin/channels/', t('Channels'), 'channels'), - 'security' => array(z_root() . '/admin/security/', t('Security'), 'security'), - 'features' => array(z_root() . '/admin/features/', t('Features'), 'features'), - 'plugins' => array(z_root() . '/admin/plugins/', t('Plugins'), 'plugins'), - 'themes' => array(z_root() . '/admin/themes/', t('Themes'), 'themes'), - 'queue' => array(z_root() . '/admin/queue', t('Inspect queue'), 'queue'), - 'profs' => array(z_root() . '/admin/profs', t('Profile Fields'), 'profs'), - 'dbsync' => array(z_root() . '/admin/dbsync/', t('DB updates'), 'dbsync') - - ); - - /* get plugins admin page */ - - $r = q("SELECT * FROM addon WHERE plugin_admin = 1"); - - $plugins = array(); - if($r) { - foreach ($r as $h){ - $plugin = $h['aname']; - $plugins[] = array(z_root() . '/admin/plugins/' . $plugin, $plugin, 'plugin'); - // temp plugins with admin - App::$plugins_admin[] = $plugin; - } - } - - $logs = array(z_root() . '/admin/logs/', t('Logs'), 'logs'); - - $arr = array('links' => $aside,'plugins' => $plugins,'logs' => $logs); - call_hooks('admin_aside',$arr); - - $o .= replace_macros(get_markup_template('admin_aside.tpl'), array( - '$admin' => $aside, - '$admtxt' => t('Admin'), - '$plugadmtxt' => t('Plugin Features'), - '$plugins' => $plugins, - '$logtxt' => t('Logs'), - '$logs' => $logs, - '$h_pending' => t('Member registrations waiting for confirmation'), - '$admurl'=> z_root() . '/admin/' - )); - - return $o; - -} - - - -function widget_album($args) { - - $owner_uid = App::$profile_uid; - $sql_extra = permissions_sql($owner_uid); - - - if(! perm_is_allowed($owner_uid,get_observer_hash(),'view_storage')) - return ''; - - if($args['album']) - $album = $args['album']; - if($args['title']) - $title = $args['title']; - - /** - * This may return incorrect permissions if you have multiple directories of the same name. - * It is a limitation of the photo table using a name for a photo album instead of a folder hash - */ - - if($album) { - $x = q("select hash from attach where filename = '%s' and uid = %d limit 1", - dbesc($album), - intval($owner_uid) - ); - if($x) { - $y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']); - if(! $y) - return ''; - } - } - - $order = 'DESC'; - - $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN - (SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph - ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) - ORDER BY created $order ", - intval($owner_uid), - dbesc($album), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE) - ); - - //edit album name - $album_edit = null; - - $photos = array(); - if($r) { - $twist = 'rotright'; - foreach($r as $rr) { - - if($twist == 'rotright') - $twist = 'rotleft'; - else - $twist = 'rotright'; - - $ext = $phototypes[$rr['mimetype']]; - - $imgalt_e = $rr['filename']; - $desc_e = $rr['description']; - - $imagelink = (z_root() . '/photos/' . App::$profile['channel_address'] . '/image/' . $rr['resource_id']); - - - $photos[] = array( - 'id' => $rr['id'], - 'twist' => ' ' . $twist . rand(2,4), - 'link' => $imagelink, - 'title' => t('View Photo'), - 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext, - 'alt' => $imgalt_e, - 'desc'=> $desc_e, - 'ext' => $ext, - 'hash'=> $rr['resource_id'], - 'unknown' => t('Unknown') - ); - } - } - - - $tpl = get_markup_template('photo_album.tpl'); - $o .= replace_macros($tpl, array( - '$photos' => $photos, - '$album' => (($title) ? $title : $album), - '$album_id' => rand(), - '$album_edit' => array(t('Edit Album'), $album_edit), - '$can_post' => false, - '$upload' => array(t('Upload'), z_root() . '/photos/' . App::$profile['channel_address'] . '/upload/' . bin2hex($album)), - '$order' => false, - '$upload_form' => $upload_form, - '$usage' => $usage_message - )); - - return $o; -} - |