diff --git a/README.md b/README.md index 9de6393b1..7fbc14219 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ Hubzilla - Community Server =========================== -Websites. Redefined. --------------------- +Help us redefine the web - using integrated and united community websites. +-------------------------------------------------------------------------- ![Hubzilla](images/hubzilla_house_arrows.png) diff --git a/boot.php b/boot.php index bc8baf818..ac2a26380 100755 --- a/boot.php +++ b/boot.php @@ -50,7 +50,7 @@ define ( 'PLATFORM_NAME', 'hubzilla' ); define ( 'RED_VERSION', trim(file_get_contents('version.inc')) . 'H'); define ( 'ZOT_REVISION', 1 ); -define ( 'DB_UPDATE_VERSION', 1152 ); +define ( 'DB_UPDATE_VERSION', 1153 ); /** * @brief Constant with a HTML line break. diff --git a/doc/about.bb b/doc/about.bb index aee0c140a..1d1a2d099 100644 --- a/doc/about.bb +++ b/doc/about.bb @@ -12,7 +12,7 @@ It is written in the PHP scripting language, thus making it trivial to install o In other words, $Projectname can run on any computing platform that comes with a web server, a MySQL-compatible database, and the PHP scripting language. -Along the way,$Projectname offers a number of unique goodies: +Along the way, $Projectname offers a number of unique goodies: [b]Single-click user identification:[/b] meaning you can access sites on $Projectname simply by clicking on links to remote sites. Authentication just happens automagically behind the scenes. Forget about remembering multiple user names with multiple passwords when accessing different sites online. diff --git a/doc/features.bb b/doc/features.bb index 54c587282..06b7fb6b0 100644 --- a/doc/features.bb +++ b/doc/features.bb @@ -190,7 +190,7 @@ When creating "Websites", content may be entered in HTML, Markdown, BB Any content created in $Projectname remains under the control of the member (or channel) that originally created it. At any time, a member can delete a message, or a range of messages. The deletion process ensures that the content is deleted, regardless of whether it was posted on a channel's primary (home) hub, or on another hub, where the channel was remotely authenticated via Zot ($Projectname communication and authentication protocol). [b]Media[/b] -Similar to any other modern blogging system, social network, or a micro-blogging service,$Projectname supports the uploading of files, embedding of videos, linking web pages. +Similar to any other modern blogging system, social network, or a micro-blogging service, $Projectname supports the uploading of files, embedding of videos, linking web pages. [b]Previewing/Editing[/b] Post can be previewed prior to sending and edited after sending. diff --git a/doc/to_do_code.bb b/doc/to_do_code.bb index 3050bea94..f66797d8b 100644 --- a/doc/to_do_code.bb +++ b/doc/to_do_code.bb @@ -6,6 +6,7 @@ We need much more than this, but here are areas where developers can help. Pleas [li]Include TOS link in registration/verification email[/li] [li]Auto preview posts/comments (configurable timer kicks in the preview if not 0)[/li] [li]Create bug tracker module[/li] +[li]delivery tracking/reporting[/li] [li]Filing posts - provide a dropdown menu integrated with the 'post actions menu'[/li] [li]integrate Mozilla Persona (possibly via plugin) https://github.com/mozilla/id-specs/blob/prod/browserid/index.md and become an idP[/li] [li]translation plugins - moses or apertium[/li] @@ -30,7 +31,7 @@ We need much more than this, but here are areas where developers can help. Pleas [li]External post connectors, add popular services[/li] [li](in progress Habeas Codice) service classes - provide a pluggable subscription payment gateway for premium accounts[/li] [li](in progress Habeas Codice) service classes - account overview page showing resources consumed by channel. With special consideration this page can also be accessed at a meta level by the site admin to drill down on problematic accounts/channels.[/li] -[li]Events module - fix permissions on events, and provide JS translation support for the calendar overview (done); integrate with calDAV[/li] +[li]implement CalDAV/CardDAV sync[/li] [li]Uploads - integrate #^[url=https://github.com/blueimp/jQuery-File-Upload]https://github.com/blueimp/jQuery-File-Upload[/url][/li] [li]Import/export - include events, things, etc.[/li] [li]API extensions, for Twitter API - search, friending, threading. For Red API, lots of stuff[/li] diff --git a/doc/what_is_zot.bb b/doc/what_is_zot.bb index 4ae9386e1..9285f4ec6 100644 --- a/doc/what_is_zot.bb +++ b/doc/what_is_zot.bb @@ -13,7 +13,7 @@ Zot is a revolutionary protocol which provides [i]decentralised communications[/ Communications and social networking are an integral part of the grid. Any channel (and any services provided by that channel) can make full use of feature-rich social communications on a global scale. These communications may be public or private - and private communications comprise not only fully encrypted transport, but also encrypted storage to help protect against accidental snooping and disclosure by rogue system administrators and internet service providers. -Zot allows a wide array of background services in the grid, from offering friend suggestions, to directory services. You can also perform other things which would typically only be possibly on a centralized provider - such as "Wall to Wall" posts. Priivate/multiple profiles can be easily created, and web content can be tailored to the viewer via the [i]Affinity Slider[/i]. +Zot allows a wide array of background services in the grid, from offering friend suggestions, to directory services. You can also perform other things which would typically only be possibly on a centralized provider - such as "Wall to Wall" posts. Private/multiple profiles can be easily created, and web content can be tailored to the viewer via the [i]Affinity Slider[/i]. You won't find these features at all on other decentralized communication services. In addition to providing hub (server) decentralization, perhaps the most innovative and interesting Zot feature is its provision of [i]decentralized identity[/i] services. @@ -27,11 +27,11 @@ The important bits of your identity and relationships can be backed up to a thum Crucially, these nomadic instances are kept in sync so any instance can take over if another one is compromised or damaged. This protects you against not only major system failure, but also temporary site overloads and governmental manipulation or censorship. -Nomadic identity, single sign-on, and$Projectname's decentralization of hubs, we believe, introduce a high degree of degree of [i]resiliency[/i] and [i]persistence[/i] in internet communications, that are sorely needed amidst global trends towards corporate centralization, as well as mass and indiscriminate government surveillance and censorship. +Nomadic identity, single sign-on, and $Projectname's decentralization of hubs, we believe, introduce a high degree of degree of [i]resiliency[/i] and [i]persistence[/i] in internet communications, that are sorely needed amidst global trends towards corporate centralization, as well as mass and indiscriminate government surveillance and censorship. As you browse the grid, viewing channels and their unique content, you are seamlessly authenticated as you go, even across completely different server hubs. No passwords to enter. Nothing to type. You're just greeted by name on every new site you visit. -How does Zot do that? We call it [i]magic-auth[/i], because$Projectname hides the details of the complexities that go into single sign-on logins, and nomadic identities, from the experience of browsing on the grid. This is one of the design goals of$Projectname: to increase privacy, and freedom on the web, while reducing the complexity and tedium brought by the need to enter new passwords and user names for every different sight that someone might visit online. +How does Zot do that? We call it [i]magic-auth[/i], because $Projectname hides the details of the complexities that go into single sign-on logins, and nomadic identities, from the experience of browsing on the grid. This is one of the design goals of $Projectname: to increase privacy, and freedom on the web, while reducing the complexity and tedium brought by the need to enter new passwords and user names for every different sight that someone might visit online. You login only once on your home hub (or any nomadic backup hub you have chosen). This allows you to access any authenticated services provided anywhere in the grid - such as shopping, blogs, forums, and access to private information. This is just like the services offered by large corporate providers with huge user databases; however you can be a member of this community, as well as a server on this network using a $35 Rasberry Pi. Your password isn't stored on a thousand different sites, or even worse, only on a few sites like Google and Facebook, beyond your direct control. diff --git a/include/DReport.php b/include/DReport.php new file mode 100644 index 000000000..ef86c8cbc --- /dev/null +++ b/include/DReport.php @@ -0,0 +1,55 @@ +location = $location; + $this->sender = $sender; + $this->recipient = $recipient; + $this->message_id = $message_id; + $this->status = $status; + $this->date = datetime_convert(); + } + + function update($status) { + $this->status = $status; + $this->date = datetime_convert(); + } + + function addto_recipient($name) { + $this->recipient = $this->recipient . ' ' . $name; + } + + function addto_update($status) { + $this->status = $this->status . ' ' . $status; + } + + + function set($arr) { + $this->location = $arr['location']; + $this->sender = $arr['sender']; + $this->recipient = $arr['recipient']; + $this->message_id = $arr['message_id']; + $this->status = $arr['status']; + $this->date = $arr['date']; + } + + function get() { + return array( + 'location' => $this->location, + 'sender' => $this->sender, + 'recipient' => $this->recipient, + 'message_id' => $this->message_id, + 'status' => $this->status, + 'date' => $this->date + ); + } +} diff --git a/include/attach.php b/include/attach.php index 513486bfc..39fdb5c3a 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1132,7 +1132,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) { */ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) { - $r = q("select hash, flags, is_dir from attach where hash = '%s' and uid = %d limit 1", + $r = q("select hash, flags, is_dir, is_photo from attach where hash = '%s' and uid = %d limit 1", dbesc($resource), intval($channel_id) ); @@ -1162,6 +1162,16 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi dbesc($resource), intval($channel_id) ); + if($r[0]['is_photo']) { + $x = q("update photo set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where resource_id = '%s' and uid = %d", + dbesc($allow_cid), + dbesc($allow_gid), + dbesc($deny_cid), + dbesc($deny_gid), + dbesc($resource), + intval($channel_id) + ); + } } /** diff --git a/include/chat.php b/include/chat.php index a0646265a..81c5c5d62 100644 --- a/include/chat.php +++ b/include/chat.php @@ -91,7 +91,7 @@ function chatroom_destroy($channel,$arr) { return $ret; } - create_sync_packet($channel['channel_id'],array('chatroom' => $r)); + build_sync_packet($channel['channel_id'],array('chatroom' => $r)); q("delete from chatroom where cr_id = %d", intval($r[0]['cr_id']) diff --git a/include/gprobe.php b/include/gprobe.php index 48c1c8e14..d8d893d9e 100644 --- a/include/gprobe.php +++ b/include/gprobe.php @@ -14,6 +14,9 @@ function gprobe_run($argv, $argc){ $url = hex2bin($argv[1]); + if(! strpos($url,'@')) + return; + $r = q("select * from xchan where xchan_addr = '%s' limit 1", dbesc($url) ); diff --git a/include/nav.php b/include/nav.php index 59a7c83a3..972795e83 100644 --- a/include/nav.php +++ b/include/nav.php @@ -94,9 +94,8 @@ EOT; require_once('include/chat.php'); $has_chats = chatroom_list_count(local_channel()); - if($has_chats) { - $nav['usermenu'][] = Array('chat/' . $channel['channel_address'],t('Chat'),"",t('Your chatrooms'),'chat_nav_btn'); - } + $nav['usermenu'][] = Array('chat/' . $channel['channel_address'] . (($has_chats) ? '' : '/new'), t('Chat'),"",t('Your chatrooms'),'chat_nav_btn'); + require_once('include/menu.php'); $has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK); diff --git a/include/network.php b/include/network.php index d3320f3ee..41e1ff37c 100644 --- a/include/network.php +++ b/include/network.php @@ -1053,16 +1053,20 @@ function discover_by_webbie($webbie) { $webbie = strtolower($webbie); - $x = webfinger_rfc7033($webbie); + $x = webfinger_rfc7033($webbie,true); if($x && array_key_exists('links',$x) && $x['links']) { foreach($x['links'] as $link) { if(array_key_exists('rel',$link) && $link['rel'] == 'http://purl.org/zot/protocol') { logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG); - $z = z_fetch_url($link['href']); - if($z['success']) { - $j = json_decode($z['body'],true); - $i = import_xchan($j); - return true; + if(array_key_exists('zot',$x) && $x['zot']['success']) + $i = import_xchan($x['zot']); + else { + $z = z_fetch_url($link['href']); + if($z['success']) { + $j = json_decode($z['body'],true); + $i = import_xchan($j); + return true; + } } } } @@ -1282,7 +1286,7 @@ LSIeXnd14lQYK/uxW/8cTFjcmddsKxeXysoQxbSa9VdDK+KkpZdgYXYrTTofXs6v+ } -function webfinger_rfc7033($webbie) { +function webfinger_rfc7033($webbie,$zot = false) { if(! strpos($webbie,'@')) @@ -1292,7 +1296,7 @@ function webfinger_rfc7033($webbie) { $resource = 'acct:' . $webbie; - $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?resource=' . $resource); + $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : '')); if($s['success']) $j = json_decode($s['body'],true); diff --git a/include/zot.php b/include/zot.php index 7e45b29c5..767abae38 100644 --- a/include/zot.php +++ b/include/zot.php @@ -296,13 +296,17 @@ function zot_refresh($them, $channel = null, $force = false) { } else { $r = null; + // if they re-installed the server we could end up with the wrong record - pointing to the old install. + // We'll order by reverse id to try and pick off the newest one first and hopefully end up with the + // correct hubloc. If this doesn't work we may have to re-write this section to try them all. + if(array_key_exists('xchan_addr',$them) && $them['xchan_addr']) { - $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_addr = '%s'", + $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_addr = '%s' order by hubloc_id desc", dbesc($them['xchan_addr']) ); } if(! $r) { - $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_hash = '%s'", + $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_hash = '%s' order by hubloc_id desc", dbesc($them['xchan_hash']) ); } @@ -483,20 +487,17 @@ function zot_refresh($them, $channel = null, $force = false) { if($y) { logger("New introduction received for {$channel['channel_name']}"); $new_perms = get_all_perms($channel['channel_id'],$x['hash']); - if($new_perms != $previous_perms) { - // Send back a permissions update if permissions have changed - $z = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", - dbesc($x['hash']), - intval($channel['channel_id']) - ); - if($z) - proc_run('php','include/notifier.php','permission_update',$z[0]['abook_id']); - } - $new_connection = q("select abook_id, abook_pending from abook where abook_channel = %d and abook_xchan = '%s' order by abook_created desc limit 1", - intval($channel['channel_id']), - dbesc($x['hash']) + + // Send a clone sync packet and a permissions update if permissions have changed + + $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 order by abook_created desc limit 1", + dbesc($x['hash']), + intval($channel['channel_id']) ); + if($new_connection) { + if($new_perms != $previous_perms) + proc_run('php','include/notifier.php','permission_update',$new_connection[0]['abook_id']); require_once('include/enotify.php'); notification(array( 'type' => NOTIFY_INTRO, @@ -504,12 +505,17 @@ function zot_refresh($them, $channel = null, $force = false) { 'to_xchan' => $channel['channel_hash'], 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'], )); - } + + if($their_perms & PERMS_R_STREAM) { + if(($channel['channel_w_stream'] & PERMS_PENDING) + || (! intval($new_connection[0]['abook_pending'])) ) + proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']); + } - if($new_connection && ($their_perms & PERMS_R_STREAM)) { - if(($channel['channel_w_stream'] & PERMS_PENDING) - || (! intval($new_connection[0]['abook_pending'])) ) - proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']); + unset($new_connection[0]['abook_id']); + unset($new_connection[0]['abook_account']); + unset($new_connection[0]['abook_channel']); + build_sync_packet($channel['channel_id'], array('abook' => $new_connection)); } } } @@ -1526,6 +1532,9 @@ function allowed_public_recips($msg) { function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) { $result = array(); + require_once('include/DReport.php'); + + $result['site'] = z_root(); // We've validated the sender. Now make sure that the sender is the owner or author @@ -1538,16 +1547,22 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ foreach($deliveries as $d) { $local_public = $public; + + $DR = new DReport(z_root(),$sender['hash'],$d['hash'],$arr['mid']); + $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($d['hash']) ); if(! $r) { - $result[] = array($d['hash'], 'recipients not found'); + $DR->update('recipient not found'); + $result[] = $DR->get(); continue; } $channel = $r[0]; + $DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>'); + // allow public postings to the sys channel regardless of permissions, but not // for comments travelling upstream. Wait and catch them on the way down. @@ -1583,7 +1598,8 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if((! perm_is_allowed($channel['channel_id'],$sender['hash'],$perm)) && (! $tag_delivery) && (! $local_public)) { logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}"); - $result[] = array($d['hash'],'permission denied',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('permission denied'); + $result[] = $DR->get(); continue; } @@ -1600,7 +1616,8 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ intval($channel['channel_id']) ); if(! $r) { - $result[] = array($d['hash'],'comment parent not found',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('comment parent not found'); + $result[] = $DR->get(); // We don't seem to have a copy of this conversation or at least the parent // - so request a copy of the entire conversation to date. @@ -1655,7 +1672,8 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if($last_hop && $last_hop != $sender['hash']) { logger('comment route mismatch: parent route = ' . $r[0]['route'] . ' expected = ' . $current_route, LOGGER_DEBUG); logger('comment route mismatch: parent msg = ' . $r[0]['id'],LOGGER_DEBUG); - $result[] = array($d['hash'],'comment route mismatch',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('comment route mismatch'); + $result[] = $DR->get(); continue; } @@ -1684,12 +1702,14 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $arr['uid'] = $channel['channel_id']; $item_id = delete_imported_item($sender,$arr,$channel['channel_id'],$relay); - $result[] = array($d['hash'],(($item_id) ? 'deleted' : 'delete_failed'),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update(($item_id) ? 'deleted' : 'delete_failed'); + $result[] = $DR->get(); if($relay && $item_id) { logger('process_delivery: invoking relay'); proc_run('php','include/notifier.php','relay',intval($item_id)); - $result[] = array($d['hash'],'relayed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('relayed'); + $result[] = $DR->get(); } continue; @@ -1705,7 +1725,9 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if(intval($r[0]['item_deleted'])) { // It was deleted locally. - $result[] = array($d['hash'],'update ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('update ignored'); + $result[] = $DR->get(); + continue; } // Maybe it has been edited? @@ -1713,17 +1735,21 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $arr['id'] = $r[0]['id']; $arr['uid'] = $channel['channel_id']; if(($arr['mid'] == $arr['parent_mid']) && (! post_is_importable($arr,$abook))) { - $result[] = array($d['hash'],'update ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('update ignored'); + $result[] = $DR->get(); } else { update_imported_item($sender,$arr,$r[0],$channel['channel_id']); - $result[] = array($d['hash'],'updated',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('updated'); + $result[] = $DR->get(); if(! $relay) add_source_route($item_id,$sender['hash']); } } else { - $result[] = array($d['hash'],'update ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('update ignored'); + $result[] = $DR->get(); + // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. @@ -1744,7 +1770,8 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $item_id = 0; if(($arr['mid'] == $arr['parent_mid']) && (! post_is_importable($arr,$abook))) { - $result[] = array($d['hash'],'post ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update('post ignored'); + $result[] = $DR->get(); } else { $item_result = item_store($arr); @@ -1756,14 +1783,16 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if(! $relay) add_source_route($item_id,$sender['hash']); } - $result[] = array($d['hash'],(($item_id) ? 'posted' : 'storage failed:' . $item_result['message']),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->update(($item_id) ? 'posted' : 'storage failed: ' . $item_result['message']); + $result[] = $DR->get(); } } if($relay && $item_id) { logger('process_delivery: invoking relay'); proc_run('php','include/notifier.php','relay',intval($item_id)); - $result[] = array($d['hash'],'relayed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + $DR->addto_update('relayed'); + $result[] = $DR->get(); } } @@ -2932,12 +2961,19 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { sync_menus($channel,$arr['menu']); if(array_key_exists('channel',$arr) && is_array($arr['channel']) && count($arr['channel'])) { - if(array_key_exists('channel_page_flags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) { - $arr['channel']['channel_removed'] = (($arr['channel']['channel_pageflags'] & 0x8000) ? 1 : 0); - $arr['channel']['channel_system'] = (($arr['channel']['channel_pageflags'] & 0x1000) ? 1 : 0); + + if(array_key_exists('channel_pageflags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) { + // These flags cannot be sync'd. + // remove the bits from the incoming flags. + + if($arr['channel_pageflags'] & 0x8000) + $arr['channel_pageflags'] = $arr['channel_pageflags'] - 0x8000; + if($arr['channel_pageflags'] & 0x1000) + $arr['channel_pageflags'] = $arr['channel_pageflags'] - 0x1000; + } - $disallowed = array('channel_id','channel_account_id','channel_primary','channel_prvkey', 'channel_address', 'channel_notifyflags'); + $disallowed = array('channel_id','channel_account_id','channel_primary','channel_prvkey', 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted', 'channel_system'); $clean = array(); foreach($arr['channel'] as $k => $v) { @@ -3404,3 +3440,291 @@ function zot_process_message_request($data) { return $ret; } + + +function zotinfo($arr) { + + $ret = array('success' => false); + + $zhash = ((x($arr,'guid_hash')) ? $arr['guid_hash'] : ''); + $zguid = ((x($arr,'guid')) ? $arr['guid'] : ''); + $zguid_sig = ((x($arr,'guid_sig')) ? $arr['guid_sig'] : ''); + $zaddr = ((x($arr,'address')) ? $arr['address'] : ''); + $ztarget = ((x($arr,'target')) ? $arr['target'] : ''); + $zsig = ((x($arr,'target_sig')) ? $arr['target_sig'] : ''); + $zkey = ((x($arr,'key')) ? $arr['key'] : ''); + $mindate = ((x($arr,'mindate')) ? $arr['mindate'] : ''); + $feed = ((x($arr,'feed')) ? intval($arr['feed']) : 0); + + if($ztarget) { + if((! $zkey) || (! $zsig) || (! rsa_verify($ztarget,base64url_decode($zsig),$zkey))) { + logger('zfinger: invalid target signature'); + $ret['message'] = t("invalid target signature"); + return($ret); + } + } + + $r = null; + + if(strlen($zhash)) { + $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash + where channel_hash = '%s' limit 1", + dbesc($zhash) + ); + } + elseif(strlen($zguid) && strlen($zguid_sig)) { + $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash + where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", + dbesc($zguid), + dbesc($zguid_sig) + ); + } + elseif(strlen($zaddr)) { + if(strpos($zaddr,'[system]') === false) { /* normal address lookup */ + $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash + where ( channel_address = '%s' or xchan_addr = '%s' ) limit 1", + dbesc($zaddr), + dbesc($zaddr) + ); + } + + else { + + /** + * The special address '[system]' will return a system channel if one has been defined, + * Or the first valid channel we find if there are no system channels. + * + * This is used by magic-auth if we have no prior communications with this site - and + * returns an identity on this site which we can use to create a valid hub record so that + * we can exchange signed messages. The precise identity is irrelevant. It's the hub + * information that we really need at the other end - and this will return it. + * + */ + + $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash + where channel_system = 1 order by channel_id limit 1"); + if(! $r) { + $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash + where channel_removed = 0 order by channel_id limit 1"); + } + } + } + else { + $ret['message'] = 'Invalid request'; + return($ret); + } + + if(! $r) { + $ret['message'] = 'Item not found.'; + return($ret); + } + + $e = $r[0]; + + $id = $e['channel_id']; + + $sys_channel = (intval($e['channel_system']) ? true : false); + $special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false); + $adult_channel = (($e['channel_pageflags'] & PAGE_ADULT) ? true : false); + $censored = (($e['channel_pageflags'] & PAGE_CENSORED) ? true : false); + $searchable = (($e['channel_pageflags'] & PAGE_HIDDEN) ? false : true); + $deleted = (intval($e['xchan_deleted']) ? true : false); + + if($deleted || $censored || $sys_channel) + $searchable = false; + + $public_forum = false; + + $role = get_pconfig($e['channel_id'],'system','permissions_role'); + if($role === 'forum' || $role === 'repository') { + $public_forum = true; + } + else { + // check if it has characteristics of a public forum based on custom permissions. + $t = q("select abook_my_perms from abook where abook_channel = %d and abook_self = 1 limit 1", + intval($e['channel_id']) + ); + if(($t) && (($t[0]['abook_my_perms'] & PERMS_W_TAGWALL) && (! ($t[0]['abook_my_perms'] & PERMS_W_STREAM)))) + $public_forum = true; + } + + + // This is for birthdays and keywords, but must check access permissions + $p = q("select * from profile where uid = %d and is_default = 1", + intval($e['channel_id']) + ); + + $profile = array(); + + if($p) { + + if(! intval($p[0]['publish'])) + $searchable = false; + + $profile['description'] = $p[0]['pdesc']; + $profile['birthday'] = $p[0]['dob']; + if(($profile['birthday'] != '0000-00-00') && (($bd = z_birthday($p[0]['dob'],$e['channel_timezone'])) !== '')) + $profile['next_birthday'] = $bd; + + if($age = age($p[0]['dob'],$e['channel_timezone'],'')) + $profile['age'] = $age; + $profile['gender'] = $p[0]['gender']; + $profile['marital'] = $p[0]['marital']; + $profile['sexual'] = $p[0]['sexual']; + $profile['locale'] = $p[0]['locality']; + $profile['region'] = $p[0]['region']; + $profile['postcode'] = $p[0]['postal_code']; + $profile['country'] = $p[0]['country_name']; + $profile['about'] = $p[0]['about']; + $profile['homepage'] = $p[0]['homepage']; + $profile['hometown'] = $p[0]['hometown']; + + if($p[0]['keywords']) { + $tags = array(); + $k = explode(' ',$p[0]['keywords']); + if($k) { + foreach($k as $kk) { + if(trim($kk," \t\n\r\0\x0B,")) { + $tags[] = trim($kk," \t\n\r\0\x0B,"); + } + } + } + if($tags) + $profile['keywords'] = $tags; + } + } + + $ret['success'] = true; + + // Communication details + + $ret['guid'] = $e['xchan_guid']; + $ret['guid_sig'] = $e['xchan_guid_sig']; + $ret['key'] = $e['xchan_pubkey']; + $ret['name'] = $e['xchan_name']; + $ret['name_updated'] = $e['xchan_name_date']; + $ret['address'] = $e['xchan_addr']; + $ret['photo_mimetype'] = $e['xchan_photo_mimetype']; + $ret['photo'] = $e['xchan_photo_l']; + $ret['photo_updated'] = $e['xchan_photo_date']; + $ret['url'] = $e['xchan_url']; + $ret['connections_url']= (($e['xchan_connurl']) ? $e['xchan_connurl'] : z_root() . '/poco/' . $e['channel_address']); + $ret['target'] = $ztarget; + $ret['target_sig'] = $zsig; + $ret['searchable'] = $searchable; + $ret['adult_content'] = $adult_channel; + $ret['public_forum'] = $public_forum; + if($deleted) + $ret['deleted'] = $deleted; + + // premium or other channel desiring some contact with potential followers before connecting. + // This is a template - %s will be replaced with the follow_url we discover for the return channel. + + if($special_channel) + $ret['connect_url'] = z_root() . '/connect/' . $e['channel_address']; + + // This is a template for our follow url, %s will be replaced with a webbie + + $ret['follow_url'] = z_root() . '/follow?f=&url=%s'; + + $ztarget_hash = (($ztarget && $zsig) + ? make_xchan_hash($ztarget,$zsig) + : '' ); + + $permissions = get_all_perms($e['channel_id'],$ztarget_hash,false); + + if($ztarget_hash) { + $permissions['connected'] = false; + $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", + dbesc($ztarget_hash), + intval($e['channel_id']) + ); + if($b) + $permissions['connected'] = true; + } + + $ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey) : $permissions); + + if($permissions['view_profile']) + $ret['profile'] = $profile; + + // array of (verified) hubs this channel uses + + $x = zot_encode_locations($e); + if($x) + $ret['locations'] = $x; + + $ret['site'] = array(); + $ret['site']['url'] = z_root(); + $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey'])); + + $dirmode = get_config('system','directory_mode'); + if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL)) + $ret['site']['directory_mode'] = 'normal'; + + if($dirmode == DIRECTORY_MODE_PRIMARY) + $ret['site']['directory_mode'] = 'primary'; + elseif($dirmode == DIRECTORY_MODE_SECONDARY) + $ret['site']['directory_mode'] = 'secondary'; + elseif($dirmode == DIRECTORY_MODE_STANDALONE) + $ret['site']['directory_mode'] = 'standalone'; + if($dirmode != DIRECTORY_MODE_NORMAL) + $ret['site']['directory_url'] = z_root() . '/dirsearch'; + + + // hide detailed site information if you're off the grid + + if($dirmode != DIRECTORY_MODE_STANDALONE) { + + $register_policy = intval(get_config('system','register_policy')); + + if($register_policy == REGISTER_CLOSED) + $ret['site']['register_policy'] = 'closed'; + if($register_policy == REGISTER_APPROVE) + $ret['site']['register_policy'] = 'approve'; + if($register_policy == REGISTER_OPEN) + $ret['site']['register_policy'] = 'open'; + + + $access_policy = intval(get_config('system','access_policy')); + + if($access_policy == ACCESS_PRIVATE) + $ret['site']['access_policy'] = 'private'; + if($access_policy == ACCESS_PAID) + $ret['site']['access_policy'] = 'paid'; + if($access_policy == ACCESS_FREE) + $ret['site']['access_policy'] = 'free'; + if($access_policy == ACCESS_TIERED) + $ret['site']['access_policy'] = 'tiered'; + + $ret['site']['accounts'] = account_total(); + + require_once('include/identity.php'); + $ret['site']['channels'] = channel_total(); + + + $ret['site']['version'] = PLATFORM_NAME . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']'; + + $ret['site']['admin'] = get_config('system','admin_email'); + + $a = get_app(); + + $visible_plugins = array(); + if(is_array($a->plugins) && count($a->plugins)) { + $r = q("select * from addon where hidden = 0"); + if($r) + foreach($r as $rr) + $visible_plugins[] = $rr['name']; + } + + $ret['site']['plugins'] = $visible_plugins; + $ret['site']['sitehash'] = get_config('system','location_hash'); + $ret['site']['sitename'] = get_config('system','sitename'); + $ret['site']['sellpage'] = get_config('system','sellpage'); + $ret['site']['location'] = get_config('system','site_location'); + $ret['site']['realm'] = get_directory_realm(); + + } + call_hooks('zot_finger',$ret); + return($ret); +} diff --git a/install/schema_mysql.sql b/install/schema_mysql.sql index 1793f89c2..3bb3b7133 100644 --- a/install/schema_mysql.sql +++ b/install/schema_mysql.sql @@ -350,6 +350,23 @@ CREATE TABLE IF NOT EXISTS `conv` ( KEY `updated` (`updated`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `dreport` ( + `dreport_id` int(11) NOT NULL AUTO_INCREMENT, + `dreport_channel` int(11) NOT NULL DEFAULT '0', + `dreport_mid` char(255) NOT NULL DEFAULT '', + `dreport_site` char(255) NOT NULL DEFAULT '', + `dreport_recip` char(255) NOT NULL DEFAULT '', + `dreport_result` char(255) NOT NULL DEFAULT '', + `dreport_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `dreport_xchan` char(255) NOT NULL DEFAULT '', + PRIMARY KEY (`dreport_id`), + KEY `dreport_mid` (`dreport_mid`), + KEY `dreport_site` (`dreport_site`), + KEY `dreport_time` (`dreport_time`), + KEY `dreport_xchan` (`dreport_xchan`), + KEY `dreport_channel` (`dreport_channel`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + CREATE TABLE IF NOT EXISTS `event` ( `id` int(11) NOT NULL AUTO_INCREMENT, `aid` int(10) unsigned NOT NULL DEFAULT '0', diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql index d31c304eb..1298f3cb3 100644 --- a/install/schema_postgres.sql +++ b/install/schema_postgres.sql @@ -341,6 +341,28 @@ CREATE TABLE "conv" ( create index "conv_created_idx" on conv ("created"); create index "conv_updated_idx" on conv ("updated"); +CREATE TABLE IF NOT EXISTS "dreport" ( + "dreport_id" int(11) NOT NULL, + "dreport_channel" int(11) NOT NULL DEFAULT '0', + "dreport_mid" char(255) NOT NULL DEFAULT '', + "dreport_site" char(255) NOT NULL DEFAULT '', + "dreport_recip" char(255) NOT NULL DEFAULT '', + "dreport_result" char(255) NOT NULL DEFAULT '', + "dreport_time" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', + "dreport_xchan" char(255) NOT NULL DEFAULT '', + PRIMARY KEY ("dreport_id") +); + +create index "dreport_mid" on dreport ("dreport_mid"); +create index "dreport_site" on dreport ("dreport_site"); +create index "dreport_time" on dreport ("dreport_time"); +create index "dreport_xchan" on dreport ("dreport_xchan"); +create index "dreport_channel" on dreport ("dreport_channel"); + + + + + CREATE TABLE "event" ( "id" serial NOT NULL, "aid" bigint NOT NULL DEFAULT '0', diff --git a/install/update.php b/install/update.php index 339d0cb25..cf35698df 100644 --- a/install/update.php +++ b/install/update.php @@ -1,6 +1,6 @@ $x)); + build_sync_packet(0, array('chatroom' => $x)); if($x) goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']); diff --git a/mod/mail.php b/mod/mail.php index 152db3231..80d7f477d 100644 --- a/mod/mail.php +++ b/mod/mail.php @@ -125,8 +125,7 @@ function mail_content(&$a) { $tpl = get_markup_template('mail_head.tpl'); $header = replace_macros($tpl, array( - '$messages' => t('Messages'), - '$tab_content' => $tab_content + '$header' => t('Messages'), )); if((argc() == 3) && (argv(1) === 'drop')) { @@ -160,8 +159,6 @@ function mail_content(&$a) { if((argc() > 1) && (argv(1) === 'new')) { - $o .= $header; - $plaintext = true; $tpl = get_markup_template('msg-header.tpl'); diff --git a/mod/message.php b/mod/message.php index 9cf4b6987..9f62f6b61 100644 --- a/mod/message.php +++ b/mod/message.php @@ -25,11 +25,7 @@ function message_content(&$a) { $cipher = 'aes256'; - $tpl = get_markup_template('mail_head.tpl'); - $header = replace_macros($tpl, array( - '$messages' => t('Messages'), - '$tab_content' => $tab_content - )); + if((argc() == 3) && (argv(1) === 'dropconv')) { if(! intval(argv(2))) @@ -42,9 +38,6 @@ function message_content(&$a) { } if(argc() == 1) { - // list messages - - $o .= $header; // private_messages_list() can do other more complicated stuff, for now keep it simple @@ -55,24 +48,33 @@ function message_content(&$a) { return $o; } - $tpl = get_markup_template('mail_list.tpl'); + $messages = array(); + foreach($r as $rr) { - - $o .= replace_macros($tpl, array( - '$id' => $rr['id'], - '$from_name' => $rr['from']['xchan_name'], - '$from_url' => chanlink_hash($rr['from_xchan']), - '$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'] : '' . $rr['title'] . ''), - '$delete' => t('Delete conversation'), - '$body' => smilies(bbcode($rr['body'])), - '$date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')), - '$seen' => $rr['seen'] - )); + $messages[] = array( + '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'] : '' . $rr['title'] . ''), + 'delete' => t('Delete conversation'), + 'body' => smilies(bbcode($rr['body'])), + 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')), + 'seen' => $rr['seen'] + ); } + + + $tpl = get_markup_template('mail_head.tpl'); + $o = replace_macros($tpl, array( + '$header' => t('Messages'), + '$messages' => $messages + )); + + $o .= alt_pager($a,count($r)); return $o; } diff --git a/mod/photos.php b/mod/photos.php index f48603d71..cd293b39d 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -770,7 +770,7 @@ function photos_content(&$a) { // fetch image, item containing image, then comments - $ph = q("SELECT aid,uid,xchan,resource_id,created,edited,title,`description`,album,filename,`type`,height,width,`size`,scale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s' + $ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,`description`,album,filename,`type`,height,width,`size`,scale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s' $sql_extra ORDER BY `scale` ASC ", intval($owner_uid), dbesc($datum) @@ -1147,7 +1147,7 @@ function photos_content(&$a) { $photo_tpl = get_markup_template('photo_view.tpl'); $o .= replace_macros($photo_tpl, array( - '$id' => $link_item['id'], //$ph[0]['id'], + '$id' => $ph[0]['id'], '$album' => $album_e, '$tools' => $tools, '$lock' => $lockstate[1], diff --git a/mod/webfinger.php b/mod/webfinger.php index a646961a8..74bfc3ce5 100644 --- a/mod/webfinger.php +++ b/mod/webfinger.php @@ -15,7 +15,7 @@ function webfinger_content(&$a) { if(x($_GET,'addr')) { $addr = trim($_GET['addr']); if(strpos($addr,'@') !== false) { - $res = webfinger_rfc7033($addr); + $res = webfinger_rfc7033($addr,true); if(! $res) $res = old_webfinger($addr); } diff --git a/mod/wfinger.php b/mod/wfinger.php index 7b9eaa461..8b9abe4af 100644 --- a/mod/wfinger.php +++ b/mod/wfinger.php @@ -1,5 +1,7 @@ $r[0]['xchan_addr'])); } } else { diff --git a/mod/zfinger.php b/mod/zfinger.php index 4f2b1fca7..fb3333280 100644 --- a/mod/zfinger.php +++ b/mod/zfinger.php @@ -5,286 +5,9 @@ function zfinger_init(&$a) { require_once('include/zot.php'); require_once('include/crypto.php'); - $ret = array('success' => false); - $zhash = ((x($_REQUEST,'guid_hash')) ? $_REQUEST['guid_hash'] : ''); - $zguid = ((x($_REQUEST,'guid')) ? $_REQUEST['guid'] : ''); - $zguid_sig = ((x($_REQUEST,'guid_sig')) ? $_REQUEST['guid_sig'] : ''); - $zaddr = ((x($_REQUEST,'address')) ? $_REQUEST['address'] : ''); - $ztarget = ((x($_REQUEST,'target')) ? $_REQUEST['target'] : ''); - $zsig = ((x($_REQUEST,'target_sig')) ? $_REQUEST['target_sig'] : ''); - $zkey = ((x($_REQUEST,'key')) ? $_REQUEST['key'] : ''); - $mindate = ((x($_REQUEST,'mindate')) ? $_REQUEST['mindate'] : ''); - $feed = ((x($_REQUEST,'feed')) ? intval($_REQUEST['feed']) : 0); + $x = zotinfo($_REQUEST); + json_return_and_die($x); - if($ztarget) { - if((! $zkey) || (! $zsig) || (! rsa_verify($ztarget,base64url_decode($zsig),$zkey))) { - logger('zfinger: invalid target signature'); - $ret['message'] = t("invalid target signature"); - json_return_and_die($ret); - } - } - - $r = null; - - if(strlen($zhash)) { - $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where channel_hash = '%s' limit 1", - dbesc($zhash) - ); - } - elseif(strlen($zguid) && strlen($zguid_sig)) { - $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", - dbesc($zguid), - dbesc($zguid_sig) - ); - } - elseif(strlen($zaddr)) { - if(strpos($zaddr,'[system]') === false) { /* normal address lookup */ - $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where ( channel_address = '%s' or xchan_addr = '%s' ) limit 1", - dbesc($zaddr), - dbesc($zaddr) - ); - } - - else { - - /** - * The special address '[system]' will return a system channel if one has been defined, - * Or the first valid channel we find if there are no system channels. - * - * This is used by magic-auth if we have no prior communications with this site - and - * returns an identity on this site which we can use to create a valid hub record so that - * we can exchange signed messages. The precise identity is irrelevant. It's the hub - * information that we really need at the other end - and this will return it. - * - */ - - $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where channel_system = 1 order by channel_id limit 1"); - if(! $r) { - $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash - where channel_removed = 0 order by channel_id limit 1"); - } - } - } - else { - $ret['message'] = 'Invalid request'; - json_return_and_die($ret); - } - - if(! $r) { - $ret['message'] = 'Item not found.'; - json_return_and_die($ret); - } - - $e = $r[0]; - - $id = $e['channel_id']; - - $sys_channel = (intval($e['channel_system']) ? true : false); - $special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false); - $adult_channel = (($e['channel_pageflags'] & PAGE_ADULT) ? true : false); - $censored = (($e['channel_pageflags'] & PAGE_CENSORED) ? true : false); - $searchable = (($e['channel_pageflags'] & PAGE_HIDDEN) ? false : true); - $deleted = (intval($e['xchan_deleted']) ? true : false); - - if($deleted || $censored || $sys_channel) - $searchable = false; - - $public_forum = false; - - $role = get_pconfig($e['channel_id'],'system','permissions_role'); - if($role === 'forum' || $role === 'repository') { - $public_forum = true; - } - else { - // check if it has characteristics of a public forum based on custom permissions. - $t = q("select abook_my_perms from abook where abook_channel = %d and abook_self = 1 limit 1", - intval($e['channel_id']) - ); - if(($t) && (($t[0]['abook_my_perms'] & PERMS_W_TAGWALL) && (! ($t[0]['abook_my_perms'] & PERMS_W_STREAM)))) - $public_forum = true; - } - - - // This is for birthdays and keywords, but must check access permissions - $p = q("select * from profile where uid = %d and is_default = 1", - intval($e['channel_id']) - ); - - $profile = array(); - - if($p) { - - if(! intval($p[0]['publish'])) - $searchable = false; - - $profile['description'] = $p[0]['pdesc']; - $profile['birthday'] = $p[0]['dob']; - if(($profile['birthday'] != '0000-00-00') && (($bd = z_birthday($p[0]['dob'],$e['channel_timezone'])) !== '')) - $profile['next_birthday'] = $bd; - - if($age = age($p[0]['dob'],$e['channel_timezone'],'')) - $profile['age'] = $age; - $profile['gender'] = $p[0]['gender']; - $profile['marital'] = $p[0]['marital']; - $profile['sexual'] = $p[0]['sexual']; - $profile['locale'] = $p[0]['locality']; - $profile['region'] = $p[0]['region']; - $profile['postcode'] = $p[0]['postal_code']; - $profile['country'] = $p[0]['country_name']; - $profile['about'] = $p[0]['about']; - $profile['homepage'] = $p[0]['homepage']; - $profile['hometown'] = $p[0]['hometown']; - - if($p[0]['keywords']) { - $tags = array(); - $k = explode(' ',$p[0]['keywords']); - if($k) { - foreach($k as $kk) { - if(trim($kk," \t\n\r\0\x0B,")) { - $tags[] = trim($kk," \t\n\r\0\x0B,"); - } - } - } - if($tags) - $profile['keywords'] = $tags; - } - } - - $ret['success'] = true; - - // Communication details - - $ret['guid'] = $e['xchan_guid']; - $ret['guid_sig'] = $e['xchan_guid_sig']; - $ret['key'] = $e['xchan_pubkey']; - $ret['name'] = $e['xchan_name']; - $ret['name_updated'] = $e['xchan_name_date']; - $ret['address'] = $e['xchan_addr']; - $ret['photo_mimetype'] = $e['xchan_photo_mimetype']; - $ret['photo'] = $e['xchan_photo_l']; - $ret['photo_updated'] = $e['xchan_photo_date']; - $ret['url'] = $e['xchan_url']; - $ret['connections_url']= (($e['xchan_connurl']) ? $e['xchan_connurl'] : z_root() . '/poco/' . $e['channel_address']); - $ret['target'] = $ztarget; - $ret['target_sig'] = $zsig; - $ret['searchable'] = $searchable; - $ret['adult_content'] = $adult_channel; - $ret['public_forum'] = $public_forum; - if($deleted) - $ret['deleted'] = $deleted; - - // premium or other channel desiring some contact with potential followers before connecting. - // This is a template - %s will be replaced with the follow_url we discover for the return channel. - - if($special_channel) - $ret['connect_url'] = z_root() . '/connect/' . $e['channel_address']; - - // This is a template for our follow url, %s will be replaced with a webbie - - $ret['follow_url'] = z_root() . '/follow?f=&url=%s'; - - $ztarget_hash = (($ztarget && $zsig) - ? make_xchan_hash($ztarget,$zsig) - : '' ); - - $permissions = get_all_perms($e['channel_id'],$ztarget_hash,false); - - if($ztarget_hash) { - $permissions['connected'] = false; - $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", - dbesc($ztarget_hash), - intval($e['channel_id']) - ); - if($b) - $permissions['connected'] = true; - } - - $ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey) : $permissions); - - if($permissions['view_profile']) - $ret['profile'] = $profile; - - // array of (verified) hubs this channel uses - - $x = zot_encode_locations($e); - if($x) - $ret['locations'] = $x; - - $ret['site'] = array(); - $ret['site']['url'] = z_root(); - $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey'])); - - $dirmode = get_config('system','directory_mode'); - if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL)) - $ret['site']['directory_mode'] = 'normal'; - - if($dirmode == DIRECTORY_MODE_PRIMARY) - $ret['site']['directory_mode'] = 'primary'; - elseif($dirmode == DIRECTORY_MODE_SECONDARY) - $ret['site']['directory_mode'] = 'secondary'; - elseif($dirmode == DIRECTORY_MODE_STANDALONE) - $ret['site']['directory_mode'] = 'standalone'; - if($dirmode != DIRECTORY_MODE_NORMAL) - $ret['site']['directory_url'] = z_root() . '/dirsearch'; - - - // hide detailed site information if you're off the grid - - if($dirmode != DIRECTORY_MODE_STANDALONE) { - - $register_policy = intval(get_config('system','register_policy')); - - if($register_policy == REGISTER_CLOSED) - $ret['site']['register_policy'] = 'closed'; - if($register_policy == REGISTER_APPROVE) - $ret['site']['register_policy'] = 'approve'; - if($register_policy == REGISTER_OPEN) - $ret['site']['register_policy'] = 'open'; - - - $access_policy = intval(get_config('system','access_policy')); - - if($access_policy == ACCESS_PRIVATE) - $ret['site']['access_policy'] = 'private'; - if($access_policy == ACCESS_PAID) - $ret['site']['access_policy'] = 'paid'; - if($access_policy == ACCESS_FREE) - $ret['site']['access_policy'] = 'free'; - if($access_policy == ACCESS_TIERED) - $ret['site']['access_policy'] = 'tiered'; - - $ret['site']['accounts'] = account_total(); - - require_once('include/identity.php'); - $ret['site']['channels'] = channel_total(); - - - $ret['site']['version'] = PLATFORM_NAME . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']'; - - $ret['site']['admin'] = get_config('system','admin_email'); - - $visible_plugins = array(); - if(is_array($a->plugins) && count($a->plugins)) { - $r = q("select * from addon where hidden = 0"); - if($r) - foreach($r as $rr) - $visible_plugins[] = $rr['name']; - } - - $ret['site']['plugins'] = $visible_plugins; - $ret['site']['sitehash'] = get_config('system','location_hash'); - $ret['site']['sitename'] = get_config('system','sitename'); - $ret['site']['sellpage'] = get_config('system','sellpage'); - $ret['site']['location'] = get_config('system','site_location'); - $ret['site']['realm'] = get_directory_realm(); - - } - call_hooks('zot_finger',$ret); - json_return_and_die($ret); } diff --git a/version.inc b/version.inc index e008faecc..e412e1495 100644 --- a/version.inc +++ b/version.inc @@ -1 +1 @@ -2015-09-16.1157 +2015-09-20.1161 diff --git a/view/css/choklet.css b/view/css/choklet.css index 5c895f15e..42a7fa6c4 100644 --- a/view/css/choklet.css +++ b/view/css/choklet.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/css/choklet_bannertwo.css b/view/css/choklet_bannertwo.css index 9eb3505bc..7ae012224 100644 --- a/view/css/choklet_bannertwo.css +++ b/view/css/choklet_bannertwo.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/css/choklet_edgesthree.css b/view/css/choklet_edgesthree.css index d1b2e4bbd..e267a4891 100644 --- a/view/css/choklet_edgesthree.css +++ b/view/css/choklet_edgesthree.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/css/choklet_edgestwo.css b/view/css/choklet_edgestwo.css index 999b602d3..6bf2bf8be 100644 --- a/view/css/choklet_edgestwo.css +++ b/view/css/choklet_edgestwo.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/css/choklet_full.css b/view/css/choklet_full.css index d00178016..f1e9b10e0 100644 --- a/view/css/choklet_full.css +++ b/view/css/choklet_full.css @@ -52,4 +52,4 @@ section { #blog-margin { margin-right: 5%; margin-left: 5%; -} \ No newline at end of file +} diff --git a/view/css/choklet_three.css b/view/css/choklet_three.css index 107834a82..17965084a 100644 --- a/view/css/choklet_three.css +++ b/view/css/choklet_three.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/css/conversation.css b/view/css/conversation.css index 7d4930aac..e409cf4cf 100644 --- a/view/css/conversation.css +++ b/view/css/conversation.css @@ -122,12 +122,15 @@ a.wall-item-name-link { overflow: auto; } -.wall-item-content h1, .wall-item-content h2 { - font-size: 1.319em; +.wall-item-content h1, +.wall-item-content h2 { + font-size: 1.319em; } -.wall-item-title h3, .wall-item-content h3, .wall-item-content h4 { - font-size: 1.112em; +.wall-item-title h3, +.wall-item-content h3, +.wall-item-content h4 { + font-size: 1.112em; } .wall-item-content img { diff --git a/view/css/default.css b/view/css/default.css index e84561baf..bffecbb81 100644 --- a/view/css/default.css +++ b/view/css/default.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/css/full.css b/view/css/full.css index acedad0e0..3f9a01d24 100644 --- a/view/css/full.css +++ b/view/css/full.css @@ -1,5 +1,6 @@ header #banner { position: fixed; + top: 0px; width: 33%; margin-left: 33%; margin-right: 33%; diff --git a/view/es/messages.po b/view/es/messages.po index 0272811eb..bb0ba9839 100644 --- a/view/es/messages.po +++ b/view/es/messages.po @@ -14,7 +14,7 @@ msgstr "" "Project-Id-Version: Redmatrix\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-11 00:05-0700\n" -"PO-Revision-Date: 2015-09-14 11:47+0000\n" +"PO-Revision-Date: 2015-09-14 18:21+0000\n" "Last-Translator: Manuel Jiménez Friaza \n" "Language-Team: Spanish (http://www.transifex.com/Friendica/red-matrix/language/es/)\n" "MIME-Version: 1.0\n" @@ -2507,7 +2507,7 @@ msgstr "Privado" #: ../../include/permissions.php:894 msgid "Community Forum" -msgstr "Foro de la comunidad" +msgstr "Foro de discusión" #: ../../include/permissions.php:895 msgid "Feed Republish" @@ -8604,7 +8604,7 @@ msgstr "O importar un canal existente de otro lugar" msgid "" "Please choose a channel type (such as social networking or community forum) " "and privacy requirements so we can select the best permissions for you" -msgstr "Elija el tipo de canal (como red social o foro de comunidad) y la privacidad que requiera, así podremos seleccionar el mejor conjunto de permisos para usted" +msgstr "Elija el tipo de canal (como red social o foro de discusión) y la privacidad que requiera, así podremos seleccionar el mejor conjunto de permisos para usted" #: ../../mod/new_channel.php:119 msgid "Channel Type" diff --git a/view/es/strings.php b/view/es/strings.php index 749562004..1d91ed820 100644 --- a/view/es/strings.php +++ b/view/es/strings.php @@ -579,7 +579,7 @@ $a->strings["Social Networking"] = "Redes sociales"; $a->strings["Mostly Public"] = "Público en su mayor parte"; $a->strings["Restricted"] = "Restringido"; $a->strings["Private"] = "Privado"; -$a->strings["Community Forum"] = "Foro de la comunidad"; +$a->strings["Community Forum"] = "Foro de discusión"; $a->strings["Feed Republish"] = "Republicar un \"feed\""; $a->strings["Special Purpose"] = "Propósito especial"; $a->strings["Celebrity/Soapbox"] = "Página para fans"; @@ -2031,7 +2031,7 @@ $a->strings["Examples: \"Bob Jameson\", \"Lisa and her Horses\", \"Soccer\", \"A $a->strings["Choose a short nickname"] = "Elija un alias corto"; $a->strings["Your nickname will be used to create an easily remembered channel address (like an email address) which you can share with others."] = "Su alias podrá usarse para crear una dirección de canal fácilmente memorizable (como una dirección de correo electrónico) que puede ser compartido con otros."; $a->strings["Or import an existing channel from another location"] = "O importar un canal existente de otro lugar"; -$a->strings["Please choose a channel type (such as social networking or community forum) and privacy requirements so we can select the best permissions for you"] = "Elija el tipo de canal (como red social o foro de comunidad) y la privacidad que requiera, así podremos seleccionar el mejor conjunto de permisos para usted"; +$a->strings["Please choose a channel type (such as social networking or community forum) and privacy requirements so we can select the best permissions for you"] = "Elija el tipo de canal (como red social o foro de discusión) y la privacidad que requiera, así podremos seleccionar el mejor conjunto de permisos para usted"; $a->strings["Channel Type"] = "Tipo de canal"; $a->strings["Read more about roles"] = "Leer más sobre los roles"; $a->strings["App installed."] = "Aplicación instalada."; diff --git a/view/js/main.js b/view/js/main.js index 77184465d..d3c7175d0 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -615,7 +615,7 @@ function updateConvItems(mode,data) { function collapseHeight() { - $(".wall-item-body, .directory-collapse").each(function() { + $(".wall-item-content, .directory-collapse").each(function() { var orgHeight = $(this).height(); if(orgHeight > divmore_height + 10) { if(! $(this).hasClass('divmore')) { diff --git a/view/php/default.php b/view/php/default.php index 4c8311ef0..6a9cc5517 100644 --- a/view/php/default.php +++ b/view/php/default.php @@ -14,7 +14,7 @@
- + diff --git a/view/theme/redbasic/php/config.php b/view/theme/redbasic/php/config.php index 6ab8acde6..6bea5bddb 100644 --- a/view/theme/redbasic/php/config.php +++ b/view/theme/redbasic/php/config.php @@ -79,7 +79,7 @@ function theme_post(&$a) { function redbasic_form(&$a, $arr) { $scheme_choices = array(); - $scheme_choices["---"] = t("Light (Hubzilla default)"); + $scheme_choices["---"] = t("Focus (Hubzilla default)"); $files = glob('view/theme/redbasic/schema/*.php'); if($files) { foreach($files as $file) { diff --git a/view/theme/redbasic/schema/dark.php b/view/theme/redbasic/schema/dark.php index 92e703325..af4b122f1 100644 --- a/view/theme/redbasic/schema/dark.php +++ b/view/theme/redbasic/schema/dark.php @@ -34,5 +34,8 @@ $toolicon_activecolour = '#fff'; if (! $font_colour) $font_colour = "#ccc"; + if (! $converse_width) + $converse_width = "1024"; + diff --git a/view/theme/redbasic/schema/simple_black_on_white.php b/view/theme/redbasic/schema/simple_black_on_white.php index 6853a0ed5..554e832f0 100644 --- a/view/theme/redbasic/schema/simple_black_on_white.php +++ b/view/theme/redbasic/schema/simple_black_on_white.php @@ -34,6 +34,9 @@ $comment_border_colour = "rgba(255,255,255,0.8)"; if (! $font_colour) $font_colour = "#000"; + if (! $converse_width) + $converse_width = "1024"; + diff --git a/view/theme/redbasic/schema/simple_green_on_black.php b/view/theme/redbasic/schema/simple_green_on_black.php index 2660624d6..8192180db 100644 --- a/view/theme/redbasic/schema/simple_green_on_black.php +++ b/view/theme/redbasic/schema/simple_green_on_black.php @@ -34,3 +34,5 @@ $comment_border_colour = "rgba(0,0,0,0.8)"; if (! $font_colour) $font_colour = "#46D43F"; + if (! $converse_width) + $converse_width = "1024"; diff --git a/view/theme/redbasic/schema/simple_white_on_black.php b/view/theme/redbasic/schema/simple_white_on_black.php index a76709ac9..b64f60bbe 100644 --- a/view/theme/redbasic/schema/simple_white_on_black.php +++ b/view/theme/redbasic/schema/simple_white_on_black.php @@ -34,3 +34,5 @@ $comment_border_colour = "rgba(0,0,0,0.8)"; if (! $font_colour) $font_colour = "#fff"; + if (! $converse_width) + $converse_width = "1024"; diff --git a/view/theme/redbasic/tpl/theme_settings.tpl b/view/theme/redbasic/tpl/theme_settings.tpl index bfb489abd..4f5b69beb 100644 --- a/view/theme/redbasic/tpl/theme_settings.tpl +++ b/view/theme/redbasic/tpl/theme_settings.tpl @@ -1,4 +1,7 @@ {{include file="field_select.tpl" field=$schema}} +{{include file="field_checkbox.tpl" field=$align_left}} +{{include file="field_checkbox.tpl" field=$narrow_navbar}} +{{include file="field_input.tpl" field=$converse_width}} {{if $expert}} {{include file="field_colorinput.tpl" field=$nav_bg}} {{include file="field_colorinput.tpl" field=$nav_gradient_top}} @@ -26,11 +29,7 @@ {{include file="field_input.tpl" field=$shadow}} {{include file="field_input.tpl" field=$top_photo}} {{include file="field_input.tpl" field=$reply_photo}} -{{/if}} -{{include file="field_input.tpl" field=$converse_width}} -{{include file="field_checkbox.tpl" field=$align_left}} -{{include file="field_checkbox.tpl" field=$narrow_navbar}} -{{if $expert}} +