aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Manning <tamanning@zoho.com>2018-06-08 05:22:01 -0400
committerAndrew Manning <tamanning@zoho.com>2018-06-08 05:22:01 -0400
commitdf2d18160212ec546ec640dd1d2152fecada5557 (patch)
tree126504df4e5ab2d42defbee153a748fe40253b38
parented17e8a6499e48b032393be351c39f31a0edcbf3 (diff)
parent7bf1c5f27b8b8f0eea226e81a5db99585c5a56b3 (diff)
downloadvolse-hubzilla-df2d18160212ec546ec640dd1d2152fecada5557.tar.gz
volse-hubzilla-df2d18160212ec546ec640dd1d2152fecada5557.tar.bz2
volse-hubzilla-df2d18160212ec546ec640dd1d2152fecada5557.zip
Merge branch 'dev' of framagit.org:hubzilla/core into dev
-rw-r--r--Zotlabs/Daemon/Deliver.php2
-rw-r--r--Zotlabs/Daemon/Poller.php8
-rw-r--r--Zotlabs/Lib/System.php2
-rw-r--r--Zotlabs/Lib/ThreadItem.php7
-rw-r--r--Zotlabs/Module/Acl.php3
-rw-r--r--Zotlabs/Module/Channel.php49
-rw-r--r--Zotlabs/Module/Connections.php2
-rw-r--r--Zotlabs/Module/Cover_photo.php1
-rw-r--r--Zotlabs/Module/Directory.php2
-rw-r--r--Zotlabs/Module/Menu.php117
-rw-r--r--Zotlabs/Module/Mitem.php99
-rw-r--r--Zotlabs/Module/Network.php104
-rw-r--r--Zotlabs/Module/Photos.php4
-rw-r--r--Zotlabs/Module/Ping.php58
-rw-r--r--Zotlabs/Module/Settings/Channel.php3
-rw-r--r--Zotlabs/Module/Viewconnections.php2
-rw-r--r--Zotlabs/Update/_1215.php26
-rw-r--r--Zotlabs/Widget/Activity_filter.php190
-rw-r--r--Zotlabs/Widget/Activity_order.php128
-rw-r--r--Zotlabs/Widget/Forums.php2
-rw-r--r--Zotlabs/Widget/Notifications.php11
-rw-r--r--app/bugreport.apd4
-rwxr-xr-xboot.php8
-rw-r--r--doc/Developers.md8
-rw-r--r--doc/Translations.md30
-rw-r--r--doc/context/es-es/articles/help.html20
-rw-r--r--doc/developer/developer_guide.bb28
-rw-r--r--doc/developers.bb143
l---------doc/es1
-rw-r--r--doc/es-es/TermsOfService.md10
-rw-r--r--doc/es-es/about/about.bb209
-rw-r--r--doc/es-es/about/about_hub.bb7
-rw-r--r--doc/es-es/about/project.bb185
-rw-r--r--doc/es-es/gdpr1.md84
-rw-r--r--doc/es-es/git_for_non_developers.bb78
-rw-r--r--doc/es-es/main.bb12
-rw-r--r--doc/es-es/toc.html74
-rw-r--r--include/connections.php9
-rw-r--r--include/conversation.php12
-rw-r--r--include/features.php29
-rw-r--r--include/group.php2
-rw-r--r--include/import.php13
-rw-r--r--include/nav.php28
-rw-r--r--include/network.php2
-rwxr-xr-xinclude/plugin.php2
-rw-r--r--include/text.php80
-rw-r--r--install/INSTALL.txt20
-rw-r--r--view/css/default.css8
-rw-r--r--view/fr/hmessages.po6
-rw-r--r--view/fr/hstrings.php4
-rw-r--r--view/js/main.js24
-rw-r--r--view/pdl/mod_network.pdl7
-rw-r--r--view/theme/redbasic/css/style.css21
-rw-r--r--view/theme/redbasic/js/redbasic.js5
-rw-r--r--view/tpl/activity_filter_widget.tpl11
-rwxr-xr-xview/tpl/build_query.tpl2
-rwxr-xr-xview/tpl/common_pills.tpl26
-rw-r--r--view/tpl/common_widget.tpl6
-rwxr-xr-xview/tpl/conv_item.tpl2
-rw-r--r--view/tpl/design_tools.tpl2
-rwxr-xr-xview/tpl/jot-header.tpl4
-rw-r--r--view/tpl/menuedit.tpl2
-rw-r--r--view/tpl/menulist.tpl6
-rw-r--r--view/tpl/mitemedit.tpl2
-rw-r--r--view/tpl/mitemlist.tpl4
-rwxr-xr-xview/tpl/navbar_default.tpl5
-rw-r--r--view/tpl/notifications_widget.tpl14
-rw-r--r--view/tpl/profile_tabs.tpl4
-rwxr-xr-xview/tpl/profile_vcard.tpl2
-rwxr-xr-xview/tpl/search_item.tpl88
-rwxr-xr-xview/tpl/settings.tpl1
71 files changed, 1771 insertions, 403 deletions
diff --git a/Zotlabs/Daemon/Deliver.php b/Zotlabs/Daemon/Deliver.php
index 394a7bf3e..b809cba91 100644
--- a/Zotlabs/Daemon/Deliver.php
+++ b/Zotlabs/Daemon/Deliver.php
@@ -75,6 +75,8 @@ class Deliver {
q("delete from dreport where dreport_queue = '%s'",
dbesc($argv[$x])
);
+
+ continue;
}
}
diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php
index e4bc9c143..49151437c 100644
--- a/Zotlabs/Daemon/Poller.php
+++ b/Zotlabs/Daemon/Poller.php
@@ -71,14 +71,18 @@ class Poller {
$randfunc = db_getfunc('RAND');
- $contacts = q("SELECT * FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
+ $contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
+ abook.abook_channel, abook.abook_id, abook.abook_archived, abook.abook_pending,
+ abook.abook_ignored, abook.abook_blocked,
+ xchan.xchan_network,
+ account.account_lastlog, account.account_flags
+ FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
LEFT JOIN account on abook_account = account_id
where abook_self = 0
$sql_extra
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED) // FIXME
-
);
if($contacts) {
diff --git a/Zotlabs/Lib/System.php b/Zotlabs/Lib/System.php
index c3e11eb6a..7bf1343bb 100644
--- a/Zotlabs/Lib/System.php
+++ b/Zotlabs/Lib/System.php
@@ -54,7 +54,7 @@ class System {
static public function get_project_srclink() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['project_srclink'])
return \App::$config['system']['project_srclink'];
- return 'https://github.com/redmatrix/hubzilla';
+ return 'https://framagit.org/hubzilla/core.git';
}
static public function get_server_role() {
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index a3c7f99b9..ed78ae00b 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -243,16 +243,9 @@ class ThreadItem {
// FIXME check this permission
if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
-// FIXME we don't need all this stuff, some can be done in the template
-
$star = array(
- 'do' => t("Add Star"),
- 'undo' => t("Remove Star"),
'toggle' => t("Toggle Star Status"),
- 'classdo' => ((intval($item['item_starred'])) ? "hidden" : ""),
- 'classundo' => ((intval($item['item_starred'])) ? "" : "hidden"),
'isstarred' => ((intval($item['item_starred'])) ? true : false),
- 'starred' => t('starred'),
);
}
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php
index 2678aeb7a..7b52e88b5 100644
--- a/Zotlabs/Module/Acl.php
+++ b/Zotlabs/Module/Acl.php
@@ -94,8 +94,7 @@ class Acl extends \Zotlabs\Web\Controller {
. " then POSITION('" . protect_sprintf(dbesc($search))
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
- $col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' );
- $sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc(($col === 'xchan_addr') ? punify($search) : $search) . "%'" ) . " ";
+ $sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) ";
}
else {
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index 327ca53db..80e81580a 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -18,6 +18,9 @@ class Channel extends \Zotlabs\Web\Controller {
function init() {
+ if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']))
+ goaway('search' . '?f=&search=' . $_GET['search']);
+
$which = null;
if(argc() > 1)
$which = argv(1);
@@ -82,7 +85,9 @@ class Channel extends \Zotlabs\Web\Controller {
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
+ $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'post');
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
+ $search = ((x($_GET,'search')) ? $_GET['search'] : EMPTY_STR);
$groups = array();
@@ -118,9 +123,12 @@ class Channel extends \Zotlabs\Web\Controller {
$static = channel_manual_conv_update(\App::$profile['profile_uid']);
- //$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
-
- // $o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
+ // search terms header
+ if($search) {
+ $o .= replace_macros(get_markup_template("section_title.tpl"),array(
+ '$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8')
+ ));
+ }
if($channel && $is_owner) {
$channel_acl = array(
@@ -179,15 +187,13 @@ class Channel extends \Zotlabs\Web\Controller {
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
-
- $search = EMPTY_STR;
- if(x($_GET,'search')) {
- $search = escape_tags($_GET['search']);
+ if($search) {
+ $search = escape_tags($search);
if(strpos($search,'#') === 0) {
- $sql_extra2 .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
+ $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
}
else {
- $sql_extra2 .= sprintf(" AND item.body like '%s' ",
+ $sql_extra .= sprintf(" AND item.body like '%s' ",
dbesc(protect_sprintf('%' . $search . '%'))
);
}
@@ -244,6 +250,7 @@ class Channel extends \Zotlabs\Web\Controller {
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
+ $order = 'post';
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
@@ -253,6 +260,12 @@ class Channel extends \Zotlabs\Web\Controller {
$sql_extra2 .= " and item.item_thread_top != 0 ";
}
+ if($order === 'post')
+ $ordering = "created";
+ else
+ $ordering = "commented";
+
+
$itemspage = get_pconfig(local_channel(),'system','itemspage');
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
@@ -269,13 +282,13 @@ class Channel extends \Zotlabs\Web\Controller {
}
}
else {
- $r = q("SELECT item.parent AS item_id FROM item
+ $r = q("SELECT DISTINCT item.parent AS item_id, $ordering FROM item
left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids )
WHERE true and item.uid = %d $item_normal
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
- AND item.item_wall = 1
- $sql_extra $sql_extra2
- ORDER BY created DESC, id $pager_sql ",
+ AND item.item_wall = 1 AND item.item_thread_top = 1
+ $sql_extra $sql_extra2
+ ORDER BY $ordering DESC $pager_sql ",
intval(\App::$profile['profile_uid'])
);
}
@@ -284,7 +297,6 @@ class Channel extends \Zotlabs\Web\Controller {
$r = array();
}
}
-
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
@@ -300,7 +312,7 @@ class Channel extends \Zotlabs\Web\Controller {
xchan_query($items);
$items = fetch_post_tags($items, true);
- $items = conv_sort($items,'created');
+ $items = conv_sort($items,$ordering);
if($load && $mid && (! count($items))) {
// This will happen if we don't have sufficient permissions
@@ -345,7 +357,7 @@ class Channel extends \Zotlabs\Web\Controller {
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => $search,
'$xchan' => '',
- '$order' => '',
+ '$order' => $order,
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? urlencode($category) : ''),
@@ -391,12 +403,13 @@ class Channel extends \Zotlabs\Web\Controller {
}
}
+ $mode = (($search) ? 'search' : 'channel');
if($checkjs->disabled()) {
- $o .= conversation($items,'channel',$update,'traditional');
+ $o .= conversation($items,$mode,$update,'traditional');
}
else {
- $o .= conversation($items,'channel',$update,$page_mode);
+ $o .= conversation($items,$mode,$update,$page_mode);
}
if((! $update) || ($checkjs->disabled())) {
diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php
index 3bbdbf326..cecada769 100644
--- a/Zotlabs/Module/Connections.php
+++ b/Zotlabs/Module/Connections.php
@@ -326,7 +326,7 @@ class Connections extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$o .= replace_macros(get_markup_template('connections.tpl'),array(
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php
index 9adfa2209..88fd4485d 100644
--- a/Zotlabs/Module/Cover_photo.php
+++ b/Zotlabs/Module/Cover_photo.php
@@ -9,6 +9,7 @@ namespace Zotlabs\Module;
require_once('include/photo/photo_driver.php');
require_once('include/channel.php');
+require_once('include/photos.php');
diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php
index f2673fa1a..8a7c6baf6 100644
--- a/Zotlabs/Module/Directory.php
+++ b/Zotlabs/Module/Directory.php
@@ -395,7 +395,7 @@ class Directory extends \Zotlabs\Web\Controller {
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
- $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
+ $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, array(
'$search' => $search,
'$desc' => t('Find'),
diff --git a/Zotlabs/Module/Menu.php b/Zotlabs/Module/Menu.php
index 1dec65c1f..1687a4414 100644
--- a/Zotlabs/Module/Menu.php
+++ b/Zotlabs/Module/Menu.php
@@ -7,18 +7,36 @@ require_once('include/channel.php');
class Menu extends \Zotlabs\Web\Controller {
+
function init() {
- if (array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
+
+ if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
- if ($sys && intval($sys['channel_id'])) {
+ if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
+
+ if(argc() > 1)
+ $which = argv(1);
+ else
+ return;
+
+ profile_load($which);
+
}
+
- function post() {
+ function post() {
- $uid = local_channel();
+ if(! \App::$profile) {
+ return;
+ }
+
+ $which = argv(1);
+
+
+ $uid = \App::$profile['channel_id'];
if(array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
$sys = get_sys_channel();
@@ -43,7 +61,7 @@ class Menu extends \Zotlabs\Web\Controller {
if($r) {
menu_sync_packet($uid,get_observer_hash(),$menu_id);
//info( t('Menu updated.') . EOL);
- goaway(z_root() . '/mitem/' . $menu_id . ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/mitem/' . $which . '/' . $menu_id . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
else
notice( t('Unable to update menu.'). EOL);
@@ -54,7 +72,7 @@ class Menu extends \Zotlabs\Web\Controller {
menu_sync_packet($uid,get_observer_hash(),$r);
//info( t('Menu created.') . EOL);
- goaway(z_root() . '/mitem/' . $r . ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/mitem/' . $which . '/' . $r . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
else
notice( t('Unable to create menu.'). EOL);
@@ -67,27 +85,71 @@ class Menu extends \Zotlabs\Web\Controller {
function get() {
+
+
+ if(! \App::$profile) {
+ notice( t('Requested profile is not available.') . EOL );
+ \App::$error = 404;
+ return;
+ }
+
+ $which = argv(1);
+
+ $_SESSION['return_url'] = \App::$query_string;
+
$uid = local_channel();
-
- if (\App::$is_sys && is_site_admin()) {
+ $owner = 0;
+ $channel = null;
+ $observer = \App::get_observer();
+
+ $channel = \App::get_channel();
+
+ if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
- $uid = intval($sys['channel_id']);
+ if($sys && intval($sys['channel_id'])) {
+ $uid = $owner = intval($sys['channel_id']);
+ $channel = $sys;
+ $observer = $sys;
+ }
}
-
- if(! $uid) {
+
+ if(! $owner) {
+ // Figure out who the page owner is.
+ $r = channelx_by_nick($which);
+ if($r) {
+ $owner = intval($r['channel_id']);
+ }
+ }
+
+ $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
+
+ $perms = get_all_perms($owner,$ob_hash);
+
+ if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
- return '';
+ return;
}
+
+ // Get the observer, check their permissions
+
+ $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
+
+ $perms = get_all_perms($owner,$ob_hash);
+
+ if(! $perms['write_pages']) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ if(argc() == 2) {
- if(argc() == 1) {
-
- $channel = (($sys) ? $sys : \App::get_channel());
+ $channel = (($sys) ? $sys : channelx_by_n($owner));
// list menus
- $x = menu_list($uid);
+ $x = menu_list($owner);
if($x) {
for($y = 0; $y < count($x); $y ++) {
- $m = menu_fetch($x[$y]['menu_name'],$uid,get_observer_hash());
+ $m = menu_fetch($x[$y]['menu_name'],$owner,get_observer_hash());
if($m)
$x[$y]['element'] = '[element]' . base64url_encode(json_encode(menu_element($channel,$m))) . '[/element]';
$x[$y]['bookmark'] = (($x[$y]['menu_flags'] & MENU_BOOKMARK) ? true : false);
@@ -100,6 +162,7 @@ class Menu extends \Zotlabs\Web\Controller {
'$menu_bookmark' => array('menu_bookmark', t('Allow Bookmarks'), 0 , t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))),
'$submit' => t('Submit and proceed'),
'$sys' => \App::$is_sys,
+ '$nick' => $which,
'$display' => 'none'
));
@@ -119,6 +182,7 @@ class Menu extends \Zotlabs\Web\Controller {
'$hintdrop' => t('Delete this menu'),
'$hintcontent' => t('Edit menu contents'),
'$hintedit' => t('Edit this menu'),
+ '$nick' => $which,
'$sys' => \App::$is_sys
));
@@ -126,19 +190,19 @@ class Menu extends \Zotlabs\Web\Controller {
}
- if(argc() > 1) {
- if(intval(argv(1))) {
+ if(argc() > 2) {
+ if(intval(argv(2))) {
- if(argc() == 3 && argv(2) == 'drop') {
- menu_sync_packet($uid,get_observer_hash(),intval(argv(1)),true);
- $r = menu_delete_id(intval(argv(1)),$uid);
+ if(argc() == 4 && argv(3) == 'drop') {
+ menu_sync_packet($owner,get_observer_hash(),intval(argv(1)),true);
+ $r = menu_delete_id(intval(argv(2)),$owner);
if(!$r)
notice( t('Menu could not be deleted.'). EOL);
- goaway(z_root() . '/menu' . ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/menu/' . $which . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
- $m = menu_fetch_id(intval(argv(1)),$uid);
+ $m = menu_fetch_id(intval(argv(2)),$owner);
if(! $m) {
notice( t('Menu not found.') . EOL);
@@ -148,14 +212,15 @@ class Menu extends \Zotlabs\Web\Controller {
$o = replace_macros(get_markup_template('menuedit.tpl'), array(
'$header' => t('Edit Menu'),
'$sys' => \App::$is_sys,
- '$menu_id' => intval(argv(1)),
- '$menu_edit_link' => 'mitem/' . intval(argv(1)) . ((\App::$is_sys) ? '?f=&sys=1' : ''),
+ '$menu_id' => intval(argv(2)),
+ '$menu_edit_link' => 'mitem/' . $which . '/' . intval(argv(1)) . ((\App::$is_sys) ? '?f=&sys=1' : ''),
'$hintedit' => t('Add or remove entries to this menu'),
'$editcontents' => t('Edit menu contents'),
'$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'),
'$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''),
'$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), (($m['menu_flags'] & MENU_BOOKMARK) ? 1 : 0), t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))),
'$menu_system' => (($m['menu_flags'] & MENU_SYSTEM) ? 1 : 0),
+ '$nick' => $which,
'$submit' => t('Submit and proceed')
));
diff --git a/Zotlabs/Module/Mitem.php b/Zotlabs/Module/Mitem.php
index 28f51b81b..ac7470e13 100644
--- a/Zotlabs/Module/Mitem.php
+++ b/Zotlabs/Module/Mitem.php
@@ -8,22 +8,25 @@ require_once('include/acl_selectors.php');
class Mitem extends \Zotlabs\Web\Controller {
function init() {
-
- $uid = local_channel();
-
- if(array_key_exists('sys',$_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
+
+ if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
- $uid = intval($sys['channel_id']);
- \App::$is_sys = true;
+ if($sys && intval($sys['channel_id'])) {
+ \App::$is_sys = true;
+ }
}
-
- if(! $uid)
+
+ if(argc() > 1)
+ $which = argv(1);
+ else
return;
+
+ profile_load($which);
- if(argc() < 2)
+ if(argc() < 3)
return;
- $m = menu_fetch_id(intval(argv(1)),$uid);
+ $m = menu_fetch_id(intval(argv(2)),\App::$profile['channel_id']);
if(! $m) {
notice( t('Menu not found.') . EOL);
return '';
@@ -32,19 +35,27 @@ class Mitem extends \Zotlabs\Web\Controller {
}
- function post() {
+ function post() {
- $uid = local_channel();
+ if(! \App::$profile) {
+ return;
+ }
+
+ $which = argv(1);
+
+
+ $uid = \App::$profile['channel_id'];
- if(\App::$is_sys && is_site_admin()) {
+ if(array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
$sys = get_sys_channel();
$uid = intval($sys['channel_id']);
+ \App::$is_sys = true;
}
- if(! $uid) {
+ if(! $uid)
return;
- }
-
+
+
if(! \App::$data['menu'])
return;
@@ -63,14 +74,14 @@ class Mitem extends \Zotlabs\Web\Controller {
$_REQUEST['mitem_flags'] |= MENU_ITEM_NEWWIN;
- $mitem_id = ((argc() > 2) ? intval(argv(2)) : 0);
+ $mitem_id = ((argc() > 3) ? intval(argv(3)) : 0);
if($mitem_id) {
$_REQUEST['mitem_id'] = $mitem_id;
$r = menu_edit_item($_REQUEST['menu_id'],$uid,$_REQUEST);
if($r) {
menu_sync_packet($uid,get_observer_hash(),$_REQUEST['menu_id']);
//info( t('Menu element updated.') . EOL);
- goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/mitem/' . $which . '/' . $_REQUEST['menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
else
notice( t('Unable to update menu element.') . EOL);
@@ -82,10 +93,10 @@ class Mitem extends \Zotlabs\Web\Controller {
menu_sync_packet($uid,get_observer_hash(),$_REQUEST['menu_id']);
//info( t('Menu element added.') . EOL);
if($_REQUEST['submit']) {
- goaway(z_root() . '/menu' . ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/menu/' . $which . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
if($_REQUEST['submit-more']) {
- goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . '?f=&display=block' . ((\App::$is_sys) ? '&sys=1' : '') );
+ goaway(z_root() . '/mitem/' . $which . '/' . $_REQUEST['menu_id'] . '?f=&display=block' . ((\App::$is_sys) ? '&sys=1' : '') );
}
}
else
@@ -96,12 +107,15 @@ class Mitem extends \Zotlabs\Web\Controller {
}
- function get() {
+ function get() {
$uid = local_channel();
- $channel = \App::get_channel();
+ $owner = \App::$profile['channel_id'];
+ $channel = channelx_by_n($owner);
$observer = \App::get_observer();
-
+
+ $which = argv(1);
+
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(\App::$is_sys && is_site_admin()) {
@@ -116,15 +130,15 @@ class Mitem extends \Zotlabs\Web\Controller {
return '';
}
- if(argc() < 2 || (! \App::$data['menu'])) {
+ if(argc() < 3 || (! \App::$data['menu'])) {
notice( t('Not found.') . EOL);
return '';
}
- $m = menu_fetch(\App::$data['menu']['menu_name'],$uid,$ob_hash);
+ $m = menu_fetch(\App::$data['menu']['menu_name'],$owner,$ob_hash);
\App::$data['menu_item'] = $m;
- $menu_list = menu_list($uid);
+ $menu_list = menu_list($owner);
foreach($menu_list as $menus) {
if($menus['menu_name'] != $m['menu']['menu_name'])
@@ -135,10 +149,10 @@ class Mitem extends \Zotlabs\Web\Controller {
$lockstate = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock');
- if(argc() == 2) {
+ if(argc() == 3) {
$r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc",
intval(\App::$data['menu']['menu_id']),
- intval($uid)
+ intval($owner)
);
if($_GET['display']) {
@@ -167,6 +181,7 @@ class Mitem extends \Zotlabs\Web\Controller {
'$display' => $display,
'$lockstate' => $lockstate,
'$menu_names' => $menu_names,
+ '$nick' => $which,
'$sys' => \App::$is_sys
));
@@ -187,40 +202,41 @@ class Mitem extends \Zotlabs\Web\Controller {
'$hintnew' => t('Add menu element'),
'$hintdrop' => t('Delete this menu item'),
'$hintedit' => t('Edit this menu item'),
+ '$nick' => $which,
));
return $o;
}
- if(argc() > 2) {
-
- if(intval(argv(2))) {
+ if(argc() > 3) {
+
+ if(intval(argv(3))) {
$m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1",
- intval(argv(2)),
- intval($uid)
+ intval(argv(3)),
+ intval($owner)
);
if(! $m) {
notice( t('Menu item not found.') . EOL);
- goaway(z_root() . '/menu'. ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/menu/'. $which . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
$mitem = $m[0];
$lockstate = (($mitem['allow_cid'] || $mitem['allow_gid'] || $mitem['deny_cid'] || $mitem['deny_gid']) ? 'lock' : 'unlock');
- if(argc() == 4 && argv(3) == 'drop') {
- menu_sync_packet($uid,get_observer_hash(),$mitem['mitem_menu_id']);
- $r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2)));
- menu_sync_packet($uid,get_observer_hash(),$mitem['mitem_menu_id']);
+ if(argc() == 5 && argv(4) == 'drop') {
+ menu_sync_packet($owner,get_observer_hash(),$mitem['mitem_menu_id']);
+ $r = menu_del_item($mitem['mitem_menu_id'], $owner, intval(argv(3)));
+ menu_sync_packet($owner,get_observer_hash(),$mitem['mitem_menu_id']);
if($r)
info( t('Menu item deleted.') . EOL);
else
notice( t('Menu item could not be deleted.'). EOL);
- goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
+ goaway(z_root() . '/mitem/' . $which . '/' . $mitem['mitem_menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
// edit menu item
@@ -234,7 +250,7 @@ class Mitem extends \Zotlabs\Web\Controller {
'$allow_gid' => acl2json($mitem['allow_gid']),
'$deny_cid' => acl2json($mitem['deny_cid']),
'$deny_gid' => acl2json($mitem['deny_gid']),
- '$mitem_id' => intval(argv(2)),
+ '$mitem_id' => intval(argv(3)),
'$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '','*'),
'$mitem_link' => array('mitem_link', t('Link or Submenu Target'), $mitem['mitem_link'], 'Enter URL of the link or select a menu name to create a submenu', '*', 'list="menu-names"'),
'$usezid' => array('usezid', t('Use magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), '', array(t('No'), t('Yes'))),
@@ -242,7 +258,8 @@ class Mitem extends \Zotlabs\Web\Controller {
'$mitem_order' => array('mitem_order', t('Order in list'),$mitem['mitem_order'],t('Higher numbers will sink to bottom of listing')),
'$submit' => t('Submit'),
'$lockstate' => $lockstate,
- '$menu_names' => $menu_names
+ '$menu_names' => $menu_names,
+ '$nick' => $which
));
return $o;
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
index 82c88e565..9837d35a3 100644
--- a/Zotlabs/Module/Network.php
+++ b/Zotlabs/Module/Network.php
@@ -15,6 +15,9 @@ class Network extends \Zotlabs\Web\Controller {
notice( t('Permission denied.') . EOL);
return;
}
+
+ if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']))
+ goaway('search' . '?f=&search=' . $_GET['search']);
if(count($_GET) < 2) {
$network_options = get_pconfig(local_channel(),'system','network_page_default');
@@ -57,13 +60,26 @@ class Network extends \Zotlabs\Web\Controller {
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
- $nouveau = ((x($_GET,'new')) ? intval($_GET['new']) : 0);
$static = ((x($_GET,'static')) ? intval($_GET['static']) : 0);
$gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0);
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : '');
-
+
+
+ $order = get_pconfig(local_channel(), 'mod_network', 'order', 0);
+ switch($order) {
+ case 0:
+ $order = 'comment';
+ break;
+ case 1:
+ $order = 'post';
+ break;
+ case 2:
+ $nouveau = true;
+ break;
+ }
+
$search = (($_GET['search']) ? $_GET['search'] : '');
if($search) {
$_GET['netsearch'] = escape_tags($search);
@@ -84,7 +100,7 @@ class Network extends \Zotlabs\Web\Controller {
}
if($datequery)
- $_GET['order'] = 'post';
+ $order = 'post';
// filter by collection (e.g. group)
@@ -107,16 +123,11 @@ class Network extends \Zotlabs\Web\Controller {
$def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>');
}
-
$default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0);
$default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99);
-
- // if no tabs are selected, defaults to comments
-
$cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
$star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
- $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment');
$liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0);
$conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0);
$spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0);
@@ -125,17 +136,20 @@ class Network extends \Zotlabs\Web\Controller {
$file = ((x($_GET,'file')) ? $_GET['file'] : '');
$xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : '');
$net = ((x($_GET,'net')) ? $_GET['net'] : '');
+ $pf = ((x($_GET,'pf')) ? $_GET['pf'] : '');
$deftag = '';
if(x($_GET,'search') || x($_GET,'file'))
$nouveau = true;
+
if($cid) {
- $r = q("SELECT abook_xchan FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
+ $cid_r = q("SELECT abook.abook_xchan, xchan.xchan_addr, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s, xchan.xchan_pubforum from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1",
intval($cid),
intval(local_channel())
);
- if(! $r) {
+
+ if(! $cid_r) {
if($update) {
killme();
}
@@ -143,14 +157,14 @@ class Network extends \Zotlabs\Web\Controller {
goaway(z_root() . '/network');
// NOTREACHED
}
- if($_GET['pf'] === '1')
- $deftag = '!' . t('forum') . '+' . intval($cid);
+ if($pf)
+ $deftag = '!{' . (($cid_r[0]['xchan_addr']) ? $cid_r[0]['xchan_addr'] : $cid_r[0]['xchan_url']) . '}';
else
- $def_acl = [ 'allow_cid' => '<' . $r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
+ $def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(! $update) {
- $tabs = network_tabs();
+ $tabs = ''; //network_tabs();
$o .= $tabs;
// search terms header
@@ -228,6 +242,7 @@ class Network extends \Zotlabs\Web\Controller {
}
}
$item_thread_top = '';
+
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) ";
$x = group_rec_byhash(local_channel(), $group_hash);
@@ -243,27 +258,26 @@ class Network extends \Zotlabs\Web\Controller {
$o .= $status_editor;
}
-
- elseif($cid) {
-
- $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1",
- intval($cid),
- intval(local_channel())
- );
- if($r) {
- $item_thread_top = '';
- $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or (body like '" . protect_sprintf('%' . $r[0]['xchan_url'] . '%') . "' and item_thread_top = 1 )) $item_normal ) ";
- $title = replace_macros(get_markup_template("section_title.tpl"),array(
- '$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>'
- ));
- $o = $tabs;
- $o .= $title;
- $o .= $status_editor;
- }
- else {
- notice( t('Invalid connection.') . EOL);
- goaway(z_root() . '/network');
+ elseif($cid_r) {
+ $item_thread_top = '';
+
+ if($load || $update) {
+ $ttype = (($pf) ? TERM_FORUM : TERM_MENTION);
+
+ $p1 = q("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal ");
+ $p2 = q("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'");
+
+ $p_str = ids_to_querystr(array_merge($p1,$p2),'parent');
+ $sql_extra = " AND item.parent IN ( $p_str ) ";
}
+
+ $title = replace_macros(get_markup_template("section_title.tpl"),array(
+ '$title' => '<a href="' . zid($cid_r[0]['xchan_url']) . '" ><img src="' . zid($cid_r[0]['xchan_photo_s']) . '" alt="' . urlencode($cid_r[0]['xchan_name']) . '" /></a> <a href="' . zid($cid_r[0]['xchan_url']) . '" >' . $cid_r[0]['xchan_name'] . '</a>'
+ ));
+
+ $o = $tabs;
+ $o .= $title;
+ $o .= $status_editor;
}
elseif($xchan) {
$r = q("select * from xchan where xchan_hash = '%s'",
@@ -337,7 +351,8 @@ class Network extends \Zotlabs\Web\Controller {
'$mid' => '',
'$verb' => $verb,
'$net' => $net,
- '$dbegin' => $datequery2
+ '$dbegin' => $datequery2,
+ '$pf' => (($pf) ? $pf : '0'),
));
}
@@ -377,9 +392,15 @@ class Network extends \Zotlabs\Web\Controller {
if($conv) {
$item_thread_top = '';
- $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ",
- dbesc(protect_sprintf($channel['channel_hash']))
- );
+
+ if($nouveau) {
+ $sql_extra .= " AND author_xchan = '" . dbesc($channel['channel_hash']) . "' ";
+ }
+ else {
+ $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan = '%s' or item_mentionsme = 1 )) ",
+ dbesc(protect_sprintf($channel['channel_hash']))
+ );
+ }
}
if($update && ! $load) {
@@ -474,9 +495,9 @@ class Network extends \Zotlabs\Web\Controller {
// Normal conversation view
if($order === 'post')
- $ordering = "created";
+ $ordering = "created";
else
- $ordering = "commented";
+ $ordering = "commented";
if($load) {
// Fetch a page full of parent items for this page
@@ -559,6 +580,9 @@ class Network extends \Zotlabs\Web\Controller {
}
$mode = (($nouveau) ? 'network-new' : 'network');
+
+ if($search)
+ $mode = 'search';
$o .= conversation($items,$mode,$update,$page_mode);
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
index e21f3025c..489bffc4a 100644
--- a/Zotlabs/Module/Photos.php
+++ b/Zotlabs/Module/Photos.php
@@ -838,7 +838,7 @@ class Photos extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template('photo_album.tpl');
$o .= replace_macros($tpl, array(
'$photos' => $photos,
@@ -1377,7 +1377,7 @@ class Photos extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template('photos_recent.tpl');
$o .= replace_macros($tpl, array(
'$title' => t('Recent Photos'),
diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php
index bb80adc41..baefe62ec 100644
--- a/Zotlabs/Module/Ping.php
+++ b/Zotlabs/Module/Ping.php
@@ -35,10 +35,12 @@ class Ping extends \Zotlabs\Web\Controller {
$result['birthdays_today'] = 0;
$result['all_events'] = 0;
$result['all_events_today'] = 0;
- $result['notice'] = array();
- $result['info'] = array();
+ $result['notice'] = [];
+ $result['info'] = [];
$result['pubs'] = 0;
$result['files'] = 0;
+ $result['forums'] = 0;
+ $result['forums_sub'] = [];
if(! $_SESSION['static_loadtime'])
$_SESSION['static_loadtime'] = datetime_convert();
@@ -622,6 +624,58 @@ class Ping extends \Zotlabs\Web\Controller {
if(! ($vnotify & VNOTIFY_BIRTHDAY))
$result['birthdays'] = 0;
+
+
+ if($vnotify & VNOTIFY_FORUMS) {
+ $forums = get_forum_channels(local_channel());
+
+ if(! $forums) {
+ $result['forums'] = 0;
+ }
+ else {
+
+ $perms_sql = item_permissions_sql(local_channel()) . item_normal();
+ $fcount = count($forums);
+ $forums['total'] = 0;
+
+ for($x = 0; $x < $fcount; $x ++) {
+ $r = q("select sum(item_unseen) as unseen from item
+ where uid = %d and owner_xchan = '%s' and item_unseen = 1 $perms_sql ",
+ intval(local_channel()),
+ dbesc($forums[$x]['xchan_hash'])
+ );
+ if($r[0]['unseen']) {
+ $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&cid=' . $forums[$x]['abook_id']);
+ $forums[$x]['name'] = $forums[$x]['xchan_name'];
+ $forums[$x]['url'] = $forums[$x]['xchan_url'];
+ $forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
+ $forums[$x]['unseen'] = $r[0]['unseen'];
+ $forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : '');
+ $forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum'));
+
+ $forums['total'] = $forums['total'] + $r[0]['unseen'];
+
+ unset($forums[$x]['abook_id']);
+ unset($forums[$x]['xchan_hash']);
+ unset($forums[$x]['xchan_name']);
+ unset($forums[$x]['xchan_url']);
+ unset($forums[$x]['xchan_photo_s']);
+
+ //if($forums[$x]['private_forum'])
+ // unset($forums[$x]['private_forum']);
+
+ }
+ else {
+ unset($forums[$x]);
+ }
+ }
+ $result['forums'] = $forums['total'];
+ unset($forums['total']);
+
+ $result['forums_sub'] = $forums;
+ }
+ }
+
$x = json_encode($result);
$t8 = dba_timer();
diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php
index beb62a3a3..3a6e03588 100644
--- a/Zotlabs/Module/Settings/Channel.php
+++ b/Zotlabs/Module/Settings/Channel.php
@@ -215,6 +215,8 @@ class Channel {
$vnotify += intval($_POST['vnotify13']);
if(x($_POST,'vnotify14'))
$vnotify += intval($_POST['vnotify14']);
+ if(x($_POST,'vnotify15'))
+ $vnotify += intval($_POST['vnotify15']);
$always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0;
@@ -599,6 +601,7 @@ class Channel {
'$vnotify12' => array('vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no),
'$vnotify13' => (($disable_discover_tab && !$site_firehose) ? array() : array('vnotify13', t('Unseen public activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)),
'$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no),
+ '$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no),
'$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ],
'$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php
index 8366e1325..0a5e86907 100644
--- a/Zotlabs/Module/Viewconnections.php
+++ b/Zotlabs/Module/Viewconnections.php
@@ -107,7 +107,7 @@ class Viewconnections extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template("viewcontact_template.tpl");
$o .= replace_macros($tpl, array(
'$title' => t('View Connections'),
diff --git a/Zotlabs/Update/_1215.php b/Zotlabs/Update/_1215.php
new file mode 100644
index 000000000..3acaab587
--- /dev/null
+++ b/Zotlabs/Update/_1215.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1215 {
+
+ function run() {
+ q("START TRANSACTION");
+
+ // this will fix mastodon hubloc_url
+ $r1 = q("UPDATE hubloc SET hubloc_url = LEFT(hubloc_url, POSITION('/users' IN hubloc_url)-1) WHERE POSITION('/users' IN hubloc_url)>0");
+
+ // this will fix peertube hubloc_url
+ $r2 = q("UPDATE hubloc SET hubloc_url = LEFT(hubloc_url, POSITION('/account' IN hubloc_url)-1) WHERE POSITION('/account' IN hubloc_url)>0");
+
+ if($r1 && $r2) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+ else {
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+ }
+ }
+
+}
diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php
new file mode 100644
index 000000000..32da20bf6
--- /dev/null
+++ b/Zotlabs/Widget/Activity_filter.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace Zotlabs\Widget;
+
+class Activity_filter {
+
+ function widget($arr) {
+
+ if(! local_channel())
+ return '';
+
+ $cmd = \App::$cmd;
+ $filter_active = false;
+
+ $tabs = [];
+
+ if(feature_enabled(local_channel(),'personal_tab')) {
+ if(x($_GET,'conv')) {
+ $conv_active = (($_GET['conv'] == 1) ? 'active' : '');
+ $filter_active = 'personal';
+ }
+
+ $tabs[] = [
+ 'label' => t('Personal Posts'),
+ 'icon' => 'user-circle',
+ 'url' => z_root() . '/' . $cmd . '/?f=&conv=1',
+ 'sel' => $conv_active,
+ 'title' => t('Show posts that mention or involve me')
+ ];
+ }
+
+ if(feature_enabled(local_channel(),'star_posts')) {
+ if(x($_GET,'star')) {
+ $starred_active = (($_GET['star'] == 1) ? 'active' : '');
+ $filter_active = 'star';
+ }
+
+ $tabs[] = [
+ 'label' => t('Starred Posts'),
+ 'icon' => 'star',
+ 'url'=>z_root() . '/' . $cmd . '/?f=&star=1',
+ 'sel'=>$starred_active,
+ 'title' => t('Show posts that I have starred')
+ ];
+ }
+
+ if(feature_enabled(local_channel(),'groups')) {
+ $groups = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ intval(local_channel())
+ );
+
+ if($groups) {
+ foreach($groups as $g) {
+ if(x($_GET,'gid')) {
+ $group_active = (($_GET['gid'] == $g['id']) ? 'active' : '');
+ $filter_active = 'group';
+ }
+ $gsub[] = [
+ 'label' => $g['gname'],
+ 'icon' => '',
+ 'url' => z_root() . '/' . $cmd . '/?f=&gid=' . $g['id'],
+ 'sel' => $group_active,
+ 'title' => sprintf(t('Show posts related to the %s privacy group'), $g['gname'])
+ ];
+ }
+ $tabs[] = [
+ 'id' => 'privacy_groups',
+ 'label' => t('Privacy Groups'),
+ 'icon' => 'users',
+ 'url' => '#',
+ 'sel' => (($filter_active == 'group') ? true : false),
+ 'title' => t('Show my privacy groups'),
+ 'sub' => $gsub
+
+ ];
+ }
+ }
+
+ if(feature_enabled(local_channel(),'filing')) {
+ $terms = q("select distinct term from term where uid = %d and ttype = %d order by term asc",
+ intval(local_channel()),
+ intval(TERM_FILE)
+ );
+
+ if($terms) {
+ foreach($terms as $t) {
+ if(x($_GET,'file')) {
+ $file_active = (($_GET['file'] == $t['term']) ? 'active' : '');
+ $filter_active = 'file';
+ }
+ $tsub[] = [
+ 'label' => $t['term'],
+ 'icon' => '',
+ 'url' => z_root() . '/' . $cmd . '/?f=&file=' . $t['term'],
+ 'sel' => $file_active,
+ 'title' => sprintf(t('Show posts that I have filed to %s'), $t['term']),
+ ];
+ }
+
+ $tabs[] = [
+ 'id' => 'saved_folders',
+ 'label' => t('Saved Folders'),
+ 'icon' => 'folder',
+ 'url' => '#',
+ 'sel' => (($filter_active == 'file') ? true : false),
+ 'title' => t('Show filed post categories'),
+ 'sub' => $tsub
+
+ ];
+ }
+ }
+
+ if(feature_enabled(local_channel(),'forums_tab')) {
+ $forums = get_forum_channels(local_channel());
+
+ if($forums) {
+ foreach($forums as $f) {
+ if(x($_GET,'pf') && x($_GET,'cid')) {
+ $forum_active = ((x($_GET,'pf') && $_GET['cid'] == $f['abook_id']) ? 'active' : '');
+ $filter_active = 'forums';
+ }
+ $fsub[] = [
+ 'label' => $f['xchan_name'],
+ 'img' => $f['xchan_photo_s'],
+ 'url' => (($f['private_forum']) ? $f['xchan_url'] : z_root() . '/' . $cmd . '/?f=&pf=1&cid=' . $f['abook_id']),
+ 'sel' => $forum_active,
+ 'title' => t('Show posts to this forum'),
+ 'lock' => (($f['private_forum']) ? 'lock' : '')
+ ];
+ }
+
+ $tabs[] = [
+ 'id' => 'forums',
+ 'label' => t('Forums'),
+ 'icon' => 'comments-o',
+ 'url' => '#',
+ 'sel' => (($filter_active == 'forums') ? true : false),
+ 'title' => t('Show forums'),
+ 'sub' => $fsub
+
+ ];
+ }
+ }
+
+
+ if(x($_GET,'search')) {
+ $filter_active = 'search';
+ $tabs[] = [
+ 'label' => t('Search'),
+ 'icon' => 'search',
+ 'url' => z_root() . '/' . $cmd . '/?f=&search=' . $_GET['search'],
+ 'sel' => 'active disabled',
+ 'title' => t('Panel search')
+ ];
+ }
+
+ $reset = [];
+ if($filter_active) {
+ $reset = [
+ 'label' => '',
+ 'icon' => 'remove',
+ 'url'=> z_root() . '/' . $cmd,
+ 'sel'=> '',
+ 'title' => t('Remove active filter')
+ ];
+ }
+
+ $arr = ['tabs' => $tabs];
+
+ call_hooks('network_tabs', $arr);
+
+ $o = '';
+
+ if($arr['tabs']) {
+ $content = replace_macros(get_markup_template('common_pills.tpl'), [
+ '$pills' => $arr['tabs']
+ ]);
+
+ $o .= replace_macros(get_markup_template('activity_filter_widget.tpl'), [
+ '$title' => t('Activity Filters'),
+ '$reset' => $reset,
+ '$content' => $content
+ ]);
+ }
+
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php
new file mode 100644
index 000000000..534d6caee
--- /dev/null
+++ b/Zotlabs/Widget/Activity_order.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Zotlabs\Widget;
+
+class Activity_order {
+
+ function widget($arr) {
+
+ if(! local_channel())
+ return '';
+
+ if(! feature_enabled(local_channel(),'order_tab')) {
+ set_pconfig(local_channel(), 'mod_network', 'order', 0);
+ return '';
+ }
+
+ $commentord_active = '';
+ $postord_active = '';
+ $unthreaded_active = '';
+
+ if(x($_GET, 'order')) {
+ switch($_GET['order']){
+ case 'post':
+ $postord_active = 'active';
+ set_pconfig(local_channel(), 'mod_network', 'order', 1);
+ break;
+ case 'comment':
+ $commentord_active = 'active';
+ set_pconfig(local_channel(), 'mod_network', 'order', 0);
+ break;
+ case 'unthreaded':
+ $unthreaded_active = 'active';
+ set_pconfig(local_channel(), 'mod_network', 'order', 2);
+ break;
+ default:
+ $commentord_active = 'active';
+ }
+ }
+ else {
+ $order = get_pconfig(local_channel(), 'mod_network', 'order', 0);
+ switch($order) {
+ case 0:
+ $commentord_active = 'active';
+ break;
+ case 1:
+ $postord_active = 'active';
+ break;
+ case 2:
+ $unthreaded_active = 'active';
+ break;
+ default:
+ $commentord_active = 'active';
+ }
+ }
+
+ // override order for search results and filer results
+ if(x($_GET,'search') || x($_GET,'file')) {
+ $unthreaded_active = 'active';
+ $commentord_active = $postord_active = 'disabled';
+ }
+
+ $cmd = \App::$cmd;
+
+ $filter = '';
+
+ if(x($_GET,'cid'))
+ $filter .= '&cid=' . $_GET['cid'];
+
+ if(x($_GET,'gid'))
+ $filter .= '&gid=' . $_GET['gid'];
+
+ if(x($_GET,'star'))
+ $filter .= '&star=' . $_GET['star'];
+
+ if(x($_GET,'conv'))
+ $filter .= '&conv=' . $_GET['conv'];
+
+ if(x($_GET,'file'))
+ $filter .= '&file=' . $_GET['file'];
+
+
+ // tabs
+ $tabs = [];
+
+ $tabs[] = [
+ 'label' => t('Commented Date'),
+ 'icon' => '',
+ 'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . $filter,
+ 'sel'=> $commentord_active,
+ 'title' => t('Order by last commented date'),
+ ];
+ $tabs[] = [
+ 'label' => t('Posted Date'),
+ 'icon' => '',
+ 'url'=>z_root() . '/' . $cmd . '?f=&order=post' . $filter,
+ 'sel'=> $postord_active,
+ 'title' => t('Order by last posted date'),
+ ];
+ $tabs[] = array(
+ 'label' => t('Date Unthreaded'),
+ 'icon' => '',
+ 'url' => z_root() . '/' . $cmd . '?f=&order=unthreaded' . $filter,
+ 'sel' => $unthreaded_active,
+ 'title' => t('Order unthreaded by date'),
+ );
+
+ $arr = ['tabs' => $tabs];
+
+ call_hooks('network_tabs', $arr);
+
+ $o = '';
+
+ if($arr['tabs']) {
+ $content = replace_macros(get_markup_template('common_pills.tpl'), [
+ '$pills' => $arr['tabs'],
+ ]);
+
+ $o = replace_macros(get_markup_template('common_widget.tpl'), [
+ '$title' => t('Activity Order'),
+ '$content' => $content,
+ ]);
+ }
+
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Widget/Forums.php b/Zotlabs/Widget/Forums.php
index 7415c0f0a..d3e2f2534 100644
--- a/Zotlabs/Widget/Forums.php
+++ b/Zotlabs/Widget/Forums.php
@@ -51,7 +51,7 @@ class Forums {
- $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 and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 $sql_extra order by xchan_name $limit ",
+ $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 and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name $limit ",
intval(local_channel())
);
diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php
index fc78a2a39..a4cf4e706 100644
--- a/Zotlabs/Widget/Notifications.php
+++ b/Zotlabs/Widget/Notifications.php
@@ -111,6 +111,17 @@ class Notifications {
'label' => t('Mark all notices seen')
]
];
+
+ $notifications[] = [
+ 'type' => 'forums',
+ 'icon' => 'comments-o',
+ 'severity' => 'secondary',
+ 'label' => t('Forums'),
+ 'title' => t('Forums'),
+ 'filter' => [
+ 'name_label' => t('Filter by name')
+ ]
+ ];
}
if(local_channel() && is_site_admin()) {
diff --git a/app/bugreport.apd b/app/bugreport.apd
index 99cc48bf9..f1f328013 100644
--- a/app/bugreport.apd
+++ b/app/bugreport.apd
@@ -1,5 +1,5 @@
-version: 1
-url: https://github.com/redmatrix/hubzilla/issues
+version: 2
+url: https://framagit.org/hubzilla/core/issues
name: Report Bug
photo: icon:bug
categories: System
diff --git a/boot.php b/boot.php
index 9b3b86381..4ad37b274 100755
--- a/boot.php
+++ b/boot.php
@@ -54,7 +54,7 @@ define ( 'STD_VERSION', '3.5.6' );
define ( 'ZOT_REVISION', '6.0a' );
-define ( 'DB_UPDATE_VERSION', 1214 );
+define ( 'DB_UPDATE_VERSION', 1215 );
define ( 'PROJECT_BASE', __DIR__ );
@@ -85,7 +85,6 @@ define ( 'DIRECTORY_FALLBACK_MASTER', 'https://zotadel.net');
$DIRECTORY_FALLBACK_SERVERS = array(
'https://hubzilla.zottel.net',
- 'https://gravizot.de',
'https://zotadel.net'
);
@@ -405,6 +404,7 @@ define ( 'VNOTIFY_REGISTER', 0x0400 );
define ( 'VNOTIFY_FILES', 0x0800 );
define ( 'VNOTIFY_PUBS', 0x1000 );
define ( 'VNOTIFY_LIKE', 0x2000 );
+define ( 'VNOTIFY_FORUMS', 0x4000 );
@@ -876,13 +876,13 @@ class App {
set_include_path("include/self::$hostname" . PATH_SEPARATOR . get_include_path());
if((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'], 0, 2) === "q=") {
- self::$query_string = substr($_SERVER['QUERY_STRING'], 2);
+ self::$query_string = escape_tags(substr($_SERVER['QUERY_STRING'], 2));
// removing trailing / - maybe a nginx problem
if (substr(self::$query_string, 0, 1) == "/")
self::$query_string = substr(self::$query_string, 1);
}
if(x($_GET,'q'))
- self::$cmd = trim($_GET['q'],'/\\');
+ self::$cmd = escape_tags(trim($_GET['q'],'/\\'));
// unix style "homedir"
diff --git a/doc/Developers.md b/doc/Developers.md
index ef02c8327..624c058d2 100644
--- a/doc/Developers.md
+++ b/doc/Developers.md
@@ -8,17 +8,17 @@ doing development.
Create your own github account.
-You may fork/clone the Red repository from [https://github.com/redmatrix/hubzilla.git](https://github.com/redmatrix/hubzilla.git).
+You may fork/clone the $Projectname repository from [https://framagit.org/hubzilla/core.git](https://framagit.org/hubzilla/core.git).
Follow the instructions provided here: [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/)
-to create and use your own tracking fork on github
+to create and use your own tracking fork on framagit
-Then go to your github page and create a "Pull request" when you are ready
+Then go to your framagit page and create a "Pull request" when you are ready
to notify us to merge your work.
**Translations**
-Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [https://www.transifex.com/projects/p/red-matrix/](https://www.transifex.com/projects/p/red-matrix/) and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'messages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
+Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [https://www.transifex.com/projects/p/hubzilla/](https://www.transifex.com/projects/p/hubzilla/) and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'messages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
[Translations - More Info](help/Translations)
diff --git a/doc/Translations.md b/doc/Translations.md
index 654ba1b83..6106e43b1 100644
--- a/doc/Translations.md
+++ b/doc/Translations.md
@@ -4,13 +4,13 @@ Translating $Projectname
Translation Process
-------------------
-The strings used in the UI of Hubzilla is translated at [Transifex][1] and then
+The strings used in the UI of $Projectname is translated at [Transifex][1] and then
included in the git repository at github. If you want to help with translation
-for any language, be it correcting terms or translating Hubzilla to a
+for any language, be it correcting terms or translating $Projectname to a
currently not supported language, please register an account at transifex.com
and contact the Redmatrix translation team there.
-Translating Hubzilla is simple. Just use the online tool at transifex. If you
+Translating $Projectname is simple. Just use the online tool at transifex. If you
don't want to deal with git & co. that is fine, we check the status of the
translations regularly and import them into the source tree at github so that
others can use them.
@@ -26,32 +26,32 @@ tree.
If you want to get your work into the source tree yourself, feel free to do so
and contact us with and question that arises. The process is simple and
-Hubzilla ships with all the tools necessary.
+$Projectname ships with all the tools necessary.
The location of the translated files in the source tree is
/view/LNG-CODE/
where LNG-CODE is the language code used, e.g. de for German or fr for French.
For the email templates (the *.tpl files) just place them into the directory
and you are done. The translated strings come as a "hmessages.po" file from
-transifex which needs to be translated into the PHP file Hubzilla uses. To do
+transifex which needs to be translated into the PHP file $Projectname uses. To do
so, place the file in the directory mentioned above and use the "po2php"
-utility from the util directory of your Hubzilla installation.
+utility from the util directory of your $Projectname installation.
Assuming you want to convert the German localization which is placed in
view/de/hmessages.po you would do the following.
1. Navigate at the command prompt to the base directory of your
- Hubzilla installation
+ $Projectname installation
2. Execute the po2php script, which will place the translation
- in the hstrings.php file that is used by Hubzilla.
+ in the hstrings.php file that is used by $Projectname.
$> php util/po2php.php view/de/hmessages.po
The output of the script will be placed at view/de/hstrings.php where
froemdoca os expecting it, so you can test your translation mmediately.
-3. Visit your Hubzilla page to check if it still works in the language you
+3. Visit your $Projectname page to check if it still works in the language you
just translated. If not try to find the error, most likely PHP will give
you a hint in the log/warnings.about the error.
@@ -62,16 +62,16 @@ view/de/hmessages.po you would do the following.
$> php view/de/hstrings.php
4. commit the two files with a meaningful commit message to your git
- repository, push it to your fork of the Hubzilla repository at github and
+ repository, push it to your fork of the $Projectname repository at github and
issue a pull request for that commit.
Utilities
---------
Additional to the po2php script there are some more utilities for translation
-in the "util" directory of the Hubzilla source tree. If you only want to
-translate Hubzilla into another language you wont need any of these tools most
-likely but it gives you an idea how the translation process of Hubzilla
+in the "util" directory of the $Projectname source tree. If you only want to
+translate $Projectname into another language you wont need any of these tools most
+likely but it gives you an idea how the translation process of $Projectname
works.
For further information see the utils/README file.
@@ -79,7 +79,7 @@ For further information see the utils/README file.
Known Problems
--------------
-* Hubzilla uses the language setting of the visitors browser to determain the
+* $Projectname uses the language setting of the visitors browser to determain the
language for the UI. Most of the time this works, but there are some known
quirks.
* the early translations are based on the friendica translations, if you
@@ -87,7 +87,7 @@ Known Problems
Links
------
-[1]: http://www.transifex.com/projects/p/red-matrix/
+[1]: http://www.transifex.com/projects/p/hubzilla/
#include doc/macros/main_footer.bb;
diff --git a/doc/context/es-es/articles/help.html b/doc/context/es-es/articles/help.html
new file mode 100644
index 000000000..0bf176fdd
--- /dev/null
+++ b/doc/context/es-es/articles/help.html
@@ -0,0 +1,20 @@
+<dl class="dl-horizontal">
+ <dt>General</dt>
+ <dd>El artículo es un tipo de documento de una naturaleza un poco especial, a mitad de camino entre las fichas de organización de trabajo ("cards") y las entradas normales, pero que está separado del stream social. Son muy adecuados para ayudar a escribir y organizar textos, con un formateo básico, pero completo, sobre cualquier tema, especialmente sobre documentación seriada, de forma más amplia que un wiki pero menos que un página web. Al no formar parte del stream social, para acceder a él hace falta conocer su dirección: <b>[URL del sitio]/articles/[nombre del usuario, sin dominio]</b>. Ahí estarán disponibles los distintas artículos que escriba, por orden de publicación.</dd>
+ <dt>Crear un artículo</dt>
+ <dd>
+ Crear un artículo nuevo es muy parecido a componer un nuevo post.<br><br>
+ <ul>
+ <li>
+ <b>Nombre del enlace de la página</b>: Este nombre es el del nombre del artículo para una URL estática
+ </li>
+ <li>
+ <b>Título</b>: El título se muestra en la parte de arriba del artículo
+ </li>
+ <li>
+ <b>Temas o Categorías</b>: Si tiene activada la opción <a href="/settings/features">Temas de las entradas</a> en su canal, entonces puede añadirlos al artículo. Estas categorías o temas se despliegan en la lista <b>Temas</b> en el panel de la izquierda y permiten filtrar su colección de artículos.
+ </li>
+ <li> <b>Sumario</b>: Es el espacio, entre las etiquetas predefinidas [summary][/summary], reservado para redactar un resumen del artículo, que aparecerá en su encabezado. El espacio disponible a continuación del sumario, en la ventana de composición, es el adecuado para la redacción del artículo en sí.
+ </ul>
+ </dd>
+</dl> \ No newline at end of file
diff --git a/doc/developer/developer_guide.bb b/doc/developer/developer_guide.bb
index f8ba0c1d8..d04cec121 100644
--- a/doc/developer/developer_guide.bb
+++ b/doc/developer/developer_guide.bb
@@ -53,29 +53,27 @@ The [url=[baseurl]/help/admin/hub_snapshots]hub snapshots[/url] page provides in
[h3]Translations[/h3]
-Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [url=https://www.transifex.com/Friendica/red-matrix/]Transifex[/url] and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'messages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
+Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [url=https://www.transifex.com/Friendica/hubzilla/]Transifex[/url] and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'messages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
[h4]Translation Process[/h4]
-The strings used in the UI of $Projectname is translated at [url=https://www.transifex.com/Friendica/red-matrix/]Transifex[/url] and then
+The strings used in the UI of $Projectname is translated at [url=https://www.transifex.com/Friendica/hubzilla/]Transifex[/url] and then
included in the git repository at github. If you want to help with translation
for any language, be it correcting terms or translating $Projectname to a
currently not supported language, please register an account at transifex.com
-and contact the Redmatrix translation team there.
+and contact the translation team there.
Translating $Projectname is simple. Just use the online tool at transifex. If you
-don't want to deal with git & co. that is fine, we check the status of the[/td][/tr]
-[tr]ranslations regularly and import them into the source tree at github so that
-others can use them.
+don't want to deal with git & co. that is fine, we check the status of the translations
+regularly and import them into the source tree at github so that others can use them.
We do not include every translation from transifex in the source tree to avoid
a scattered and disturbed overall experience. As an uneducated guess we have a
lower limit of 50% translated strings before we include the language. This
-limit is judging only by the amount of translated strings under the assumption[/td][/tr]
-[tr]hat the most prominent strings for the UI will be translated first by a[/td][/tr]
-[tr]ranslation team. If you feel your translation useable before this limit,
-please contact us and we will probably include your teams work in the source[/td][/tr]
-[tr]ree.
+limit is judging only by the amount of translated strings under the assumption
+that the most prominent strings for the UI will be translated first by a translation
+team. If you feel your translation useable before this limit,
+please contact us and we will probably include your teams work in the source tree.
If you want to get your work into the source tree yourself, feel free to do so
and contact us with and question that arises. The process is simple and
@@ -85,8 +83,8 @@ The location of the translated files in the source tree is
/view/LNG-CODE/
where LNG-CODE is the language code used, e.g. de for German or fr for French.
For the email templates (the *.tpl files) just place them into the directory
-and you are done. The translated strings come as a "hmessages.po" file from[/td][/tr]
-[tr]ransifex which needs to be translated into the PHP file $Projectname uses. To do
+and you are done. The translated strings come as a "hmessages.po" file from
+Transifex which needs to be translated into the PHP file $Projectname uses. To do
so, place the file in the directory mentioned above and use the "po2php"
utility from the util directory of your $Projectname installation.
@@ -121,8 +119,8 @@ view/de/hmessages.po you would do the following.
[h4]Utilities[/h4]
Additional to the po2php script there are some more utilities for translation
-in the "util" directory of the $Projectname source tree. If you only want to[/td][/tr]
-[tr]ranslate $Projectname into another language you wont need any of these tools most
+in the "util" directory of the $Projectname source tree. If you only want to
+translate $Projectname into another language you wont need any of these tools most
likely but it gives you an idea how the translation process of $Projectname
works.
diff --git a/doc/developers.bb b/doc/developers.bb
index f8489640b..22dc82d7e 100644
--- a/doc/developers.bb
+++ b/doc/developers.bb
@@ -1,72 +1,71 @@
-[b]$Projectname Developer Guide[/b]
-
-We're pretty relaxed when it comes to developers. We don't have a lot of rules. Some of us are over-worked and if you want to help we're happy to let you help. That said, attention to a few guidelines will make the process smoother and make it easier to work together. All developers are expected to abide by our [zrl=[baseurl]/help/contributor/covenant]code of conduct[/zrl]. We have developers from across the globe with different abilities and different cultural backgrounds and different levels of patience. Our primary rule is to respect others. Sometimes this is hard and sometimes we have very different opinions of how things should work, but if everybody makes an effort, we'll get along just fine.
-
-[b]Here is how you can join us.[/b]
-
-First, get yourself a working git package on the system where you will be
-doing development.
-
-Create your own github account.
-
-You may fork/clone the Red repository from [url=https://github.com/redmatrix/hubzilla.git]https://github.com/redmatrix/hubzilla.git[/url]
-
-Follow the instructions provided here: [url=http://help.github.com/fork-a-repo/]http://help.github.com/fork-a-repo/[/url]
-to create and use your own tracking fork on github
-
-Then go to your github page and create a &quot;Pull request&quot; when you are ready
-to notify us to merge your work.
-
-[b]Translations[/b]
-
-Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [url=https://www.transifex.com/projects/p/red-matrix/]https://www.transifex.com/projects/p/red-matrix/[/url] and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'messages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
-
-[zrl=[baseurl]/help/Translations]Translations - More Info[/zrl]
-
-[b]Important[/b]
-
-Please pull in any changes from the project repository and merge them with your work **before** issuing a pull request. We reserve the right to reject any patch which results in a large number of merge conflicts. This is especially true in the case of language translations - where we may not be able to understand the subtle differences between conflicting versions.
-
-Also - **test your changes**. Don't assume that a simple fix won't break something else. If possible get an experienced Red developer to review the code.
-
-Further documentation can be found at the Github wiki pages at: [url=https://github.com/friendica/red/wiki]https://github.com/friendica/red/wiki[/url]
-
-[b]Licensing[/b]
-
-All code contributed to the project falls under the MIT license, unless otherwise specified. We will accept third-party code which falls under MIT, BSD and LGPL, but copyleft licensing (GPL, and AGPL) is only permitted in addons. It must be possible to completely remove the GPL (copyleft) code from the main project without breaking anything.
-
-[b]Concensus Building[/b]
-
-Code changes which fix an obvious bug are pretty straight-forward. For instance if you click "Save" and the thing you're trying to save isn't saved, it's fairly obvious what the intended behaviour should be. Often when developing feature requests, it may affect large numbers of community members and it's possible that other members of the community won't agree with the need for the feature, or with your proposed implementation. They may not see something as a bug or a desirable feature.
-
-We encourage consensus building within the community when it comes to any feature which might be considered controversial or where there isn't unanimous decision that the proposed feature is the correct way to accomplish the task. The first place to pitch your ideas is to [url=https://zothub.com/channel/one]Channel One[/url]. Others may have some input or be able to point out facets of your concept which might be problematic in our environment. But also, you may encounter opposition to your plan. This doesn't mean you should stop and/or ignore the feature. Listen to the concerns of others and try and work through any implementation issues.
-
-There are places where opposition cannot be resolved. In these cases, please consider making your feature [b]optional[/b] or non-default behaviour that must be specifically enabled. This technique can often be used when a feature has significant but less than unanimous support. Those who desire the feature can turn it on and those who don't want it - will leave it turned off.
-
-If a feature uses other networks or websites and or is only seen as desirable by a small minority of the community, consider making the functionality available via an addon or plugin. Once again, those who don't desire the feature won't need to install it. Plugins are relatively easy to create and "hooks" can be easily added or modified if the current hooks do not do what is needed to allow your plugin to work.
-
-
-[b]Coding Style[/b]
-
-In the interests of consistency we adopt the following code styling. We may accept patches using other styles, but where possible please try to provide a consistent code style. We aren't going to argue or debate the merits of this style, and it is irrelevant what project 'xyz' uses. This is not project 'xyz'. This is a baseline to try and keep the code readable now and in the future.
-
-[li] All comments should be in English.[/li]
-
-[li] We use doxygen to generate documentation. This hasn't been consistently applied, but learning it and using it are highly encouraged.[/li]
-
-[li] Indentation is accomplished primarily with tabs using a tab-width of 4.[/li]
-
-[li] String concatenation and operators should be separated by whitespace. e.g. &quot;$foo = $bar . 'abc';&quot; instead of &quot;$foo=$bar.'abc';&quot;[/li]
-
-[li] Generally speaking, we use single quotes for string variables and double quotes for SQL statements. &quot;Here documents&quot; should be avoided. Sometimes using double quoted strings with variable replacement is the most efficient means of creating the string. In most cases, you should be using single quotes.[/li]
-
-[li] Use whitespace liberally to enhance readability. When creating arrays with many elements, we will often set one key/value pair per line, indented from the parent line appropriately. Lining up the assignment operators takes a bit more work, but also increases readability.[/li]
-
-[li] Generally speaking, opening braces go on the same line as the thing which opens the brace. They are the last character on the line. Closing braces are on a line by themselves. [/li]
-
-[li] Some functions take arguments in argc/argv style like main() in C or function args in bash or Perl. Urls are broken up within a module. e.g, given "http://example.com/module/arg1/arg2", then $this->argc will be 3 (integer) and $this->argv will contain: [0] => 'module', [1] => 'arg1', [2] => 'arg2'. There will always be one argument. If provided a naked domain URL, $this->argv[0] is set to "home".[/li]
-
-[b]See Also[/b]
-[zrl=[baseurl]/help/sql_conventions]SQL Conventions[/zrl]
-
-#include doc/macros/main_footer.bb;
+[b]$Projectname Developer Guide[/b]
+
+We're pretty relaxed when it comes to developers. We don't have a lot of rules. Some of us are over-worked and if you want to help we're happy to let you help. That said, attention to a few guidelines will make the process smoother and make it easier to work together. All developers are expected to abide by our [zrl=[baseurl]/help/contributor/covenant]code of conduct[/zrl]. We have developers from across the globe with different abilities and different cultural backgrounds and different levels of patience. Our primary rule is to respect others. Sometimes this is hard and sometimes we have very different opinions of how things should work, but if everybody makes an effort, we'll get along just fine.
+
+[b]Here is how you can join us.[/b]
+
+First, get yourself a working git package on the system where you will be
+doing development.
+
+Create your own github account.
+
+You may fork/clone the project repository from [url=https://framagit.org/hubzilla/core.git]https://framagit.org/hubzilla/core.git[/url]
+
+Follow the instructions provided here: [url=http://help.github.com/fork-a-repo/]http://help.github.com/fork-a-repo/[/url]
+to create and use your own tracking fork on framagit
+
+Then go to your framagit page and create a &quot;Pull request&quot; when you are ready
+to notify us to merge your work.
+
+[b]Translations[/b]
+
+Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [url=https://www.transifex.com/projects/p/hubzilla/]https://www.transifex.com/projects/p/hubzilla/[/url] and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'hmessages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
+
+[zrl=[baseurl]/help/Translations]Translations - More Info[/zrl]
+
+[b]Important[/b]
+
+Please pull in any changes from the project repository and merge them with your work **before** issuing a pull request. We reserve the right to reject any patch which results in a large number of merge conflicts. This is especially true in the case of language translations - where we may not be able to understand the subtle differences between conflicting versions.
+
+Also - **test your changes**. Don't assume that a simple fix won't break something else. If possible get an experienced Red developer to review the code.
+
+
+[b]Licensing[/b]
+
+All code contributed to the project falls under the MIT license, unless otherwise specified. We will accept third-party code which falls under MIT, BSD and LGPL, but copyleft licensing (GPL, and AGPL) is only permitted in addons. It must be possible to completely remove the GPL (copyleft) code from the main project without breaking anything.
+
+[b]Concensus Building[/b]
+
+Code changes which fix an obvious bug are pretty straight-forward. For instance if you click "Save" and the thing you're trying to save isn't saved, it's fairly obvious what the intended behaviour should be. Often when developing feature requests, it may affect large numbers of community members and it's possible that other members of the community won't agree with the need for the feature, or with your proposed implementation. They may not see something as a bug or a desirable feature.
+
+We encourage consensus building within the community when it comes to any feature which might be considered controversial or where there isn't unanimous decision that the proposed feature is the correct way to accomplish the task. The first place to pitch your ideas is to the [url=https://project.hubzilla.org/channel/hubzilla]Hubzilla Development[/url] forum. Others may have some input or be able to point out facets of your concept which might be problematic in our environment. But also, you may encounter opposition to your plan. This doesn't mean you should stop and/or ignore the feature. Listen to the concerns of others and try and work through any implementation issues.
+
+There are places where opposition cannot be resolved. In these cases, please consider making your feature [b]optional[/b] or non-default behaviour that must be specifically enabled. This technique can often be used when a feature has significant but less than unanimous support. Those who desire the feature can turn it on and those who don't want it - will leave it turned off.
+
+If a feature uses other networks or websites and or is only seen as desirable by a small minority of the community, consider making the functionality available via an addon or plugin. Once again, those who don't desire the feature won't need to install it. Plugins are relatively easy to create and "hooks" can be easily added or modified if the current hooks do not do what is needed to allow your plugin to work.
+
+
+[b]Coding Style[/b]
+
+In the interests of consistency we adopt the following code styling. We may accept patches using other styles, but where possible please try to provide a consistent code style. We aren't going to argue or debate the merits of this style, and it is irrelevant what project 'xyz' uses. This is not project 'xyz'. This is a baseline to try and keep the code readable now and in the future.
+
+[li] All comments should be in English.[/li]
+
+[li] We use doxygen to generate documentation. This hasn't been consistently applied, but learning it and using it are highly encouraged.[/li]
+
+[li] Indentation is accomplished primarily with tabs using a tab-width of 4.[/li]
+
+[li] String concatenation and operators should be separated by whitespace. e.g. &quot;$foo = $bar . 'abc';&quot; instead of &quot;$foo=$bar.'abc';&quot;[/li]
+
+[li] Generally speaking, we use single quotes for string variables and double quotes for SQL statements. &quot;Here documents&quot; should be avoided. Sometimes using double quoted strings with variable replacement is the most efficient means of creating the string. In most cases, you should be using single quotes.[/li]
+
+[li] Use whitespace liberally to enhance readability. When creating arrays with many elements, we will often set one key/value pair per line, indented from the parent line appropriately. Lining up the assignment operators takes a bit more work, but also increases readability.[/li]
+
+[li] Generally speaking, opening braces go on the same line as the thing which opens the brace. They are the last character on the line. Closing braces are on a line by themselves. [/li]
+
+[li] Some functions take arguments in argc/argv style like main() in C or function args in bash or Perl. Urls are broken up within a module. e.g, given "http://example.com/module/arg1/arg2", then $this->argc will be 3 (integer) and $this->argv will contain: [0] => 'module', [1] => 'arg1', [2] => 'arg2'. There will always be one argument. If provided a naked domain URL, $this->argv[0] is set to "home".[/li]
+
+[b]See Also[/b]
+[zrl=[baseurl]/help/sql_conventions]SQL Conventions[/zrl]
+
+#include doc/macros/main_footer.bb;
diff --git a/doc/es b/doc/es
new file mode 120000
index 000000000..c8ba7666b
--- /dev/null
+++ b/doc/es
@@ -0,0 +1 @@
+es-es \ No newline at end of file
diff --git a/doc/es-es/TermsOfService.md b/doc/es-es/TermsOfService.md
new file mode 100644
index 000000000..0963ae38e
--- /dev/null
+++ b/doc/es-es/TermsOfService.md
@@ -0,0 +1,10 @@
+Política de privacidad
+==============
+
+#include doc/gdpr1.md;
+
+
+Condiciones de uso
+================
+
+#include doc/SiteTOS.md; \ No newline at end of file
diff --git a/doc/es-es/about/about.bb b/doc/es-es/about/about.bb
new file mode 100644
index 000000000..731bdef85
--- /dev/null
+++ b/doc/es-es/about/about.bb
@@ -0,0 +1,209 @@
+[h3]¿Qué es $Projectname?[/h3]
+$Projectname es un conjunto [b]gratuito y de código abierto[/b] de aplicaciones y servicios web que se ejecutan en un tipo especial de servidor web, llamado "hub", que puede conectarse a otros hubs en una red descentralizada que nos gusta llamar "la red", proporcionando sofisticados servicios de comunicaciones, identidad y control de acceso que funcionan juntos a la perfección a través de dominios y sitios web independientes. Permite a cualquiera publicar, pública o[b]privadamente[/b], contenidos a través de "canales", que son las identidades fundamentales, criptográficamente seguras, que proporcionan autenticación independientemente de los hubs que los alojan. Esta revolucionaria liberación de la identidad en línea a partir de servidores y dominios individuales se denomina "identidad nómada" y está impulsada por el protocolo Zot, un nuevo marco para el control de acceso descentralizado con permisos bien definidos y extensibles.
+
+[h3] De acuerdo... pero, entonces, ¿qué es $Projectname?[/h3]
+Desde la perspectiva práctica de los miembros del hub que utilizan el software, $Projectname ofrece una variedad de aplicaciones y servicios web familiares e integrados, incluyendo:
+[ul]
+[li]hilos de discusión de redes sociales[/li]
+[li]almacenamiento de archivos de nube[/li]
+[li]Calendario y contactos (con soporte CalDAV y CardDAV)[/li]
+[li]alojamiento de páginas web con un sistema de gestión de contenidos[/li]
+[li]wiki[/li]
+[li]y más...[/li][/ul]
+Aunque todas estas aplicaciones y servicios se pueden encontrar en otros paquetes de software, sólo $Projectname le permite establecer permisos para grupos e individuos que pueden no tener cuentas en tu hub. En las aplicaciones web típicas, si desea compartir cosas en privado en Internet, las personas con las que comparte deben tener cuentas en el servidor que aloja sus datos; de lo contrario, no hay una forma sólida para que su servidor[i]autentifique[/i] a los visitantes del sitio para saber si les concede acceso. $Projectname resuelve este problema con un sistema avanzado de[i]autenticación remota[/i] que valida la identidad de los visitantes empleando técnicas que incluyen criptografía de clave pública.
+
+
+[h3]El software[/h3]
+
+$Projectname es, básicamente, una aplicación de servidor web relativamente estándar escrita principalmente en PHP/MySQL [url=https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt][/url], que requiere poco más que un servidor web, una base de datos compatible con MySQL y el lenguaje de scripting PHP. Está diseñado para ser fácilmente instalable por aquellos con habilidades básicas de administración de sitios web en plataformas típicas de alojamiento compartido con una amplia gama de hardware informático. También se puede extender fácilmente a través de plugins y temas y otras herramientas de terceros.
+
+[h3]Glosario[/h3]
+
+[dl terms="b"]
+Una instancia de este software ejecutándose en un servidor web estándar
+
+[grid] Red global de hubs que intercambian información entre sí utilizando el protocolo Zot.
+
+La identidad fundamental en la cuadrícula. Un canal puede representar a una persona, un blog o un foro, por nombrar algunos. Los canales pueden hacer conexiones con otros canales para compartir información con permisos muy detallados.
+
+Los canales pueden tener clones asociados con cuentas separadas y otras cuentas no relacionadas en hubs independientes. Las comunicaciones compartidas con un canal se sincronizan entre los clones del canal, permitiendo que un canal envíe y reciba mensajes y acceda a contenido compartido desde múltiples hubs. Esto proporciona resistencia contra fallas en la red y en el hardware, lo que puede ser un problema significativo para los servidores web autohospedados o de recursos limitados. La clonación le permite mover completamente un canal de un hub a otro, llevando sus datos y conexiones con usted. Ver identidad nómada.
+
+Identidad nómada] La capacidad de autenticar y migrar fácilmente una identidad a través de concentradores y dominios web independientes. La identidad nómada proporciona una verdadera propiedad de una identidad en línea, porque las identidades de los canales controlados por una cuenta en un hub no están vinculadas al propio hub. Un hub es más como un "host" para canales. Con Hubzilla, no tienes una "cuenta" en un servidor como lo haces en sitios web típicos; tienes una identidad que puedes llevarte a través de la rejilla usando clones.
+
+Traducción y sincronización: El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo para el control de acceso distribuido a escala de Internet que es discreto.
+[/dl]
+
+[h3]Características[/h3]
+
+Esta página enumera algunas de las características principales de $Projectname que se incluyen en la versión oficial. $Projectname es una plataforma altamente extensible, por lo que se pueden añadir más características y capacidades a través de temas y plugins adicionales.
+
+[h4]Control deslizante de afinidad[/h4]
+
+Cuando se añaden conexiones en $Projectname, los miembros tienen la opción de asignar niveles de "afinidad" (cuán cerca está su amigo).
+Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad de "Amigos".
+
+En este punto, la herramienta $Projectname [i]Control deslizante de afinidad[/i], que normalmente aparece en la parte superior de la página, ajusta su contenido para incluir aquellos contactos que están dentro del rango de afinidad deseado. Los canales fuera de ese rango no se mostrarán, a menos que ajuste el control deslizante para incluirlos.
+
+El control deslizante de afinidad permite el filtrado instantáneo de grandes cantidades de contenido, agrupado por niveles de cercanía.
+
+[h4]Filtrado de conexiones[/h4]
+
+Usted tiene la capacidad de controlar con precisión lo que aparece en su flujo usando el "Filtro de conexión" opcional. Cuando está habilitado, el Editor de conexión proporciona entradas para seleccionar los criterios que deben coincidir para incluir o excluir un mensaje específico de un canal específico. Una vez que un mensaje ha sido permitido, todos los comentarios a ese mensaje son permitidos sin importar si coinciden o no con los criterios de selección. Puede seleccionar las palabras que, si están presentes, bloquean el mensaje o se aseguran de que esté incluido en su stream. Se pueden utilizar expresiones regulares para un control aún más preciso, así como hashtags o incluso el idioma detectado del mensaje.
+
+[h4]Listas de Control de Acceso[/h4]
+
+Al compartir contenido, los miembros tienen la opción de restringir quién ve el contenido. Al hacer clic en el candado debajo del cuadro de compartir, uno puede elegir los destinatarios deseados del mensaje, haciendo clic en sus nombres.
+
+Una vez enviado, el mensaje sólo podrá ser visto por el remitente y los destinatarios seleccionados. En otras palabras, el mensaje no aparecerá en ningún muro público.
+
+Las listas de control de acceso se pueden aplicar a contenido y mensajes, fotos, eventos, páginas web, salas de chat y archivos.
+
+[h4]Inicio de sesión único[/h4]
+
+Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en el hub de su casa. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica".
+
+
+[h4]Almacenamiento de Archivos habilitado para WebDAV[/h4]
+
+Los ficheros se pueden cargar en su área de almacenamiento personal utilizando las utilidades de su sistema operativo (arrastrar y soltar en la mayoría de los casos). Usted puede proteger estos archivos con Listas de Control de Acceso a cualquier combinación de miembros de $Projectname (incluyendo algunos miembros de una red de terceros) o hacerlos públicos.
+
+[h4]Álbumes de Fotos[/h4]
+
+Almacenar fotos en álbumes. Todas sus fotos pueden estar protegidas por Listas de Control de Acceso.
+
+[h4]Calendario de eventos[/h4]
+
+Cree y gestione eventos y tareas, que también pueden estar protegidos con Listas de Control de Acceso. Los eventos pueden importarse/exportarse a otro software utilizando el formato vcalendar/iCal estándar de la industria y compartirse en mensajes con otros. Los eventos de cumpleaños de tus amigos se añaden automáticamente y se convierten a tu zona horaria correcta para que sepas exactamente cuándo ocurre el cumpleaños, sin importar en qué parte del mundo estés en relación con la persona que cumple años. Los eventos normalmente se crean con contadores de asistencia para que sus amigos y conexiones puedan confirmar su asistencia instantáneamente.
+
+[h4]Salas de chat[/h4]
+
+Puede crear cualquier número de salas de chat personales y permitir el acceso a través de las listas de control de acceso. Éstas son típicamente más seguras que XMPP, IRC, y otros transportes de Mensajería Instantánea, aunque también permitimos el uso de estos otros servicios a través de plugins.
+
+[h4]Construcción de Páginas Web[/h4]
+
+El nombre del proyecto tiene muchas herramientas de creación de "Gestión de contenidos" para construir páginas web, incluyendo edición de diseño, menús, bloques, widgets y regiones de página/contenido. Todo esto puede ser controladospara que las páginas resultantes sean privadas para la audiencia a la que están destinadas.
+
+[h4]Aplicaciones[/h4]
+
+Las aplicaciones pueden ser construidas y distribuidas por los miembros. Éstas se diferencian de las aplicaciones tradicionales de "bloqueo de proveedores" porque están completamente controladas por el autor, que puede proporcionar control de acceso en las páginas de aplicaciones de destino y cobrar en consecuencia por este acceso. La mayoría de las aplicaciones en $Projectname son gratuitas y pueden ser creadas fácilmente por aquellos sin conocimientos de programación.
+
+[h4]Diseño[/h4
+
+El diseño de la página se basa en un lenguaje de descripción llamado comanche. El propio nombre del proyecto está escrito en diseños comanches que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario".
+
+[h4]Marcadores[/h4]
+
+Comparta y guarde/maneje los marcadores de los enlaces proporcionados en las conversaciones.
+
+[h4]Cifrado privado de mensajes y cuestiones de privacidad[/h4]
+
+El correo privado se almacena en un formato "oscuro". Aunque este no es a prueba de balas, por lo general evita que el administrador del sitio o el ISP husmeen ocasionalmente.
+
+Cada canal $Projectname tiene su propio conjunto único de claves RSA 4096-bit privadas y públicas asociadas, generadas cuando se crean los canales por primera vez. Se utiliza para proteger mensajes privados y mensajes en tránsito.
+
+Además, los mensajes pueden crearse utilizando "encriptación de extremo a extremo" que no puede ser leída por los operadores de nombres de proyecto o ISPs o cualquier persona que no conozca el código de acceso.
+
+Por lo general, los mensajes públicos no se cifran durante el transporte ni durante el almacenamiento.
+
+Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído todavía.
+
+Los mensajes se pueden crear con una fecha de caducidad, en la que se borrarán/quitarán en el sitio del destinatario.
+
+
+[h4]Federación de Servicios[/h4]
+
+Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde/hacia la diáspora, Friendica, GNU-Social, Mastodon y otros proveedores que utilizan estos protocolos.
+
+También existe soporte experimental para la autenticación OpenID que puede utilizarse en las listas de control de acceso. Este es un trabajo en progreso. Su hub $Projectname puede ser utilizado como un proveedor de OpenID para autenticarle en servicios externos que utilizan esta tecnología.
+
+Los canales pueden tener permisos para convertirse en "canales derivados" cuando dos o más canales existentes se combinan para crear un nuevo canal temático.
+
+[h4]Grupos de Privacidad[/h4]
+
+Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de la Diáspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo).
+
+
+[h4]Servicios de directorio[/h4]
+
+Proporcionamos un acceso fácil a un directorio de miembros y proporcionamos herramientas descentralizadas capaces de proporcionar "sugerencias" de amigos. Los directorios son sitios normales de $Projectname que han elegido aceptar el rol de servidor de directorio. Esto requiere más recursos que la mayoría de los sitios típicos, por lo que no es un servicio predeterminado. Los directorios están sincronizados y duplicados de forma que todos contengan información actualizada sobre toda la red (sujeta a los retardos normales de propagación).
+
+
+[h4]TLS/SSL[/h4]
+
+En el caso de los concentradores de nombres de proyecto que utilizan TLS/SSL, las comunicaciones de cliente a servidor se cifran mediante TLS/SSL. Dadas las recientes revelaciones en los medios de comunicación con respecto a la vigilancia global generalizada y la elusión del cifrado por parte de NSA y GCHQ, es razonable asumir que las comunicaciones protegidas por HTTPS pueden verse comprometidas de varias maneras. Por consiguiente, las comunicaciones privadas se cifran a un nivel superior antes de enviarlas fuera del sitio.
+
+[h4]Ajustes de canal[/h4]
+
+Cuando se crea un canal, se elige una función que aplica una serie de configuraciones de seguridad y privacidad preconfiguradas. Éstos se eligen en función de las mejores prácticas para mantener la privacidad en los niveles solicitados.
+
+Si elige una función de privacidad "personalizada", cada canal permite establecer permisos precisos para varios aspectos de la comunicación. Por ejemplo, bajo el encabezado "Ajustes de seguridad y privacidad", cada aspecto del lado izquierdo de la página tiene seis (6) opciones de visualización/acceso posibles, que pueden seleccionarse haciendo clic en el menú desplegable. También hay otras configuraciones de privacidad que puedes editar.
+
+Las opciones son:
+
+ Nadie excepto usted mismo.
+ Sólo aquellos que usted permita específicamente.
+ Cualquiera en sus conexiones aprobadas.
+ Cualquiera en este sitio web.
+ Cualquiera en esta red.
+ Cualquiera autentificado.
+ Cualquiera en Internet.
+
+
+[h4]Foros Públicos y Privados[/h4]
+
+Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros: 1) mensajes de "muro a muro" y 2) a través de las etiquetas @mención del foro. Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros.
+
+[h4]Clonación de cuentas[/h4]
+
+Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando creas una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com.
+
+Por el contrario, digamos que ha creado una identidad $Projectname llamada[b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b]
+
+Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envías un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas.
+
+Esta es una característica bastante revolucionaria, si consideramos algunos escenarios:
+
+ ¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tienesque iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre.
+
+ El administrador de su hub ya no puede permitirse el lujo de pagar por su hub gratuito y público $Projectname. Anuncia que el centro cerrará en dos semanas. Esto le da tiempo suficiente para clonar su(s) identidad(es) y preservar las relaciones, amigos y contenido de su $Projectname.
+
+ ¿Qué sucede si su identidad está sujeta a la censura del gobierno? Es posible que su proveedor de hubs se vea obligado a eliminar su cuenta, junto con las identidades y los datos asociados. Con la clonación, $Projectname ofrece [b]resistencia a la censura[/b]. Usted puede tener cientos de clones, si lo desea, todos con diferentes nombres, y que existen en muchos hubs diferentes, esparcidos por todo el Internet.
+
+$Projectname ofrece nuevas e interesantes posibilidades de privacidad. Puede leer más en la página <<Buenas Prácticas de Comunicación Privada>>.
+
+Se aplican algunas advertencias. Para una explicación completa de la clonación de identidad, lea el documento <HOW TO CLONE MY IDENTITY>.
+
+[h4]Perfiles Múltiples[/h4]
+
+Se puede crear cualquier número de perfiles que contengan información diferente y éstos pueden hacerse visibles para algunas de sus conexiones/amigos. Un perfil "predeterminado" puede ser visto por cualquiera y puede contener información limitada, con más información disponible para seleccionar grupos o personas. Esto significa que el perfil (y el contenido del sitio) que ven sus compañeros de trabajo puede ser diferente de lo que ven sus compañeros de trabajo, y también completamente diferente de lo que es visible para el público en general.
+
+[h4]Copia de seguridad de la cuenta[/h4]
+
+$Projectname ofrece una sencilla copia de seguridad de la cuenta con un solo clic, en la que puede descargar una copia de seguridad completa de su(s) perfil(es). Las copias de seguridad se pueden utilizar para clonar o restaurar un perfil.
+
+[h4]Borrado de cuenta[/h4]
+
+Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la rejilla (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible.
+
+[h4]Supresión de contenido[/h4]
+Cualquier contenido creado en $Projectname permanece bajo el control del miembro (o canal) que lo creó originalmente. En cualquier momento, un miembro puede borrar un mensaje o un rango de mensajes. El proceso de eliminación garantiza que el contenido se elimine, independientemente de si se publicó en el concentrador principal (doméstico) de un canal o en otro concentrador, donde el canal se autenticó de forma remota a través de Zot (protocolo de autenticación y comunicación de $Projectname).
+
+[h4]Medios[/h4]
+
+Al igual que cualquier otro sistema moderno de blogging, red social, o un servicio de micro-blogging, $Projectname soporta la carga de archivos, incrustación de video y vinculación de páginas web.
+
+[h4]Previsualización/Edición[/h4]
+Los mensajes y comentarios se pueden previsualizar antes de enviarlos y editarlos después de enviarlos.
+
+[h4]Votación/Consenso[/h4]
+
+Los mensajes pueden convertirse en elementos de "consenso" que permiten a los lectores ofrecer retroalimentación, que se recopila en contadores de "acuerdo", "desacuerdo" y "abstención". Esto le permite medir el interés por las ideas y crear encuestas informales.
+
+[h4]Extendiendo $Nombre del proyecto[/h4]
+
+El nombre del proyecto se puede ampliar de varias maneras, a través de la personalización del sitio, personalización, configuración de opciones, temas y complementos/plugins.
+
+[h4]API[/h4]
+
+
+Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth es proporcionado. \ No newline at end of file
diff --git a/doc/es-es/about/about_hub.bb b/doc/es-es/about/about_hub.bb
new file mode 100644
index 000000000..92faeb9f0
--- /dev/null
+++ b/doc/es-es/about/about_hub.bb
@@ -0,0 +1,7 @@
+[h3]Información del sitio[/h3]
+[list][*][url=[baseurl]/siteinfo]Información del sitio[/url]
+[*][url=[baseurl]/siteinfo/json]Información del sitio (en formato JSON)[/url][/list]
+[h3]Términos del Servicio[/h3]
+[list][*][url=[baseurl]/help/TermsOfService]Términos de servicio de este hub[/url][/list]
+#include doc/SiteTOS.md;
+
diff --git a/doc/es-es/about/project.bb b/doc/es-es/about/project.bb
new file mode 100644
index 000000000..6871869d5
--- /dev/null
+++ b/doc/es-es/about/project.bb
@@ -0,0 +1,185 @@
+[h3]$Nombre del proyecto Gobernanza[/h3]
+
+La gobernanza se relaciona con la gestión de un proyecto y, en particular, con su relación con la resolución de conflictos.
+
+[h4]Gobernanza de la comunidad[/h4]
+
+El proyecto es mantenido y las decisiones tomadas por la "comunidad". La estructura de gobernanza sigue evolucionando. Hasta que se finalice la estructura, las decisiones se toman en el siguiente orden:
+
+[ol]
+Consenso perezoso
+
+Si se presenta una propuesta de proyecto a uno de los foros de gobierno de la comunidad y no hay objeciones serias en un plazo "razonable" desde la fecha de la propuesta (por lo general, disponemos de 2 a 3 días para que todas las partes interesadas puedan opinar), no es necesario votar y la propuesta se considerará aprobada. En este momento se pueden plantear algunas preocupaciones, pero si éstas se abordan durante la discusión y se proporcionan soluciones provisionales, se considerarán aprobadas.
+
+
+[*] Veto
+
+Los desarrolladores senior con un historial significativo de proyectos se comprometen a vetar cualquier decisión. La decisión no podrá adoptarse hasta que se retire el veto o se presente una propuesta alternativa.
+
+
+Voto Comunitario
+
+Una decisión que no tiene un mandato claro o un consenso claro, pero que no es vetada, puede ser llevada a votación comunitaria. En la actualidad se trata de un simple voto popular en uno de los foros comunitarios aplicables. En este momento, el voto popular decide el resultado. Esto puede cambiar en el futuro si la comunidad adopta un modelo de gobierno de "consejo". Este documento se actualizará en ese momento con las reglas de gobierno actualizadas.
+[/ol]
+
+El Voto Comunitario no siempre proporciona un resultado agradable y puede generar facciones polarizadas en la comunidad (de ahí la razón por la que se están considerando otros modelos). Si la propuesta es "rechazada" todavía hay varias cosas que se pueden hacer y la propuesta se vuelve a presentar con parámetros ligeramente diferentes (convertir a un complemento, convertir a una característica opcional que está desactivada por defecto, etc.). Si el interés en la película es alto y la votación es "cercana", puede generar muchos malos sentimientos entre los votantes perdedores. En estas votaciones tan reñidas, se[b]recomienda encarecidamente[/b] que el proponente tome medidas para abordar cualquier inquietud que se haya planteado y vuelva a presentar.
+
+
+
+[h4]Política de privacidad[/h4]
+
+P: ¿Quién puede ver mi contenido?
+
+R: Por defecto CUALQUIER PERSONA en Internet, A MENOS que usted lo restrinja. El nombre del proyecto le permite elegir el nivel de privacidad que desea. El contenido restringido NO será visible para las "redes de espionaje" y los anunciantes. Estará protegido contra las escuchas de personas ajenas a la empresa, en la medida de nuestras posibilidades. Los administradores de los hubs con suficientes habilidades y paciencia PUEDEN ser capaces de escuchar a escondidas algunas comunicaciones privadas, pero deben hacer un esfuerzo para hacerlo. Los modos de privacidad existen dentro de $Projectname que son incluso resistentes a las escuchas por parte de administradores de hubs cualificados y decididos.
+
+P: ¿Se puede censurar mi contenido?
+
+R: $Nombre del proyecto (la red) NO PUEDE censurar su contenido. Los administradores de servidores y hubs están sujetos a las leyes locales y PUEDEN eliminar contenido objetable de su sitio o hub. Cualquiera PUEDE convertirse en administrador del hub, incluyéndote a ti; y por lo tanto publicar contenido que de otra manera podría ser censurado. Usted aún PUEDE estar sujeto a las leyes locales.
+
+
+[h5]Definiciones[/h5]
+
+**$$Nombre del proyecto**
+
+También conocido como "la red", $Projectname es una colección de ordenadores/servidores individuales (aka **hubs**) que se conectan para formar una red cooperativa más grande.
+
+*Hub*
+
+Una computadora individual o servidor conectado a $Projectname. Estos son proporcionados por un administrador de **hub y pueden ser públicos o privados, de pago o gratuitos.
+
+El administrador del hub.
+
+El operador del sistema de un hub individual.
+
+[h5]Políticas[/h5]
+
+**Información Pública**
+
+Cualquier información o cualquier cosa publicada por usted dentro de $Projectname PUEDE ser pública o visible para cualquier persona en Internet. En la medida de lo posible, $Projectname le permite proteger el contenido y restringir quién puede verlo.
+
+La foto de tu perfil, el nombre de su canal y la ubicación (URL o dirección de red) de su canal son visibles para cualquiera en Internet y los controles de privacidad no afectarán la visualización de estos elementos.
+
+Usted PUEDE proporcionar adicionalmente otra información de perfil. Cualquier información que proporcione en su "perfil por defecto" o **perfil público** PUEDE ser transmitida a otros hubs en $Nombre del proyecto y además PUEDE ser mostrada en el directorio de canales. Puede restringir la visualización de esta información de perfil. Puede estar restringido sólo a los miembros de su hub, o sólo a conexiones (amigos), u otros grupos limitados de espectadores que desee. Si desea que su perfil sea restringido, debe establecer la configuración de privacidad apropiada, o simplemente NO proporcione información adicional.
+
+**Contenido**
+
+El contenido que usted proporciona (mensajes de estado, fotos, archivos, etc.) le pertenece a usted. Por defecto, el nombre del proyecto es publicar contenido de forma abierta y visible para cualquiera en Internet (PÚBLICO). Usted PUEDE controlar esto en la configuración de su canal y restringir los permisos predeterminados o PUEDE restringir la visibilidad de cualquier elemento publicado por separado (PRIVADO).
+Los desarrolladores de $Projectbane se asegurarán de que el contenido restringido SÓLO sea visible para aquellos en la lista de restricciones, en la medida de sus posibilidades.
+
+El contenido (especialmente los mensajes de estado) que comparte con otras redes o que has hecho visible para cualquiera en Internet (PÚBLICO) no se puede recuperar fácilmente una vez que se ha publicado. PUEDE ser compartido con otras redes y estar disponible a través de RSS/Atom feeds. También puede ser sindicado en otros sitios de $Projectname. Puede aparecer en otras redes y sitios web y ser visible en búsquedas en Internet. Si no desea este comportamiento por defecto, por favor ajuste la configuración de su canal y restrinja quién puede ver su contenido.
+
+**Comentarios y mensajes en el Foro***
+
+Los comentarios a los mensajes creados por otros y los mensajes designados como mensajes del foro le pertenecen a usted como creador/autor, pero la distribución de estos mensajes no está bajo su control directo, y usted renuncia a ALGUNOS derechos sobre estos elementos. Estos mensajes/comentarios PUEDEN ser redistribuidos a otros, y PUEDEN ser visibles para cualquier persona en Internet. En el caso de los comentarios, el creador del "primer mensaje" en el hilo (conversación) al que está respondiendo controla la distribución de todos los comentarios y respuestas a ese mensaje. Ellos "poseen" y por lo tanto tienen ciertos derechos con respecto a toda la conversación (incluyendo todos los comentarios contenidos en ella). Todavía puede editar o eliminar el comentario, pero el propietario de la conversación también tiene derechos para editar, eliminar, redistribuir y realizar copias de seguridad/restaurar todo o parte del contenido de la conversación.
+
+**Información Privada**
+
+Los desarrolladores de $Projectnamese asegurarán de que cualquier contenido que usted proporcione que esté designado como PRIVADO estará protegido contra las escuchas clandestinas, en la medida de sus posibilidades. El contenido de los canales privados PUEDE ser visto en la base de datos de cada administrador de hubs involucrado, pero los mensajes privados son ocultados en la base de datos. Esto último significa que es muy difícil, pero NO imposible, que este contenido sea visto por un administrador de hubs. El contenido de los canales privados y los mensajes privados también se eliminan de las notificaciones por correo electrónico. La encriptación de extremo a extremo se proporciona como una característica opcional y esto NO PUEDE ser visto, ni siquiera por un administrador determinado.
+
+[h5]Privacidad de la identidad[/h5]
+
+La privacidad para su identidad es otro aspecto. Debido a que tiene una identidad descentralizada en $Projectname, su privacidad se extiende más allá de su centro de operaciones. Si quiere tener el control total de tu privacidad y seguridad, deberías tener tu propio hub en un servidor dedicado. Para muchas personas, esto es complicado y puede estirar sus habilidades técnicas. Así que vamos a enumerar algunas precauciones que puede tomar para asegurar su privacidad tanto como sea posible.
+
+Una identidad descentralizada tiene muchas ventajas y le ofrece muchas características interesantes, pero debe tener en cuenta que su identidad es conocida por otros hubs de la red $Projectname. Una de esas ventajas es que otros canales pueden servirte contenido personalizado y permitirte ver cosas privadas (como fotos privadas que otros desean compartir contigo). Por eso esos canales necesitan saber quién eres. Pero entendemos que a veces esos otros canales saben más de ti de lo que deseas. Por ejemplo el plug-in Visage que puede decirle al propietario de un canal la última vez que visites su perfil. Usted puede fácilmente OPT-OUT de este bajo nivel y, pensamos, seguimiento inofensivo.
+
+Puede habilitar [No rastrear (DNT)](http://donottrack.us/) en su navegador web. Respetamos esta nueva propuesta de política de privacidad. Todos los navegadores modernos soportan DNT. Lo encontrarás en la configuración de privacidad de tus navegadores o bien puedes consultar el manual del navegador. Esto no afectará a la funcionalidad de $Projectname. Este ajuste es probablemente suficiente para la mayoría de las personas.
+
+Puede [desactivar la publicación](configuración) de su canal en nuestro directorio de canales. Si quieres que la gente encuentre tu canal, debes darles la dirección de tu canal directamente a ellos. Creemos que esto es una buena indicación de que prefieres privacidad extra y habilitar automáticamente "No rastrear" si este es el caso.
+
+Puedes tener un hub bloqueado. Esto significa que todos los canales y contenidos de ese hub no son públicos y no son visibles para el mundo exterior. Esto es algo que sólo el administrador del hub puede hacer. También respetamos esto y activamos automáticamente "No rastrear" si está configurado.
+
+[h5]Censura[/h5]
+
+$Projectname es una red global que incluye todas las religiones y culturas. Esto no implica que todos los miembros de la red se sientan de la misma manera que usted en cuestiones polémicas, y es posible que algunas personas se opongan rotundamente al contenido que usted publica. En general, si desea publicar algo que sabe que puede no ser universalmente aceptable, el mejor enfoque es restringir la audiencia utilizando los controles de privacidad a un pequeño círculo de amigos.
+
+El nombre del proyecto como proveedor de red no puede censurar el contenido. Sin embargo, los administradores de los hubs PUEDEN censurar cualquier contenido que aparezca en su hub para cumplir con las leyes locales o incluso con juicios personales. Su decisión es definitiva. Si tienes problemas con algún administrador de hub, puedes mover tu cuenta y anuncios a otro sitio que esté más en línea con tus expectativas.
+$Projectname RECOMIENDA que los administradores de hubs proporcionen un período de gracia de 1-2 días entre el aviso al titular de la cuenta del contenido que necesita ser eliminado y la eliminación o desactivación física de la cuenta. Esto le dará al propietario del contenido la oportunidad de exportar los metadatos de su canal e importarlos a otro sitio. En raras ocasiones el contenido puede ser de tal naturaleza que justifique la terminación inmediata de la cuenta. Esta es una decisión de hub, no $Projectname.
+
+Si usted típica y regularmente publica contenido de naturaleza adulta u ofensiva, se le recomienda encarecidamente que marque su cuenta "NSFW" (No es seguro para el trabajo). Esto evitará que se muestre la foto de tu perfil en el directorio, excepto a los espectadores que hayan optado por desactivar el "modo seguro". Si los administradores del directorio consideran que la foto de tu perfil es adulta u ofensiva, el administrador del directorio PUEDE marcar tu foto de perfil como NSFW. Actualmente no existe ningún mecanismo oficial para impugnar o revertir esta decisión, razón por la cual DEBERÍA usted marcar su propia cuenta NSFW si es probable que sea inapropiada para el público en general.
+
+[h3]Créditos[/h3]
+
+Gracias a todos los que han ayudado y contribuido al proyecto y a sus predecesores a lo largo de los años.
+Es posible que hayamos fallado en su nombre, pero esto no es intencional. También agradecemos a la comunidad y a sus miembros por hacer aportes valiosos y sin los cuales todo este esfuerzo carecería de sentido.
+
+También vale la pena reconocer las contribuciones y soluciones a los problemas que surgieron a partir de discusiones entre miembros y desarrolladores de otros proyectos relacionados y en competencia; incluso si hemos tenido nuestros desacuerdos ocasionales.
+
+[list]
+[li]Mike Macgirvin[/li]
+[li]Fabio Comuni[/li]
+[li]Simon L'nu[/li]
+[li]marijus[/li]
+[li]Tobias Diekershoff[/li]
+[li]fabrixxm[/li]
+[li]tommy tomson[/li]
+[li]Simon[/li]
+[li]zottel[/li]
+[li]Christian Vogeley[/li]
+[li]Jeroen van Riet Paap (jeroenpraat)[/li]
+[li]Michael Vogel[/li]
+[li]erik[/li]
+[li]Zach Prezkuta[/li]
+[li]Paolo T[/li]
+[li]Michael Meer[/li]
+[li]Michael[/li]
+[li]Abinoam P. Marques Jr[/li]
+[li]Tobias Hößl[/li]
+[li]Alexander Kampmann[/li]
+[li]Olaf Conradi[/li]
+[li]Paolo Tacconi[/li]
+[li]tobiasd[/li]
+[li]Devlon Duthie[/li]
+[li]Zvi ben Yaakov (a.k.a rdc)[/li]
+[li]Alexandre Hannud Abdo[/li]
+[li]Olivier Migeot[/li]
+[li]Chris Case[/li]
+[li]Klaus Weidenbach[/li]
+[li]Michael Johnston[/li]
+[li]olivierm[/li]
+[li]Vasudev Kamath[/li]
+[li]pixelroot[/li]
+[li]Max Weller[/li]
+[li]duthied[/li]
+[li]Martin Schmitt[/li]
+[li]Sebastian Egbers[/li]
+[li]Erkan Yilmaz[/li]
+[li]sasiflo[/li]
+[li]Stefan Parviainen[/li]
+[li]Haakon Meland Eriksen[/li]
+[li]Oliver Hartmann (23n)[/li]
+[li]Erik Lundin[/li]
+[li]habeascodice[/li]
+[li]sirius[/li]
+[li]Charles[/li]
+[li]Tony Baldwin[/li]
+[li]Hauke Zuehl[/li]
+[li]Keith Fernie[/li]
+[li]Anne Walk[/li]
+[li]toclimb[/li]
+[li]Daniel Frank[/li]
+[li]Matthew Exon[/li]
+[li]Michal Supler[/li]
+[li]Tobias Luther[/li]
+[li]U-SOUND\mike[/li]
+[li]mrjive[/li]
+[li]nostupidzone[/li]
+[li]tonnerkiller[/li]
+[li]Antoine G[/li]
+[li]Christian Drechsler[/li]
+[li]Ludovic Grossard[/li]
+[li]RedmatrixCanada[/li]
+[li]Stanislav Lechev [0xAF][/li]
+[li]aweiher[/li]
+[li]bufalo1973[/li]
+[li]dsp1986[/li]
+[li]felixgilles[/li]
+[li]ike[/li]
+[li]maase2[/li]
+[li]mycocham[/li]
+[li]ndurchx[/li]
+[li]pafcu[/li]
+[li]Simó Albert i Beltran[/li]
+[li]Manuel Reva[/li]
+[li]Manuel Jiménez Friaza[/li]
+[li]Gustav Wall aka "neue medienordnung plus"[/li]
+[/list]
diff --git a/doc/es-es/gdpr1.md b/doc/es-es/gdpr1.md
new file mode 100644
index 000000000..67fcf354e
--- /dev/null
+++ b/doc/es-es/gdpr1.md
@@ -0,0 +1,84 @@
+
+Aviso sobre privacidad. Mayo, 2018
+
+Cómo será usada su información
+=================================
+
+La información que usted proporcione a este sitio web puede ser almacenada y usada con el fin de proveer servicios para usted.
+
+Necesitamos una dirección de correo electrónico para identificar al titular de la cuenta. Esta no será compartido con ningún otro sitio web o servicio. Será usada para enviarle notificaciones acerca de su cuenta y para llevar a cabo tareas administrativas como realizar un cambio de contraseña. Tiene la opción de inhabilitar todas las notificaciones por correo electrónico en su configuración personal.
+
+Communication channels created on this website require a name and a photo or avatar. A
+default avatar will be chosen if you do not supply one. The name, avatar, and a link to
+the channel webpage will be shared with other servers and services in order to refer to
+this identity. The name does not need to be your real name and the photo or avatar does
+not need to resemble you.
+
+All other information you supply to this website is optional.
+
+As a social communication and cloud storage service, you will usually be using this website
+to share information with others. We provide a range of privacy options to allow you to
+restrict this sharing to only those you choose.
+
+
+Procesamiento de su información
+==============================
+
+Nuestro tratamiento de su información se limitia a almacenarla para su uso. Our processing of your information is limited to storing it for you to use. PODRÍAMOS mantener registros de actividad para ayudar a diagnosticar problemas de software y mantener la seguridad del sistema contra intrusión. Estos registros se borran rutinariamente al cabo de unos días.
+
+Nosotros PODEMOS (si usted ha proporcionado este permiso) tratar de sugerir amistades o conexiones basadas en en el análisis de la información disponible públicamente sobre sus conexiones. Este es actualmente el "procesamiento" más avanzado de datos realizado en este sitio web. Usted puede restringir el acceso a esta información si no lo desea.
+
+Si se nos proporciona, PODRÍAMOS usar su género para formular mensajes de texto en su idioma nativo, por ejemplo "Bob comentó en SU post."
+
+En todos los demás casos, sus datos se almacenan bajo su propia política de privacidad y de la mejor manera posible, según nuestra habilidad, sólo se comparte con aquellos con quienes usted ha elegido compartirla.
+
+No compartimos su información privada con terceros ni analizamos su comportamiento o características personales. No tenemos publicidad ni relaciones comerciales con anunciantes.
+
+PODRÍAMOS ser solicitados u obligados a divulgar información proporcionada por usted en respuesta a preguntas legítimas en procedimientos penales y judiciales. En la medida de lo posible, le notificaremos si esto sucede.
+
+
+Acceso a su información
+==========================
+
+Algunas comunicaciones se comparten con otros sitios web. Aquellos que usan el mismo software normalmente tienen políticas de privacidad similares.
+
+Es posible que se le muestren vídeos incrustados y se le proporcionen enlaces para visitar otros sitios web como parte de sus actividades diarias utilizando este sitio web. Esto PUEDE exponerle a la monitorización por parte de servicios externos, tales como como (pero no limitado a) Facebook, Twitter y Google. Cada operador de sitio web puede configurar si se permite o no el contenido incrustado.
+
+El acceso a sus datos personales y archivos almacenados está bajo su control.
+
+Nuestro almacenamiento de sus datos se proporciona bajo su consentimiento implícito a través de su uso continuado de el servicio. Usted puede retirar este consentimiento en cualquier momento y, en caso de eliminación de la cuenta, eliminaremos todos los datos que le pertenecen. El proceso de eliminación puede tomar varios días ya que también hacemos de buena fe un esfuerzo para eliminarlo de cualquier sitio web conectado a Internet al que se le haya proporcionado una copia.
+
+Todos los datos y archivos almacenados para un canal de comunicación están disponibles para que usted pueda para guardarlos o transferirlos a otro sitio web compatible.
+
+
+
+Sus derechos
+===========
+
+Bajo el Reglamento General de Protección de Datos (GDPR) y la Ley de Protección de Datos de 2018 (DPA) usted tiene una serie de derechos con respecto a sus datos personales.
+Usted tiene derecho a solicitarnos el acceso, rectificación o cancelación de sus datos personales, el derecho a restringir el tratamiento, a oponerse al tratamiento así como, en determinadas circunstancias, el derecho a la portabilidad de datos.
+
+Si usted ha dado su consentimiento para el tratamiento de sus datos, tiene derecho (en determinados casos) a retirar ese consentimiento en cualquier momento, siempre que no afecte a la legalidad, a dicho procesamiento antes de que su consentimiento fuera retirado.
+
+Usted tiene derecho a presentar una queja ante la Oficina del Comisionado de Información si cree que no hemos cumplido con los requisitos del GDPR o DPA 18 con respecto a sus datos personales.
+
+Identidad y datos de contacto del responsable del tratamiento y del responsable de la protección de datos
+
+[NOMBRE DE LA COMPAÑÍA]
+es el controlador
+[y procesador]
+de datos a efectos de la DPA 18 y el GDPR. 3
+
+Si tiene alguna duda sobre cómo se procesan sus datos, puede ponerse en contacto con nosotros:
+
+[
+[NOMBRE]
+Oferta de protección de datos en
+[DIRECCIÓN DE CORREO ELECTRÓNICO]
+]
+[NOMBRE][CARGO]
+en
+[DIRECCIÓN DE CORREO ELECTRÓNICO]
+o puede escribir a las siguientes direcciones
+personas que utilicen la dirección de
+[]
diff --git a/doc/es-es/git_for_non_developers.bb b/doc/es-es/git_for_non_developers.bb
new file mode 100644
index 000000000..7a3ab980b
--- /dev/null
+++ b/doc/es-es/git_for_non_developers.bb
@@ -0,0 +1,78 @@
+[b]Git para no desarrolladores[/b]
+
+Así que está manejando una traducción, o está contribuyendo a un tema, y cada vez que hace un pull request tiene que hablar con uno de los desarrolladores antes de que sus cambios puedan ser fusionados?
+
+Lo más probable es que no haya encontrado una forma rápida de explicar cómo mantener las cosas sincronizadas en su lado. Es realmente muy fácil.
+
+Después de crear un fork del repositorio (sólo tiene que hacer clic en "fork" en github), necesita clonar su propia copia.
+
+Por ejemplo, asumiremos que está trabajando en un tema llamado redexample (que no existe).
+
+[code]git clone https://github.com/username/red.git[/code]
+
+Así que está manejando una traducción, o está contribuyendo a un tema, y cada vez que hace un pull request tiene que hablar con uno de los desarrolladores antes de que sus cambios puedan ser fusionados?
+
+Lo más probable es que no haya encontrado una forma rápida de explicar cómo mantener las cosas sincronizadas en su lado. Es realmente muy fácil.
+
+Después de crear un fork del repositorio (sólo tiene que hacer clic en "fork" en github), necesita clonar su propia copia.
+
+Por ejemplo, asumiremos que está trabajando en un tema llamado redexample (que no existe).
+
+Una vez que lo haya hecho, cd en el directorio, y añadir un upstream.
+
+[code]
+cd red
+git remote add upstream https://github.com/redmatrix/hubzilla
+[/code]
+
+A partir de ahora, puede realizar cambios en el upstream con el comando
+[code]git fetch upstream[/code]
+
+Antes de que sus cambios puedan fusionarse automáticamente, a menudo necesitará fusionar los cambios anteriores.
+
+[code]
+git merge upstream/master
+[/code]
+
+Siempre debe fusionar upstream antes de subir cualquier cambio, y [i]debe[/i] fusionar upstream con cualquier pull request para que se fusionen automáticamente.
+
+El 99% de las veces, todo irá bien. La única vez que no lo hará es si alguien más ha estado editando los mismos ficheros que usted y, a menudo, sólo si ha estado editando las mismas líneas de los mismos archivos. Si eso sucede, ese sería un buen momento para solicitar ayuda hasta que se acostumbre a manejar sus propios conflictos de fusión.
+
+Entonces sólo necesitas añadir tus cambios [code]git añadir vista/tema/redexample/[/code]
+
+Esto agregará todos los archivos en la vista/tema/redexample y cualquier subdirectorio. Si sus archivos particulares se mezclan a través del código, usted debe agregar uno a la vez. Trata de no hacer git add -a, ya que esto lo agregará todo, incluyendo archivos temporales (mayormente, pero no siempre atrapamos a aquellos con un.gitignore) y cualquier cambio local que tenga, pero que no intente confirmar.
+
+Una vez que haya agregado todos los archivos que ha cambiado, necesita confirmarlos. [code]git commit[/code]
+
+Esto abrirá un editor donde podrá describir los cambios que ha realizado. Guarde este archivo y salga del editor.
+
+Finalmente, suba los cambios en su propio git
+[code]git push[/code]
+
+Y eso es todo, su repo está al día!
+
+Todo lo que necesita hacer ahora es crear la petición pull. Hay dos maneras de hacerlo.
+
+La forma más fácil, si está utilizando Github, es simplemente hacer clic en el botón verde en la parte superior de su propia copia del repositorio, introducir una descripción de los cambios, y hacer clic en `crear pull request'. El repositorio principal, los temas y los complementos tienen su rama principal en Github, por lo que este método se puede utilizar la mayor parte del tiempo.
+
+La mayoría de la gente puede parar aquí.
+
+Algunos proyectos en la ecosfera extendida de RedMatrix no tienen presencia en Github, para un pull request, los pasos son un poco diferentes: usted tendrá que crear su pull request manualmente. Afortunadamente, esto no es
+mucho más difícil.
+
+[code]git request-pull -p <start> <url>[/code]
+
+Start es el nombre de un commit por el que empezar. Esto debe existir en el upstream. Normalmente, sólo querr'a la rama master.
+
+URL es la URL de[i]su[/i] repo.
+
+También se puede especificar <end>. Este valor predeterminado es HEAD.
+
+Ejemplo:
+[código]
+git request-pull master https://ejemplo.com/proyecto
+[/código]
+
+Y simplemente envíe la salida al mantenedor del proyecto.
+
+#include doc/macros/main_footer.bb;
diff --git a/doc/es-es/main.bb b/doc/es-es/main.bb
new file mode 100644
index 000000000..00d2e47bb
--- /dev/null
+++ b/doc/es-es/main.bb
@@ -0,0 +1,12 @@
+
+[zrl=[baseurl]/help/about][b]¿Qué es $Projectname?[/b][/zrl]
+$Projectname est un software de publicación y comunicación descentralizadas que le permite tener el control de sus necesidades y datos. Es ustedm y solo usted, quien decide a quién permite ver sus publicaciones.
+
+
+[zrl=[baseurl]/help/features][b]Funcionaliades de $Projectname[/b][/zrl]
+$Projectname es una red global distribuida que es flexible, pero puede crecer en potencia desde in pequeño sitio personal hasta albergar una comunidad de numerosas personas.
+
+$Projectname funciona en tanto que red global distribuida. Es flexible y puede crecer en potencia. Se puede usar para los miembros de una familia, para una comunidad en línea, para foros, blogs y páginas web.
+
+[zrl=[baseurl]/help/what_is_zot][b]¿Qué es Zot?[/b][/zrl]
+Zot es un protocolo de comunicación diseñado especialmente para $Projectname. En tanto que miembro, usted no está ligado a un sitio web único o a un hub, gracias a la identidad nómada. Puede migrar fácilmente a otros servidores y guardar sus contactos. Puede también clonar su canal y éste se encontrará en distintos servidores. En el caso de que un servidor deje de estar operativo definitivamente, usted perderá sus datos. Además, si está en $Projectname, no tendrá necesidad de identificarse varias veces, incluso para acceder a otros sitios $Projectname. De modo que Zot es el corazón de $Projectname.
diff --git a/doc/es-es/toc.html b/doc/es-es/toc.html
new file mode 100644
index 000000000..152d9de25
--- /dev/null
+++ b/doc/es-es/toc.html
@@ -0,0 +1,74 @@
+<div class="" id="accordion">
+ <div class="">
+ <div class="">
+ <h3 class="panel-title">
+ Tutoriales
+ </h3>
+ </div>
+ <div id="tutorials" class="doco-section">
+ <div class="flex-column">
+ <a class="nav-link" href="/help/tutorials/personal_channel">Canal personal</a>
+ </div>
+ </div>
+ </div>
+ <div class="">
+ <div class="">
+ <h3 class="panel-title">
+ Miembros
+ </h3>
+ </div>
+ <div id="members" class="doco-section">
+ <div class="flex-column">
+ <a class="nav-link" href="/help/member/member_guide">Guía</a>
+ <a class="nav-link" href="/help/member/bbcode">Referencia de BBcode</a>
+ <a class="nav-link" href="/help/feature/additional/overview">Funcionalidades adicionales</a>
+ <a class="nav-link" href="/help/bugs">Informar de bugs</a>
+ <a class="nav-link" href="/help/member/member_faq">FAQ</a>
+ </div>
+ </div>
+ </div>
+ <div class="panel">
+ <div class="">
+ <h3 class="panel-title">
+ Administradores
+ </h3>
+ </div>
+ <div id="administrators" class="doco-section">
+ <div class="flex-column">
+ <a class="nav-link" href="/help/admin/administrator_guide">Guía</a>
+ <a class="nav-link" href="/help/admin/hub_snapshots">Instantáneas de hubs</a>
+ <a class="nav-link" href="/help/database">Tablas de la base de datos</a>
+ </div>
+ </div>
+ </div>
+ <div class="panel">
+ <div class="">
+ <h3 class="panel-title">
+ Desarrolladores
+ </h3>
+ </div>
+ <div id="developers" class="doco-section">
+ <div class="flex-column">
+ <a class="nav-link" href="/help/developer/developer_guide">Guía</a>
+ <a class="nav-link" href="/help/developer/covenant">Código de conducta</a>
+ <a class="nav-link" href="/help/developer/zot_protocol">Protocolo Zot</a>
+ <a class="nav-link" href="/help/developer/api_zot">API de Zot</a>
+ <a class="nav-link" href="/help/hooklist">Hooks</a>
+ </div>
+ </div>
+ </div>
+ <div class="panel">
+ <div class="">
+ <h3 class="panel-title">
+ A propósito de
+ </h3>
+ </div>
+ <div id="about" class="doco-section">
+ <div class="flex-column">
+ <a class="nav-link" href="/help/about/about">A propósito de</a>
+ <a class="nav-link" href="/help/about/project">Proyecto</a>
+ <a class="nav-link" href="/help/about/about_hub">Acerca de este hub</a>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/include/connections.php b/include/connections.php
index 32baa94bd..5a9e31950 100644
--- a/include/connections.php
+++ b/include/connections.php
@@ -374,14 +374,19 @@ function contact_remove($channel_id, $abook_id) {
return false;
- $r = q("select id from item where (owner_xchan = '%s' or author_xchan = '%s') and uid = %d",
+ $r = q("select id from item where (owner_xchan = '%s' or author_xchan = '%s') and uid = %d and item_retained = 0 and item_starred = 0",
dbesc($abook['abook_xchan']),
dbesc($abook['abook_xchan']),
intval($channel_id)
);
if($r) {
+ $r = fetch_post_tags($r,true);
+
foreach($r as $rr) {
- drop_item($rr['id'],false);
+ $terms = get_terms_oftype($item['term'],TERM_FILE);
+ if(! $terms) {
+ drop_item($rr['id'],false);
+ }
}
}
diff --git a/include/conversation.php b/include/conversation.php
index 4a1cdc7da..4997bc2b7 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -509,6 +509,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
. ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
. ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '')
. ((x($_GET,'uri')) ? '&uri=' . $_GET['uri'] : '')
+ . ((x($_GET,'pf')) ? '&pf=' . $_GET['pf'] : '')
. "'; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
}
}
@@ -690,8 +691,10 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
'delete' => t('Delete'),
);
- $star = false;
- $isstarred = "unstarred fa-star-o";
+ $star = array(
+ 'toggle' => t("Toggle Star Status"),
+ 'isstarred' => ((intval($item['item_starred'])) ? true : false),
+ );
$lock = (($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
? t('Private Message')
@@ -773,8 +776,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
'owner_photo' => $owner_photo,
'plink' => get_plink($item,false),
'edpost' => false,
- 'isstarred' => $isstarred,
- 'star' => $star,
+ 'star' => ((feature_enabled(local_channel(),'star_posts')) ? $star : ''),
'drop' => $drop,
'vote' => $likebuttons,
'like' => '',
@@ -1162,7 +1164,7 @@ function builtin_activity_puller($item, &$conv_responses) {
if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
$name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown'));
$url = (($item['author_xchan'] && $item['author']['xchan_photo_s'])
- ? '<a class="dropdown-item" href="' . chanlink_hash($item['author_xchan']) . '">' . '<img class="menu-img-1" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" />' . $name . '</a>'
+ ? '<a class="dropdown-item" href="' . chanlink_hash($item['author_xchan']) . '">' . '<img class="menu-img-1" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" /> ' . $name . '</a>'
: '<a class="dropdown-item" href="#" class="disabled">' . $name . '</a>'
);
diff --git a/include/features.php b/include/features.php
index 616e3f6c5..bcdea73e0 100644
--- a/include/features.php
+++ b/include/features.php
@@ -386,21 +386,30 @@ function get_features($filtered = true, $level = (-1)) {
],
[
- 'personal_tab',
- t('Network Personal Tab'),
- t('Enable tab to display only Network posts that you\'ve interacted on'),
+ 'order_tab',
+ t('Alternate Stream Order'),
+ t('Ability to order the stream by last post date, last comment date or unthreaded activities'),
false,
- get_config('feature_lock','personal_tab'),
- feature_level('personal_tab',1),
+ get_config('feature_lock','order_tab'),
+ feature_level('order_tab',2),
+ ],
+
+ [
+ 'forums_tab',
+ t('Forum Filter'),
+ t('Ability to display only posts of a specific forum'),
+ false,
+ get_config('feature_lock','forums_tab'),
+ feature_level('forums_tab',1),
],
[
- 'new_tab',
- t('Network New Tab'),
- t('Enable tab to display all new Network activity'),
+ 'personal_tab',
+ t('Personal Posts Filter'),
+ t('Ability to display only Network posts that you\'ve interacted on'),
false,
- get_config('feature_lock','new_tab'),
- feature_level('new_tab',2),
+ get_config('feature_lock','personal_tab'),
+ feature_level('personal_tab',1),
],
[
diff --git a/include/group.php b/include/group.php
index 8c95f6224..03ebf7ee5 100644
--- a/include/group.php
+++ b/include/group.php
@@ -284,7 +284,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
'text' => t('All Channels'),
'id' => 0,
'selected' => (($group_id == 0) ? 'group-selected' : ''),
- 'href' => $every . (($every === 'network') ? '?f=&gid=0' : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
+ 'href' => $every . (($every === 'network') ? '?f=&gid=0' : ''),
);
diff --git a/include/import.php b/include/import.php
index ae6a0ab6a..91a26b23b 100644
--- a/include/import.php
+++ b/include/import.php
@@ -1326,20 +1326,23 @@ function sync_files($channel, $files) {
);
if($exists) {
- if(! dbesc_array($p))
- continue;
$str = '';
foreach($p as $k => $v) {
+ $matches = false;
+ if(preg_match('/([^a-zA-Z0-9\-\_\.])/',$k,$matches)) {
+ continue;
+ }
+
if($str)
$str .= ",";
-
- $str .= " " . TQUOT . $k . TQUOT . " = '" . $v . "' ";
+
+ $str .= " " . TQUOT . $k . TQUOT . " = '" . (($k === 'content') ? dbescbin($v) : dbesc($v)) . "' ";
}
$r = dbq("update photo set " . $str . " where id = " . intval($exists[0]['id']) );
}
else {
- create_table_from_array('photo',$p);
+ create_table_from_array('photo',$p, [ 'content' ] );
}
}
}
diff --git a/include/nav.php b/include/nav.php
index c5ceb97c5..5642f438f 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -91,8 +91,10 @@ function nav($template = 'default') {
if(local_channel()) {
if(! $_SESSION['delegate']) {
- $nav['manage'] = array('manage', t('Channel Manager'), "", t('Manage Your Channels'),'manage_nav_btn');
+ $nav['manage'] = array('manage', t('Channel Manager'), "", t('Manage your channels'),'manage_nav_btn');
}
+ if(feature_enabled(local_channel(),'groups'))
+ $nav['group'] = array('group', t('Privacy Groups'),"", t('Manage your privacy groups'),'group_nav_btn');
$nav['settings'] = array('settings', t('Settings'),"", t('Account/Channel Settings'),'settings_nav_btn');
@@ -168,21 +170,19 @@ function nav($template = 'default') {
$nav['help'] = [$help_url, t('Help'), "", t('Help and documentation'), 'help_nav_btn', $context_help, $enable_context_help];
}
- $nav['search'] = ['search', t('Search'), "", t('Search site @name, !forum, #tag, ?docs, content')];
-
+ switch(App::$module) {
+ case 'network':
+ $search_form_action = 'network';
+ break;
+ case 'channel':
+ $search_form_action = 'channel';
+ break;
+ default:
+ $search_form_action = 'search';
+ }
- /**
- *
- * The following nav links are only show to logged in users
- *
- */
- if(local_channel()) {
- if(! $_SESSION['delegate']) {
- $nav['manage'] = array('manage', t('Channel Manager'), "", t('Manage Your Channels'),'manage_nav_btn');
- }
- $nav['settings'] = array('settings', t('Settings'),"", t('Account/Channel Settings'),'settings_nav_btn');
- }
+ $nav['search'] = ['search', t('Search'), "", t('Search site @name, !forum, #tag, ?docs, content'), $search_form_action];
/**
* Admin page
diff --git a/include/network.php b/include/network.php
index 4b2d2f93f..91a39a6cb 100644
--- a/include/network.php
+++ b/include/network.php
@@ -1740,7 +1740,7 @@ function deliverable_singleton($channel_id,$xchan) {
function get_repository_version($branch = 'master') {
- $path = "https://raw.githubusercontent.com/redmatrix/hubzilla/$branch/boot.php";
+ $path = "https://framagit.org/hubzilla/core/raw/$branch/boot.php";
$x = z_fetch_url($path);
if($x['success']) {
diff --git a/include/plugin.php b/include/plugin.php
index 28d27619f..734c20d79 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -559,7 +559,7 @@ function get_widget_info($widget){
$checkpaths = [
"Zotlabs/SiteWidget/$ucwidget.php",
- "Zotlibs/Widget/$ucwidget.php",
+ "Zotlabs/Widget/$ucwidget.php",
"addon/$ucwidget/$ucwidget.php",
"addon/$widget.php"
];
diff --git a/include/text.php b/include/text.php
index 34063cdd7..a8c28d7bd 100644
--- a/include/text.php
+++ b/include/text.php
@@ -3186,21 +3186,33 @@ function array2XML($obj, $array) {
*
* @param string $table
* @param array $arr
+ * @param array $binary_fields - fields which will be cleansed with dbescbin rather than dbesc; this is critical for postgres
* @return boolean|PDOStatement
*/
-function create_table_from_array($table, $arr) {
+function create_table_from_array($table, $arr, $binary_fields = []) {
if(! ($arr && $table))
return false;
- if(dbesc_array($arr)) {
- $r = dbq("INSERT INTO " . TQUOT . $table . TQUOT . " (" . TQUOT
- . implode(TQUOT . ', ' . TQUOT, array_keys($arr))
- . TQUOT . ") VALUES ('"
- . implode("', '", array_values($arr))
- . "')"
- );
+ $clean = [];
+ foreach($arr as $k => $v) {
+ $matches = false;
+ if(preg_match('/([^a-zA-Z0-9\-\_\.])/',$k,$matches)) {
+ return false;
+ }
+ if(in_array($k,$binary_fields)) {
+ $clean[$k] = dbescbin($v);
+ }
+ else {
+ $clean[$k] = dbesc($v);
+ }
}
+ $r = dbq("INSERT INTO " . TQUOT . $table . TQUOT . " (" . TQUOT
+ . implode(TQUOT . ', ' . TQUOT, array_keys($clean))
+ . TQUOT . ") VALUES ('"
+ . implode("', '", array_values($clean))
+ . "')"
+ );
return $r;
}
@@ -3333,4 +3345,54 @@ function unique_multidim_array($array, $key) {
$i++;
}
return $temp_array;
-}
+}
+
+function get_forum_channels($uid) {
+
+ if(! $uid)
+ return;
+
+ $xf = false;
+
+ $x1 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'send_stream' and v = '0'",
+ intval($uid)
+ );
+ 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($uid)
+ );
+
+ if($x2) {
+ $xf = ids_to_querystr($x2,'xchan',true);
+
+ // private forums
+ $x3 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'post_wall' and v = '1' and xchan in (" . $xc . ") and not xchan in (" . $xf . ") ",
+ intval(local_channel())
+ );
+ if($x3) {
+ $xf = ids_to_querystr(array_merge($x2,$x3),'xchan',true);
+ }
+ }
+ }
+
+ $sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
+
+ $r = 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 and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name",
+ intval($uid)
+ );
+
+ for($x = 0; $x < count($r); $x ++) {
+ if($x3) {
+ foreach($x3 as $xx) {
+ if($r[$x]['xchan_hash'] == $xx['xchan']) {
+ $r[$x]['private_forum'] = 1;
+ }
+ }
+ }
+ }
+
+ return $r;
+
+}
diff --git a/install/INSTALL.txt b/install/INSTALL.txt
index 88269f032..c39c8ad8b 100644
--- a/install/INSTALL.txt
+++ b/install/INSTALL.txt
@@ -16,14 +16,14 @@ be able to support Hubzilla. Many will - but please review the requirements
and confirm these with your hosting provider prior to installation. (And
preferably before entering into a long-term contract.)
-If you encounter installation issues, please let us know via the Github issue
-tracker where you downloaded the software. Please be as clear as
-you can about your operating environment and provide as much detail as possible
-about any error messages you may see, so that we can prevent it from happening
-in the future. Due to the large variety of operating systems and PHP platforms
-in existence we may have only limited ability to debug your PHP installation
-or acquire any missing modules - but we will do our best to solve any general
-code issues.
+If you encounter installation issues, please let us know via the issue
+tracker at https://framagit.org/hubzilla where you downloaded the software.
+Please be as clear as you can about your operating environment and provide as
+much detail as possible about any error messages you may see, so that we can
+prevent it from happening in the future. Due to the large variety of operating
+systems and PHP platforms in existence we may have only limited ability to
+debug your PHP installation or acquire any missing modules - but we will do
+our best to solve any general code issues.
@@ -113,7 +113,7 @@ web server platforms.
software much easier to update. The Linux command to clone the repository
into a directory "mywebsite" would be
- git clone https://github.com/redmatrix/hubzilla.git mywebsite
+ git clone https://framagit.org/hubzilla/core.git mywebsite
- and then you can pick up the latest changes at any time with
@@ -144,7 +144,7 @@ web server platforms.
a nickname of 'hzaddons'. You can pull in other hubzilla addon repositories by
giving them different nicknames.
- util/add_addon_repo https://github.com/redmatrix/hubzilla-addons.git hzaddons
+ util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons
- For keeping the addon tree updated, you should be on your top level website
directory and issue an update command for that repository.
diff --git a/view/css/default.css b/view/css/default.css
index fc6da54f9..765a197d9 100644
--- a/view/css/default.css
+++ b/view/css/default.css
@@ -1,11 +1,3 @@
-header #banner {
- position: fixed;
- top: 0px;
- width: 33%;
- margin-left: 33%;
- margin-right: 33%;
-}
-
main {
display: table;
table-layout: fixed;
diff --git a/view/fr/hmessages.po b/view/fr/hmessages.po
index a830d06ef..c5263c2df 100644
--- a/view/fr/hmessages.po
+++ b/view/fr/hmessages.po
@@ -15,7 +15,7 @@ msgstr ""
"Project-Id-Version: Redmatrix\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-23 11:34+0200\n"
-"PO-Revision-Date: 2018-05-06 07:46+0000\n"
+"PO-Revision-Date: 2018-05-26 07:06+0000\n"
"Last-Translator: Philip Wittamore <philip@wittamore.com>\n"
"Language-Team: French (http://www.transifex.com/Friendica/red-matrix/language/fr/)\n"
"MIME-Version: 1.0\n"
@@ -6943,7 +6943,7 @@ msgstr "À propos&nbsp;:"
#: ../../include/conversation.php:1052 ../../include/channel.php:1376
#: ../../include/connections.php:110
msgid "Connect"
-msgstr "Ajouter/Suivre"
+msgstr "Lier"
#: ../../Zotlabs/Module/Directory.php:339
msgid "Public Forum:"
@@ -12750,7 +12750,7 @@ msgstr "Saisir nom ou centre d'intérêt"
#: ../../include/contact_widgets.php:21
msgid "Connect/Follow"
-msgstr "Ajouter/Suivre"
+msgstr "Lier et suivre"
#: ../../include/contact_widgets.php:22
msgid "Examples: Robert Morgenstein, Fishing"
diff --git a/view/fr/hstrings.php b/view/fr/hstrings.php
index f7fd25224..cdf233584 100644
--- a/view/fr/hstrings.php
+++ b/view/fr/hstrings.php
@@ -1485,7 +1485,7 @@ App::$strings["Location:"] = "Emplacement&nbsp;:";
App::$strings["Description:"] = "Description&nbsp;:";
App::$strings["Hometown:"] = "Ville natale&nbsp;:";
App::$strings["About:"] = "À propos&nbsp;:";
-App::$strings["Connect"] = "Ajouter/Suivre";
+App::$strings["Connect"] = "Lier";
App::$strings["Public Forum:"] = "Forum public&nbsp;:";
App::$strings["Keywords: "] = "Mots-clefs&nbsp;:";
App::$strings["Don't suggest"] = "Ne pas suggérer";
@@ -2868,7 +2868,7 @@ App::$strings["%d invitation available"] = array(
);
App::$strings["Find Channels"] = "Trouver des canaux";
App::$strings["Enter name or interest"] = "Saisir nom ou centre d'intérêt";
-App::$strings["Connect/Follow"] = "Ajouter/Suivre";
+App::$strings["Connect/Follow"] = "Lier et suivre";
App::$strings["Examples: Robert Morgenstein, Fishing"] = "Exemples: Guillaume Martin, Course à pieds";
App::$strings["Random Profile"] = "Un profil au hasard";
App::$strings["Invite Friends"] = "Inviter des amis";
diff --git a/view/js/main.js b/view/js/main.js
index 3e24e8177..45c412296 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -420,6 +420,14 @@ function notificationsUpdate(cached_data) {
// Put the object into storage
sessionStorage.setItem('notifications_cache', JSON.stringify(data));
+ var fnotifs = [];
+ if(data.forums) {
+ $.each(data.forums_sub, function() {
+ fnotifs.push(this);
+ });
+ handleNotificationsItems('forums', fnotifs);
+ }
+
if(data.invalid == 1) {
window.location.href=window.location.href;
}
@@ -451,7 +459,7 @@ function notificationsUpdate(cached_data) {
}
function handleNotifications(data) {
- if(data.network || data.home || data.intros || data.register || data.mail || data.all_events || data.notify || data.files || data.pubs) {
+ if(data.network || data.home || data.intros || data.register || data.mail || data.all_events || data.notify || data.files || data.pubs || data.forums) {
$('.notifications-btn').css('opacity', 1);
$('#no_notifications').hide();
}
@@ -495,13 +503,13 @@ function handleNotifications(data) {
}
function handleNotificationsItems(notifyType, data) {
- var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
+ var notifications_tpl = ((notifyType == 'forums') ? unescape($("#nav-notifications-forums-template[rel=template]").html()) : unescape($("#nav-notifications-template[rel=template]").html()));
var notify_menu = $("#nav-" + notifyType + "-menu");
notify_menu.html('');
$(data).each(function() {
- html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid,this.notify_id,this.thread_top);
+ html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid,this.notify_id,this.thread_top,this.unseen,this.private_forum);
notify_menu.append(html);
});
@@ -812,6 +820,15 @@ function updateInit() {
if (initialLoad && (sessionStorage.getItem('notifications_cache') !== null)) {
var cached_data = JSON.parse(sessionStorage.getItem('notifications_cache'));
notificationsUpdate(cached_data);
+
+ var fnotifs = [];
+ if(cached_data.forums) {
+ $.each(cached_data.forums_sub, function() {
+ fnotifs.push(this);
+ });
+ handleNotificationsItems('forums', fnotifs);
+ }
+
}
if(! src) {
@@ -1022,6 +1039,7 @@ function loadNotificationItems(notifyType) {
}
console.log('updating ' + notifyType + ' notifications...');
+
$.get(pingExCmd, function(data) {
if(data.invalid == 1) {
window.location.href=window.location.href;
diff --git a/view/pdl/mod_network.pdl b/view/pdl/mod_network.pdl
index 09fdba573..a4bdf0a9f 100644
--- a/view/pdl/mod_network.pdl
+++ b/view/pdl/mod_network.pdl
@@ -1,9 +1,8 @@
[region=aside]
-[widget=collections][/widget]
-[widget=forums][/widget]
-[widget=suggestions][/widget]
+[widget=activity_order][/widget]
+[widget=activity_filter][/widget]
[widget=savedsearch][/widget]
-[widget=filer][/widget]
+[widget=suggestions][/widget]
[widget=notes][/widget]
[/region]
diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css
index 4488dcddd..87c97f1f5 100644
--- a/view/theme/redbasic/css/style.css
+++ b/view/theme/redbasic/css/style.css
@@ -593,7 +593,8 @@ footer {
background-color: $comment_item_colour;
}
-#nav-notifications-template {
+#nav-notifications-template,
+#nav-notifications-forums-template {
display: none;
}
@@ -837,6 +838,11 @@ div.jGrowl div.jGrowl-notification {
white-space: nowrap;
}
+.notification.notification-forum {
+ font-size: 0.9rem;
+ color: $font_colour;
+}
+
#acl-search::-webkit-input-placeholder {
/* non-fontawesome fonts set a fallback for text parts of the placeholder*/
font-family: ForkAwesome, sans-serif, arial, freesans;
@@ -1271,9 +1277,8 @@ img.mail-conv-sender-photo {
}
.menu-img-1 {
- height: 1.5em;
- width: 1.5em;
- margin-right: 5px;
+ height: 1.28571429em;
+ width: 1.28571429em;
border-radius: $radius;
}
@@ -1799,3 +1804,11 @@ dl.bb-dl > dd > li {
.cover-photo-review {
margin-bottom: 10px;
}
+
+.hover-fx-hide {
+ opacity: 0;
+}
+
+.hover-fx-show:hover .hover-fx-hide {
+ opacity: 1;
+}
diff --git a/view/theme/redbasic/js/redbasic.js b/view/theme/redbasic/js/redbasic.js
index 41f5eb7ce..c905c92cb 100644
--- a/view/theme/redbasic/js/redbasic.js
+++ b/view/theme/redbasic/js/redbasic.js
@@ -89,6 +89,11 @@ $(document).ready(function() {
tagClass: 'badge badge-pill badge-warning text-dark'
});
+ $('a.disabled').click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
var doctitle = document.title;
function checkNotify() {
var notifyUpdateElem = document.getElementById('notify-update');
diff --git a/view/tpl/activity_filter_widget.tpl b/view/tpl/activity_filter_widget.tpl
new file mode 100644
index 000000000..7ff5a4f7e
--- /dev/null
+++ b/view/tpl/activity_filter_widget.tpl
@@ -0,0 +1,11 @@
+<div class="widget">
+ <h3 class="d-flex justify-content-between align-items-center">
+ {{$title}}
+ {{if $reset}}
+ <a href="{{$reset.url}}" class="text-muted" title="{{$reset.title}}">
+ <i class="fa fa-fw fa-{{$reset.icon}}"></i>
+ </a>
+ {{/if}}
+ </h3>
+ {{$content}}
+</div>
diff --git a/view/tpl/build_query.tpl b/view/tpl/build_query.tpl
index 1d938d395..754d5997c 100755
--- a/view/tpl/build_query.tpl
+++ b/view/tpl/build_query.tpl
@@ -30,6 +30,7 @@
var bParam_mid = "{{$mid}}";
var bParam_verb = "{{$verb}}";
var bParam_net = "{{$net}}";
+ var bParam_pf = "{{$pf}}";
function buildCmd() {
var udargs = ((page_load) ? "/load" : "");
@@ -60,6 +61,7 @@
if(bParam_verb != "") bCmd = bCmd + "&verb=" + bParam_verb;
if(bParam_net != "") bCmd = bCmd + "&net=" + bParam_net;
if(bParam_page != 1) bCmd = bCmd + "&page=" + bParam_page;
+ if(bParam_pf != 0) bCmd = bCmd + "&pf=" + bParam_pf;
return(bCmd);
}
diff --git a/view/tpl/common_pills.tpl b/view/tpl/common_pills.tpl
new file mode 100755
index 000000000..e2b018d26
--- /dev/null
+++ b/view/tpl/common_pills.tpl
@@ -0,0 +1,26 @@
+<ul class="nav nav-pills flex-column">
+ {{foreach $pills as $p}}
+ <li class="nav-item hover-fx-show"{{if $p.id}} id="{{$p.id}}"{{/if}}>
+ <a class="nav-link{{if $p.sel}} {{$p.sel}}{{/if}}" href="{{$p.url}}"{{if $p.title}} title="{{$p.title}}"{{/if}}{{if $p.sub}} onclick="{{if $p.sel}}closeOpen('{{$p.id}}_sub');{{else}}openClose('{{$p.id}}_sub');{{/if}} return false;"{{/if}}>
+ {{if $p.icon}}<i class="fa fa-fw fa-{{$p.icon}}"></i>{{/if}}
+ {{if $p.img}}<img class="menu-img-1" src="{{$p.img}}">{{/if}}
+ {{$p.label}}
+ {{if $p.sub}}<i class="fa fa-fw fa-caret-down hover-fx-hide"></i>{{/if}}
+ </a>
+ {{if $p.sub}}
+ <ul class="nav nav-pills flex-column ml-4" id="{{$p.id}}_sub"{{if !$p.sel}} style="display: none;"{{/if}}>
+ {{foreach $p.sub as $ps}}
+ <li class="nav-item"{{if $ps.id}} id="{{$ps.id}}"{{/if}}>
+ <a class="nav-link{{if $ps.sel}} {{$ps.sel}}{{/if}}" href="{{$ps.url}}"{{if $ps.title}} title="{{$ps.title}}"{{/if}}>
+ {{if $ps.icon}}<i class="fa fa-fw fa-{{$ps.icon}}"></i>{{/if}}
+ {{if $ps.img}}<img class="menu-img-1" src="{{$ps.img}}">{{/if}}
+ {{$ps.label}}
+ {{if $ps.lock}}<i class="fa fa-{{$ps.lock}} text-muted"></i>{{/if}}
+ </a>
+ </li>
+ {{/foreach}}
+ </ul>
+ {{/if}}
+ </li>
+ {{/foreach}}
+</ul>
diff --git a/view/tpl/common_widget.tpl b/view/tpl/common_widget.tpl
new file mode 100644
index 000000000..e542031dc
--- /dev/null
+++ b/view/tpl/common_widget.tpl
@@ -0,0 +1,6 @@
+<div class="widget">
+ <h3>
+ {{$title}}
+ </h3>
+ {{$content}}
+</div>
diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl
index 6baf06dda..ac6af40e9 100755
--- a/view/tpl/conv_item.tpl
+++ b/view/tpl/conv_item.tpl
@@ -29,7 +29,7 @@
<div class="p-2 clearfix wall-item-head{{if $item.is_new && !$item.title && !$item.event && !$item.is_comment}} wall-item-head-new rounded-top{{/if}}">
<div class="wall-item-info " id="wall-item-info-{{$item.id}}" >
<div class="wall-item-photo-wrapper{{if $item.owner_url}} wwfrom{{/if}} h-card p-author" id="wall-item-photo-wrapper-{{$item.id}}">
- <img src="{{$item.thumb}}" class="fakelink wall-item-photo{{$item.sparkle}} u-photo p-name" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" data-toggle="dropdown" />
+ <img src="{{$item.thumb}}" class="fakelink wall-item-photo{{$item.sparkle}} u-photo p-name" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" data-toggle="dropdown" />
{{if $item.thread_author_menu}}
<i class="fa fa-caret-down wall-item-photo-caret cursor-pointer" data-toggle="dropdown"></i>
<div class="dropdown-menu">
diff --git a/view/tpl/design_tools.tpl b/view/tpl/design_tools.tpl
index bc7d46dc1..b4657cb7f 100644
--- a/view/tpl/design_tools.tpl
+++ b/view/tpl/design_tools.tpl
@@ -2,7 +2,7 @@
<h3>{{$title}}</h3>
<div class="nav nav-pills flex-column">
<a class="nav-link" href="blocks/{{$who}}">{{$blocks}}</a>
- <a class="nav-link" href="menu{{if $sys}}?f=&sys=1{{/if}}">{{$menus}}</a>
+ <a class="nav-link" href="menu/{{$who}}">{{$menus}}</a>
<a class="nav-link" href="layouts/{{$who}}">{{$layout}}</a>
<a class="nav-link" href="webpages/{{$who}}">{{$pages}}</a>
</div>
diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl
index 22413f350..365a922f9 100755
--- a/view/tpl/jot-header.tpl
+++ b/view/tpl/jot-header.tpl
@@ -365,12 +365,12 @@ var activeCommentText = '';
if($('#jot-nocomment').val() > 0) {
$('#jot-nocomment').val(0);
$('#profile-nocomment, #profile-nocomment-sub').removeClass('fa-comments-o').addClass('fa-comments');
- $('#profile-nocomment-wrapper').attr('title', '{{$nocomment_enabled}}');
+ $('#profile-nocomment-wrapper').attr('title', '{{$nocomment_enabled|escape:'javascript'}}');
}
else {
$('#jot-nocomment').val(1);
$('#profile-nocomment, #profile-nocomment-sub').removeClass('fa-comments').addClass('fa-comments-o');
- $('#profile-nocomment-wrapper').attr('title', '{{$nocomment_disabled}}');
+ $('#profile-nocomment-wrapper').attr('title', '{{$nocomment_disabled|escape:'javascript'}}');
}
}
diff --git a/view/tpl/menuedit.tpl b/view/tpl/menuedit.tpl
index 84b16dc0b..3558bdbaa 100644
--- a/view/tpl/menuedit.tpl
+++ b/view/tpl/menuedit.tpl
@@ -11,7 +11,7 @@
</div>
{{/if}}
<div id="menu-creator" class="section-content-tools-wrapper" style="display: {{$display}};">
- <form id="menuedit" action="menu{{if $menu_id}}/{{$menu_id}}{{/if}}{{if $sys}}?f=&sys=1{{/if}}" method="post" >
+ <form id="menuedit" action="menu/{{$nick}}{{if $menu_id}}/{{$menu_id}}{{/if}}{{if $sys}}?f=&sys=1{{/if}}" method="post" >
{{if $menu_id}}
<input type="hidden" name="menu_id" value="{{$menu_id}}" />
{{/if}}
diff --git a/view/tpl/menulist.tpl b/view/tpl/menulist.tpl
index e23035062..f9c925472 100644
--- a/view/tpl/menulist.tpl
+++ b/view/tpl/menulist.tpl
@@ -25,11 +25,11 @@
{{foreach $menus as $m }}
<tr id="menu-list-item-{{$m.menu_id}}">
<td>{{if $m.bookmark}}<i class="fa fa-bookmark menu-list-tool" title="{{$bmark}}" ></i>{{/if}}</td>
- <td><a href="mitem/{{$m.menu_id}}{{if $sys}}?f=&sys=1{{/if}}" title="{{$hintcontent}}">{{$m.menu_name}}</a></td>
+ <td><a href="mitem/{{$nick}}/{{$m.menu_id}}{{if $sys}}?f=&sys=1{{/if}}" title="{{$hintcontent}}">{{$m.menu_name}}</a></td>
<td>{{$m.menu_desc}}</td>
- <td class="menu-list-tool"><a href="menu/{{$m.menu_id}}{{if $sys}}?f=&sys=1{{/if}}" title="{{$hintedit}}"><i class="fa fa-pencil"></i></a></td>
+ <td class="menu-list-tool"><a href="menu/{{$nick}}/{{$m.menu_id}}{{if $sys}}?f=&sys=1{{/if}}" title="{{$hintedit}}"><i class="fa fa-pencil"></i></a></td>
<td class="menu-list-tool"><a href="rpost?attachment={{$m.element}}" title="{{$share}}"><i class="fa fa-share-square-o"></i></a></td>
- <td class="menu-list-tool"><a href="#" title="{{$hintdrop}}" onclick="dropItem('menu/{{$m.menu_id}}/drop{{if $sys}}?f=&sys=1{{/if}}', '#menu-list-item-{{$m.menu_id}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a></td>
+ <td class="menu-list-tool"><a href="#" title="{{$hintdrop}}" onclick="dropItem('menu/{{$nick}}/{{$m.menu_id}}/drop{{if $sys}}?f=&sys=1{{/if}}', '#menu-list-item-{{$m.menu_id}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a></td>
<td class="d-none d-md-table-cell">{{$m.menu_created}}</td>
<td class="d-none d-md-table-cell">{{$m.menu_edited}}</td>
</tr>
diff --git a/view/tpl/mitemedit.tpl b/view/tpl/mitemedit.tpl
index 9f696fc23..36be0b207 100644
--- a/view/tpl/mitemedit.tpl
+++ b/view/tpl/mitemedit.tpl
@@ -5,7 +5,7 @@
</div>
{{/if}}
<div id="menu-element-creator" class="section-content-tools-wrapper" style="display: {{$display}};">
- <form id="mitemedit" action="mitem/{{$menu_id}}{{if $mitem_id}}/{{$mitem_id}}{{/if}}{{if $sys}}?f=&sys=1{{/if}}" method="post" class="acl-form" data-form_id="mitemedit" data-allow_cid='{{$allow_cid}}' data-allow_gid='{{$allow_gid}}' data-deny_cid='{{$deny_cid}}' data-deny_gid='{{$deny_gid}}'>
+ <form id="mitemedit" action="mitem/{{$nick}}/{{$menu_id}}{{if $mitem_id}}/{{$mitem_id}}{{/if}}{{if $sys}}?f=&sys=1{{/if}}" method="post" class="acl-form" data-form_id="mitemedit" data-allow_cid='{{$allow_cid}}' data-allow_gid='{{$allow_gid}}' data-deny_cid='{{$deny_cid}}' data-deny_gid='{{$deny_gid}}'>
<input type="hidden" name="menu_id" value="{{$menu_id}}" />
{{if $mitem_id}}
<input type="hidden" name="mitem_id" value="{{$mitem_id}}" />
diff --git a/view/tpl/mitemlist.tpl b/view/tpl/mitemlist.tpl
index b28cdfc7e..1e6302868 100644
--- a/view/tpl/mitemlist.tpl
+++ b/view/tpl/mitemlist.tpl
@@ -24,8 +24,8 @@
<td width="1%">{{$m.mitem_desc}}</td>
<td width="96%"><a href="{{$m.mitem_link}}">{{$m.mitem_link}}</a></td>
<td width="1%" class="mitem-list-tool dropdown">{{if $m.allow_cid || $m.allow_gid || $m.deny_cid || $m.deny_gid}}<i class="fa fa-lock lockview" data-toggle="dropdown" onclick="lockview('menu_item',{{$m.mitem_id}});" ></i><ul id="panel-{{$m.mitem_id}}" class="lockview-panel dropdown-menu"></ul>{{/if}}</td>
- <td width="1%" class="mitem-list-tool"><a href="mitem/{{$menu_id}}/{{$m.mitem_id}}" title="{{$hintedit}}"><i class="fa fa-pencil"></i></a></td>
- <td width="1%" class="mitem-list-tool"><a href="#" title="{{$hintdrop}}" onclick="dropItem('mitem/{{$menu_id}}/{{$m.mitem_id}}/drop', '#mitem-list-item-{{$m.mitem_id}}, #pmenu-item-{{$m.mitem_id}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a></td>
+ <td width="1%" class="mitem-list-tool"><a href="mitem/{{$nick}}/{{$menu_id}}/{{$m.mitem_id}}" title="{{$hintedit}}"><i class="fa fa-pencil"></i></a></td>
+ <td width="1%" class="mitem-list-tool"><a href="#" title="{{$hintdrop}}" onclick="dropItem('mitem/{{$nick}}/{{$menu_id}}/{{$m.mitem_id}}/drop', '#mitem-list-item-{{$m.mitem_id}}, #pmenu-item-{{$m.mitem_id}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a></td>
</tr>
{{/foreach}}
</table>
diff --git a/view/tpl/navbar_default.tpl b/view/tpl/navbar_default.tpl
index 7bc8df8d5..0eb0a964c 100755
--- a/view/tpl/navbar_default.tpl
+++ b/view/tpl/navbar_default.tpl
@@ -27,6 +27,9 @@
{{foreach $nav.usermenu as $usermenu}}
<a class="dropdown-item{{if $usermenu.2}} active{{/if}}" href="{{$usermenu.0}}" title="{{$usermenu.3}}" role="menuitem" id="{{$usermenu.4}}">{{$usermenu.1}}</a>
{{/foreach}}
+ {{if $nav.group}}
+ <a class="dropdown-item" href="{{$nav.group.0}}" title="{{$nav.group.3}}" role="menuitem" id="{{$nav.group.4}}">{{$nav.group.1}}</a>
+ {{/if}}
{{if $nav.manage}}
<a class="dropdown-item{{if $sel.name == Manage}} active{{/if}}" href="{{$nav.manage.0}}" title="{{$nav.manage.3}}" role="menuitem" id="{{$nav.manage.4}}">{{$nav.manage.1}}</a>
{{/if}}
@@ -119,7 +122,7 @@
<ul id="nav-right" class="navbar-nav ml-auto">
<li class="nav-item collapse clearfix" id="nav-search">
- <form class="form-inline" method="get" action="search" role="search">
+ <form class="form-inline" method="get" action="{{$nav.search.4}}" role="search">
<input class="form-control form-control-sm mt-1 mr-2" id="nav-search-text" type="text" value="" placeholder="{{$help}}" name="search" title="{{$nav.search.3}}" onclick="this.submit();" onblur="closeMenu('nav-search'); openMenu('nav-search-btn');"/>
</form>
<div id="nav-search-spinner" class="spinner-wrapper">
diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl
index 215fddd08..068441997 100644
--- a/view/tpl/notifications_widget.tpl
+++ b/view/tpl/notifications_widget.tpl
@@ -127,12 +127,20 @@
{{$no_notifications}}<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span>
</div>
<div id="nav-notifications-template" rel="template">
- <a class="list-group-item clearfix notification {5}" href="{0}" title="{2} {3}" data-b64mid="{6}" data-notify_id="{7}" data-thread_top="{8}" data-contact_name="{2}">
+ <a class="list-group-item clearfix notification {5}" href="{0}" title="{2}" data-b64mid="{6}" data-notify_id="{7}" data-thread_top="{8}" data-contact_name="{2}">
<img class="menu-img-3" data-src="{1}">
<span class="contactname">{2}</span>
<span class="dropdown-sub-text">{3}<br>{4}</span>
</a>
</div>
+ <div id="nav-notifications-forums-template" rel="template">
+ <a class="list-group-item clearfix notification notification-forum" href="{0}" title="{3}" data-b64mid="{6}" data-notify_id="{7}" data-thread_top="{8}" data-contact_name="{2}">
+ <span class="float-right badge badge-{{$notification.severity}}">{9}</span>
+ <img class="menu-img-1" src="{1}">
+ <span class="">{2}</span>
+ <i class="fa fa-{10} text-muted"></i>
+ </a>
+ </div>
<div id="notifications" class="navbar-nav">
{{foreach $notifications as $notification}}
<div class="collapse {{$notification.type}}-button">
@@ -152,15 +160,19 @@
</div>
{{/if}}
{{if $notification.filter}}
+ {{if $notification.filter.posts_label}}
<div class="list-group-item cursor-pointer" id="tt-{{$notification.type}}-only">
<i class="fa fa-fw fa-filter"></i> {{$notification.filter.posts_label}}
</div>
+ {{/if}}
+ {{if $notification.filter.name_label}}
<div class="list-group-item clearfix notifications-textinput" id="cn-{{$notification.type}}-only">
<div class="text-muted notifications-textinput-filter"><i class="fa fa-fw fa-filter"></i></div>
<input id="cn-{{$notification.type}}-input" type="text" class="form-control form-control-sm" placeholder="{{$notification.filter.name_label}}">
<div id="cn-{{$notification.type}}-input-clear" class="text-muted notifications-textinput-clear d-none"><i class="fa fa-times"></i></div>
</div>
{{/if}}
+ {{/if}}
<div id="nav-{{$notification.type}}-menu" class="">
{{$loading}}<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span>
</div>
diff --git a/view/tpl/profile_tabs.tpl b/view/tpl/profile_tabs.tpl
index e77da23f3..dd9fbc52b 100644
--- a/view/tpl/profile_tabs.tpl
+++ b/view/tpl/profile_tabs.tpl
@@ -1,5 +1,5 @@
-<div class="dropdown-header text-white-50 d-lg-none" ><img src="{{$thumb}}" class="menu-img-1">{{$name}}</div>
-<div class="dropdown-header text-black-50 d-none d-lg-block"><img src="{{$thumb}}" class="menu-img-1">{{$name}}</div>
+<div class="dropdown-header text-white-50 d-lg-none" ><img src="{{$thumb}}" class="menu-img-1"> {{$name}}</div>
+<div class="dropdown-header text-black-50 d-none d-lg-block"><img src="{{$thumb}}" class="menu-img-1"> {{$name}}</div>
{{foreach $tabs as $tab}}
<a class="dropdown-item{{if $tab.sel}} {{$tab.sel}}{{/if}}" href="{{$tab.url}}"{{if $tab.title}} title="{{$tab.title}}"{{/if}}><i class="fa fa-fw fa-{{$tab.icon}} generic-icons-nav"></i>{{$tab.label}}</a>
{{/foreach}}
diff --git a/view/tpl/profile_vcard.tpl b/view/tpl/profile_vcard.tpl
index 07e6dcc0a..262bf257f 100755
--- a/view/tpl/profile_vcard.tpl
+++ b/view/tpl/profile_vcard.tpl
@@ -11,7 +11,7 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#" ><i class="fa fa-pencil" title="{{$editmenu.edit.1}}"></i></a>
<div class="dropdown-menu dropdown-menu-right" role="menu">
{{foreach $editmenu.menu.entries as $e}}
- <a href="profiles/{{$e.id}}" class="dropdown-item"><img class="menu-img-1" src='{{$e.photo}}'>{{$e.profile_name}}</a>
+ <a href="profiles/{{$e.id}}" class="dropdown-item"><img class="menu-img-1" src='{{$e.photo}}'> {{$e.profile_name}}</a>
{{/foreach}}
<a href="profile_photo" class="dropdown-item">{{$editmenu.menu.chg_photo}}</a>
{{if $editmenu.menu.cr_new}}<a href="profiles/new" id="profile-listing-new-link" class="dropdown-item">{{$editmenu.menu.cr_new}}</a>{{/if}}
diff --git a/view/tpl/search_item.tpl b/view/tpl/search_item.tpl
index ebfb6a256..018e98989 100755
--- a/view/tpl/search_item.tpl
+++ b/view/tpl/search_item.tpl
@@ -23,7 +23,15 @@
<div class="p-2 clearfix wall-item-head{{if $item.is_new && !$item.title && !$item.event && !$item.is_comment}} wall-item-head-new rounded-top{{/if}}">
<div class="wall-item-info" id="wall-item-info-{{$item.id}}" >
<div class="wall-item-photo-wrapper{{if $item.owner_url}} wwfrom{{/if}}" id="wall-item-photo-wrapper-{{$item.id}}">
- <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-photo-link" id="wall-item-photo-link-{{$item.id}}"><img src="{{$item.thumb}}" class="wall-item-photo{{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" /></a>
+ <img src="{{$item.thumb}}" class="fakelink wall-item-photo{{$item.sparkle}} u-photo p-name" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" data-toggle="dropdown" />
+ {{if $item.thread_author_menu}}
+ <i class="fa fa-caret-down wall-item-photo-caret cursor-pointer" data-toggle="dropdown"></i>
+ <div class="dropdown-menu">
+ {{foreach $item.thread_author_menu as $mitem}}
+ <a class="dropdown-item" {{if $mitem.href}}href="{{$mitem.href}}"{{/if}} {{if $mitem.action}}onclick="{{$mitem.action}}"{{/if}} {{if $mitem.title}}title="{{$mitem.title}}"{{/if}} >{{$mitem.title}}</a>
+ {{/foreach}}
+ </div>
+ {{/if}}
</div>
</div>
{{if $item.lock}}
@@ -54,69 +62,53 @@
<div class="body-tags">
<span class="tag">{{$item.mentions}} {{$item.tags}} {{$item.categories}} {{$item.folders}}</span>
</div>
- {{**
- {{if $item.mentions}}
- <div class="body-tags" id="item-mentions">
- <span class="tag">{{$item.mentions}}</span>
- </div>
- {{/if}}
- {{if $item.tags}}
- <div class="body-tags" id="item-tags">
- <span class="tag">{{$item.tags}}</span>
- </div>
- {{/if}}
- {{if $item.categories}}
- <div class="body-tags" id="item-categories">
- <span class="tag">{{$item.categories}}</span>
- </div>
- {{/if}}
- {{if $item.folders}}
- <div class="body-tags" id="item-folders">
- <span class="tag">{{$item.folders}}</span>
- </div>
- {{/if}}
- **}}
</div>
{{/if}}
<div class="p-2 clearfix wall-item-tools">
- <div class="wall-item-tools-right btn-group pull-right">
- <button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown">
- <i class="fa fa-cog"></i>
- </button>
- <div class="dropdown-menu dropdown-menu-right">
- {{if $item.thread_action_menu}}
- {{foreach $item.thread_action_menu as $mitem}}
- <a class="dropdown-item" {{if $mitem.href}}href="{{$mitem.href}}"{{/if}} {{if $mitem.action}}onclick="{{$mitem.action}}"{{/if}} {{if $mitem.title}}title="{{$mitem.title}}"{{/if}} ><i class="fa fa-{{$mitem.icon}}"></i> {{$mitem.title}}</a></li>
- {{/foreach}}
- {{/if}}
- {{if $item.drop.dropping}}
- <a class="dropdown-item" href="item/drop/{{$item.id}}" onclick="return confirmDelete();" title="{{$item.drop.delete}}" ><i class="fa fa-trash-o"></i> {{$item.drop.delete}}</a></li>
- {{/if}}
- {{if $item.thread_author_menu}}
- <div class="dropdown-divider"></div>
- {{foreach $item.thread_author_menu as $mitem}}
- <a class="dropdown-item" {{if $mitem.href}}href="{{$mitem.href}}"{{/if}} {{if $mitem.action}}onclick="{{$mitem.action}}"{{/if}} {{if $mitem.title}}title="{{$mitem.title}}"{{/if}} >{{$mitem.title}}</a></li>
- {{/foreach}}
- {{/if}}
+ <div class="float-right wall-item-tools-right">
+ <div class="btn-group">
+ <div id="like-rotator-{{$item.id}}" class="spinner-wrapper">
+ <div class="spinner s"></div>
+ </div>
</div>
+ <div class="btn-group">
+ <button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown">
+ <i class="fa fa-cog"></i>
+ </button>
+ <div class="dropdown-menu dropdown-menu-right">
+ {{if $item.star}}
+ <a class="dropdown-item" href="#" onclick="dostar({{$item.id}}); return false;"><i id="starred-{{$item.id}}" class="fa fa-fw{{if $item.star.isstarred}} starred fa-star{{else}} unstarred fa-star-o{{/if}} generic-icons-nav" title="{{$item.star.toggle}}"></i>{{$item.star.toggle}}</a>
+ {{/if}}
+ {{if $item.thread_action_menu}}
+ {{foreach $item.thread_action_menu as $mitem}}
+ <a class="dropdown-item" {{if $mitem.href}}href="{{$mitem.href}}"{{/if}} {{if $mitem.action}}onclick="{{$mitem.action}}"{{/if}} {{if $mitem.title}}title="{{$mitem.title}}"{{/if}} ><i class="fa fa-fw fa-{{$mitem.icon}} generic-icons-nav"></i>{{$mitem.title}}</a></li>
+ {{/foreach}}
+ {{/if}}
+ {{if $item.drop.dropping}}
+ <a class="dropdown-item" href="item/drop/{{$item.id}}" onclick="return confirmDelete();" title="{{$item.drop.delete}}" ><i class="fa fa-fw fa-trash-o generic-icons-nav"></i>{{$item.drop.delete}}</a></li>
+ {{/if}}
+ </div>
+ </div>
+ </div>
+ {{if $item.star && $item.star.isstarred}}
+ <div class="btn-group" id="star-button-{{$item.id}}">
+ <button type="button" class="btn btn-outline-secondary btn-sm wall-item-like" onclick="dostar({{$item.id}});"><i class="fa fa-star"></i></button>
</div>
+ {{/if}}
{{if $item.attachments}}
<div class="wall-item-tools-left btn-group">
<button type="button" class="btn btn-outline-secondary btn-sm wall-item-like dropdown-toggle" data-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="fa fa-paperclip"></i></button>
<div class="dropdown-menu">{{$item.attachments}}</div>
</div>
{{/if}}
- {{if $item.mode === 'moderate'}}
- <div class="wall-item-tools-left btn-group">
+ <div class="wall-item-tools-left btn-group" id="wall-item-tools-left-{{$item.id}}">
+ {{if $item.mode === 'moderate'}}
<a href="moderate/{{$item.id}}/approve" class="btn btn-success btn-sm">{{$item.approve}}</a>
<a href="moderate/{{$item.id}}/drop" class="btn btn-danger btn-sm">{{$item.delete}}</a>
-
+ {{/if}}
</div>
-
-
- {{/if}}
</div>
</div>
{{if $item.conv}}
diff --git a/view/tpl/settings.tpl b/view/tpl/settings.tpl
index b5e871c36..3a05ea828 100755
--- a/view/tpl/settings.tpl
+++ b/view/tpl/settings.tpl
@@ -147,6 +147,7 @@
{{include file="field_intcheckbox.tpl" field=$vnotify13}}
{{/if}}
{{include file="field_intcheckbox.tpl" field=$vnotify14}}
+ {{include file="field_intcheckbox.tpl" field=$vnotify15}}
{{include file="field_intcheckbox.tpl" field=$always_show_in_notices}}
{{include file="field_input.tpl" field=$evdays}}
</div>