aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Vavti <mario@mariovavti.com>2021-02-02 10:58:28 +0100
committerMario Vavti <mario@mariovavti.com>2021-02-02 10:58:28 +0100
commitaf6f7f244e965c2dfb392b060d6e26c30dc78e31 (patch)
treeee7a7c2c69578c501b7be32f5ee95ecaa0a8f853
parentf3f49cf80f2441d576d825f116afdb5a66bb7c54 (diff)
parent08c9152abdfa90da09931bdcc6e6c81ea243434c (diff)
downloadvolse-hubzilla-af6f7f244e965c2dfb392b060d6e26c30dc78e31.tar.gz
volse-hubzilla-af6f7f244e965c2dfb392b060d6e26c30dc78e31.tar.bz2
volse-hubzilla-af6f7f244e965c2dfb392b060d6e26c30dc78e31.zip
Merge branch 'dev' of https://framagit.org/hubzilla/core into dev
-rw-r--r--Zotlabs/Daemon/Convo.php2
-rw-r--r--Zotlabs/Lib/Activity.php161
-rw-r--r--Zotlabs/Lib/ActivityStreams.php232
-rw-r--r--Zotlabs/Lib/ZotURL.php14
-rw-r--r--Zotlabs/Module/Channel.php367
-rw-r--r--Zotlabs/Module/Profile.php117
-rw-r--r--Zotlabs/Module/Search.php14
-rw-r--r--doc/pl/admin/administrator_guide.md456
-rw-r--r--doc/pl/admin/hub_snapshots.md4
-rw-r--r--doc/pl/checking_account_quota_usage.bb20
-rw-r--r--doc/pl/member/member_guide.bb418
-rw-r--r--doc/pl/tutorials/assets/0965ace945f0c95ae38aa5bfedd230d2a7233d3915ac15d629f9dd845854.pngbin0 -> 249151 bytes
-rw-r--r--doc/pl/tutorials/assets/1ebe02c205962dd25035c441631745d16acdb7a44e50d148256c8ad26a67.pngbin0 -> 293314 bytes
-rw-r--r--doc/pl/tutorials/assets/2243e48ccea25bd907cce3dbd6fc9f7cd832a4c91a4c5dd294b7b219e7d8.pngbin0 -> 178913 bytes
-rw-r--r--doc/pl/tutorials/assets/25eaad2435200f72a1dd3a00ba17a76ca6db4c246b3c4fa286b390cae7c8.pngbin0 -> 43797 bytes
-rw-r--r--doc/pl/tutorials/assets/2b539d5a8474d6ec6dc91155b628d9be5f99ab04a78108ec404f53ec7bb5.pngbin0 -> 46752 bytes
-rw-r--r--doc/pl/tutorials/assets/31f42a02bdbae095e0329db6c3814e2975979aff12f873f43d81724c5e61.pngbin0 -> 257211 bytes
-rw-r--r--doc/pl/tutorials/assets/324247680b605fd214fd61aecd8f216fa8f5dfa0f16a04c8e968fdbc43d0.pngbin0 -> 91478 bytes
-rw-r--r--doc/pl/tutorials/assets/3656a67dce40a1fc2515e9089217f2e136d4fcf8babe77bac00ecaad43ce.pngbin0 -> 293611 bytes
-rw-r--r--doc/pl/tutorials/assets/458a842c2ea0fbe3b7869bb14dfffe1e5be098d1cd6e590bbead25b4cc05.pngbin0 -> 318766 bytes
-rw-r--r--doc/pl/tutorials/assets/4aaaf1e124514c8d6999a5fe1d07be5af460cda4ba6cde9106ebc1564bb0.pngbin0 -> 298857 bytes
-rw-r--r--doc/pl/tutorials/assets/4cf326152797a8ecdf5630e921756f825ee00f8ee464d3ef9fed971d2852.pngbin0 -> 532838 bytes
-rw-r--r--doc/pl/tutorials/assets/75d2927b7ad0d2043d4d3b6ba1364fac8ead173edd39340adaf78be11c9d.pngbin0 -> 137827 bytes
-rw-r--r--doc/pl/tutorials/assets/7c976a06662a1357b3da8ed0680d1a721c85f2ae2bdd5739a8def466010e.pngbin0 -> 466641 bytes
-rw-r--r--doc/pl/tutorials/assets/99a6efda4df631dfb2d2a849412044cc6a0f8aebeac289d28786f2649d24.pngbin0 -> 240495 bytes
-rw-r--r--doc/pl/tutorials/assets/9eae9fad774a4cd29e665961d35affbd053368056f562c58200fb41027b0.pngbin0 -> 665755 bytes
-rw-r--r--doc/pl/tutorials/assets/b0bfdf02aef3710a37bb6092c3240b291eca8afa73133b3ac03b86f3302d.pngbin0 -> 324092 bytes
-rw-r--r--doc/pl/tutorials/assets/b334915c03a665493915598c69c17a87c910a39db2cd3b5292e4623ea4c4.pngbin0 -> 466584 bytes
-rw-r--r--doc/pl/tutorials/assets/b3eece28e8db67f1024af42055f0f24ed5e81ba622aca8cac576ccf5930e.pngbin0 -> 155763 bytes
-rw-r--r--doc/pl/tutorials/assets/bdbcf0ffd9004657237f6b7b7863da5a8e39a5bc17d2c67fa160efef2056.pngbin0 -> 134643 bytes
-rw-r--r--doc/pl/tutorials/assets/c4cad3e4c356dd2a227df79bd4dc6d47edf1b66ea243f005b6b452ec366b.pngbin0 -> 306069 bytes
-rw-r--r--doc/pl/tutorials/assets/c9a880cc82ffa1f7c2f460397bb083bf7dc2a2b8f065e64da598b45b4a2b.pngbin0 -> 57185 bytes
-rw-r--r--doc/pl/tutorials/assets/d080e92d797af5e863fa39b2084c16a8410de1f7a6559633435817444aef.pngbin0 -> 255688 bytes
-rw-r--r--doc/pl/tutorials/assets/e05248fdc5688d6d24bde52432fdc7b39692a094559aa504de99352940b1.pngbin0 -> 83265 bytes
-rw-r--r--doc/pl/tutorials/assets/e5d5674a34e848e2cce90a60fc416415271d9c51b81ad2a950fb0157222a.pngbin0 -> 264916 bytes
-rw-r--r--doc/pl/tutorials/assets/ef78bc6aa3fafebd46f353514c907b3fdfe019918fc5553bb3f31388a36f.pngbin0 -> 68194 bytes
-rw-r--r--doc/pl/tutorials/assets/facb0bdfdecb4c779de9048cd14b417c0d76de17af476be5f296b78d70e9.pngbin0 -> 99210 bytes
-rw-r--r--doc/pl/tutorials/personal_channel.md116
-rw-r--r--include/photo/photo_driver.php62
-rw-r--r--view/pl/hmessages.mobin296728 -> 0 bytes
-rw-r--r--view/pl/hmessages.po13
-rw-r--r--view/pl/hstrings.php15
42 files changed, 944 insertions, 1067 deletions
diff --git a/Zotlabs/Daemon/Convo.php b/Zotlabs/Daemon/Convo.php
index f7478d778..940216b2c 100644
--- a/Zotlabs/Daemon/Convo.php
+++ b/Zotlabs/Daemon/Convo.php
@@ -49,7 +49,7 @@ class Convo {
// and that lets us use implied_create
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
- $item = Activity::decode_note($AS, true);
+ $item = Activity::decode_note($AS);
Activity::store($channel, $contact['abook_xchan'], $AS, $item);
}
}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 388d74d91..cedc9adc8 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -87,14 +87,16 @@ class Activity {
}
$headers = [
- 'Accept' => 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ 'Accept' => ActivityStreams::get_accept_header_string($channel),
'Host' => $m['host'],
'Date' => datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T'),
'(request-target)' => 'get ' . get_request_string($url)
];
+
if (isset($token)) {
$headers['Authorization'] = 'Bearer ' . $token;
}
+
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), false);
$x = z_fetch_url($url, true, $redirects, ['headers' => $h]);
}
@@ -111,7 +113,6 @@ class Activity {
return null;
}
-
static function fetch_person($x) {
return self::fetch_profile($x);
}
@@ -177,7 +178,6 @@ class Activity {
}
}
-
static function fetch_image($x) {
$ret = [
'type' => 'Image',
@@ -302,7 +302,7 @@ class Activity {
$m = get_iconfig($i['id'], 'activitypub', 'rawmsg');
if ($m) {
if (is_string($m))
- $t = json_decode($m,true);
+ $t = json_decode($m, true);
else
$t = $m;
}
@@ -351,7 +351,6 @@ class Activity {
return $ret;
}
-
static function encode_item($i) {
$ret = [];
@@ -583,7 +582,6 @@ class Activity {
return $ret;
}
-
static function encode_taxonomy($item) {
$ret = [];
@@ -672,7 +670,6 @@ class Activity {
return $ret;
}
-
static function decode_attachment($item) {
$ret = [];
@@ -696,7 +693,6 @@ class Activity {
return $ret;
}
-
static function encode_activity($i, $recurse = false) {
$ret = [];
@@ -958,7 +954,6 @@ class Activity {
}
// Returns an array of URLS for any mention tags found in the item array $i.
-
static function map_mentions($i) {
if (!$i['term']) {
@@ -981,7 +976,6 @@ class Activity {
}
// Returns an array of all recipients targeted by private item array $i.
-
static function map_acl($i) {
$ret = [];
@@ -1064,6 +1058,7 @@ class Activity {
if ($p['xchan_addr'] && strpos($p['xchan_addr'], '@'))
$ret['preferredUsername'] = substr($p['xchan_addr'], 0, strpos($p['xchan_addr'], '@'));
+
$ret['name'] = $p['xchan_name'];
$ret['updated'] = datetime_convert('UTC', 'UTC', $p['xchan_name_date'], ATOM_TIME);
$ret['icon'] = [
@@ -1093,15 +1088,17 @@ class Activity {
'publicKeyPem' => $p['xchan_pubkey']
];
- $arr = ['xchan' => $p, 'encoded' => $ret];
+ $arr = [
+ 'xchan' => $p,
+ 'encoded' => $ret
+ ];
+
call_hooks('encode_person', $arr);
$ret = $arr['encoded'];
-
return $ret;
}
-
static function activity_mapper($verb) {
if (strpos($verb, '/') === false) {
@@ -1145,7 +1142,7 @@ class Activity {
if (strpos($verb, ACTIVITY_POKE) !== false)
return 'Activity';
- // We should return false, however this will trigger an uncaught execption and crash
+ // We should return false, however this will trigger an uncaught execption and crash
// the delivery system if encountered by the JSON-LDSignature library
logger('Unmapped activity: ' . $verb);
@@ -1153,7 +1150,6 @@ class Activity {
// return false;
}
-
static function activity_decode_mapper($verb) {
$acts = [
@@ -1225,7 +1221,6 @@ class Activity {
return 'Note';
}
-
static function activity_obj_mapper($obj) {
$objs = [
@@ -1272,17 +1267,16 @@ class Activity {
}
-
static function follow($channel, $act) {
$contact = null;
$their_follow_id = null;
/*
- *
- * if $act->type === 'Follow', actor is now following $channel
- * if $act->type === 'Accept', actor has approved a follow request from $channel
- *
+ *
+ * if $act->type === 'Follow', actor is now following $channel
+ * if $act->type === 'Accept', actor has approved a follow request from $channel
+ *
*/
$person_obj = $act->actor;
@@ -1297,7 +1291,7 @@ class Activity {
self::actor_store($person_obj['id'], $person_obj);
- // Find any existing abook record
+ // Find any existing abook record
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($person_obj['id']),
@@ -1314,7 +1308,7 @@ class Activity {
if ($contact && $contact['abook_id']) {
- // A relationship of some form already exists on this site.
+ // A relationship of some form already exists on this site.
switch ($act->type) {
@@ -1469,7 +1463,6 @@ class Activity {
}
-
static function unfollow($channel, $act) {
$contact = null;
@@ -1495,7 +1488,6 @@ class Activity {
return;
}
-
static function actor_store($url, $person_obj) {
if (!is_array($person_obj))
@@ -1601,7 +1593,7 @@ class Activity {
else {
// Record exists. Cache existing records for one week at most
- // then refetch to catch updated profile photos, names, etc.
+ // then refetch to catch updated profile photos, names, etc.
$d = datetime_convert('UTC', 'UTC', 'now - 1 week');
if ($r[0]['xchan_name_date'] > $d)
@@ -1663,7 +1655,6 @@ class Activity {
}
-
static function create_action($channel, $observer_hash, $act) {
if (in_array($act->obj['type'], ['Note', 'Article', 'Video'])) {
@@ -1681,7 +1672,6 @@ class Activity {
}
-
static function like_action($channel, $observer_hash, $act) {
if (in_array($act->obj['type'], ['Note', 'Article', 'Video'])) {
@@ -1692,7 +1682,6 @@ class Activity {
}
// sort function width decreasing
-
static function vid_sort($a, $b) {
if ($a['width'] === $b['width'])
return 0;
@@ -1954,7 +1943,6 @@ class Activity {
}
-
static function update_poll($item, $post) {
$multi = false;
$mid = $post['mid'];
@@ -2047,7 +2035,6 @@ class Activity {
return false;
}
-
static function decode_note($act) {
$response_activity = false;
@@ -2506,9 +2493,6 @@ class Activity {
$item['item_private'] = 2;
}*/
- // TODO: remove
- // $is_parent = (($item['parent_mid'] && $item['parent_mid'] === $item['mid']) ? true : false);
-
if ($item['parent_mid'] && $item['parent_mid'] !== $item['mid']) {
$is_child_node = true;
}
@@ -2563,7 +2547,7 @@ class Activity {
$allowed = true;
// reject public stream comments that weren't sent by the conversation owner
- if ($is_sys_channel && $pubstream && $item['owner_xchan'] !== $observer_hash && ! $fetch_parents) { // TODO: check why? This would make it impossible to fetch externals via zotfeed where $observer_hash = sys channel
+ if ($is_sys_channel && $pubstream && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) {
$allowed = false;
}
}
@@ -2587,12 +2571,6 @@ class Activity {
}*/
}
- // TODO: remove
- /*if ($is_parent && (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream))) {
- logger('no permission');
- return;
- }*/
-
if (tgroup_check($channel['channel_id'], $item) && (!$is_child_node)) {
// for forum deliveries, make sure we keep a copy of the signed original
set_iconfig($item, 'activitypub', 'rawmsg', $act->raw, 1);
@@ -2642,15 +2620,6 @@ class Activity {
return;
}
- // TODO: remove
- /*if (is_array($act->obj)) {
- $content = self::get_content($act->obj);
- }
- if (!$content) {
- logger('no content');
- return;
- }*/
-
$item['aid'] = $channel['channel_account_id'];
$item['uid'] = $channel['channel_id'];
@@ -2717,54 +2686,6 @@ class Activity {
$parent = null;
- // TODO: remove
- /*if (!$is_parent) {
- $p = q("select parent_mid, id, obj_type from item where mid = '%s' and uid = %d limit 1",
- dbesc($item['parent_mid']),
- intval($item['uid'])
- );
- if (!$p) {
- $a = (($fetch_parents) ? self::fetch_and_store_parents($channel, $item) : false);
- if ($a) {
- $p = q("select parent_mid from item where mid = '%s' and uid = %d limit 1",
- dbesc($item['parent_mid']),
- intval($item['uid'])
- );
- }
- else {
- logger('could not fetch parents');
- return;
-
- // @TODO we maybe could accept these is we formatted the body correctly with share_bb()
- // or at least provided a link to the object
- // if(in_array($act->type,[ 'Like','Dislike' ])) {
- // return;
- // }
-
- // @TODO do we actually want that?
- // if no parent was fetched, turn into a top-level post
-
- // turn into a top level post
- // $s['parent_mid'] = $s['mid'];
- // $s['thr_parent'] = $s['mid'];
- }
- }
-
- if ($p[0]['obj_type'] === 'Question') {
- if ($item['obj_type'] === ACTIVITY_OBJ_NOTE && $item['title'] && (!$item['content'])) {
- $item['obj_type'] = 'Answer';
- }
- }
-
- if ($p[0]['parent_mid'] !== $item['parent_mid']) {
- $item['thr_parent'] = $item['parent_mid'];
- }
- else {
- $item['thr_parent'] = $p[0]['parent_mid'];
- }
- $item['parent_mid'] = $p[0]['parent_mid'];
- }*/
-
if ($is_child_node) {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
@@ -2824,24 +2745,6 @@ class Activity {
$x = item_store($item);
}
- // TODO: remove
- /*$r = q("select id, created, edited from item where mid = '%s' and uid = %d limit 1",
- dbesc($item['mid']),
- intval($item['uid'])
- );
- if ($r) {
- if ($item['edited'] > $r[0]['edited']) {
- $item['id'] = $r[0]['id'];
- $x = item_store_update($item);
- }
- else {
- return;
- }
- }
- else {
- $x = item_store($item);
- }*/
-
if ($fetch_parents && $parent && !intval($parent[0]['item_private'])) {
logger('topfetch', LOGGER_DEBUG);
// if the thread owner is a connnection, we will already receive any additional comments to their posts
@@ -2883,23 +2786,6 @@ class Activity {
sync_an_item($channel['channel_id'], $x['item_id']);
}
- // TODO: remove
- /*if (is_array($x) && $x['item_id']) {
- if ($is_parent) {
- if ($item['owner_xchan'] === $channel['channel_hash']) {
- // We are the owner of this conversation, so send all received comments back downstream
- Master::Summon(['Notifier', 'comment-import', $x['item_id']]);
- }
- $r = q("select * from item where id = %d limit 1",
- intval($x['item_id'])
- );
- if ($r) {
- send_status_notifications($x['item_id'], $r[0]);
- }
- }
- sync_an_item($channel['channel_id'], $x['item_id']);
- }*/
-
}
static public function fetch_and_store_parents($channel, $observer_hash, $item, $force = false) {
@@ -2963,7 +2849,7 @@ class Activity {
break;
}
- array_unshift($p,[ $a, $item ]);
+ array_unshift($p, [$a, $item]);
if ($item['parent_mid'] === $item['mid']) {
break;
@@ -3386,7 +3272,6 @@ class Activity {
return;
}
-
static function bb_attach($attach, $body) {
$ret = false;
@@ -3412,9 +3297,7 @@ class Activity {
return $ret;
}
-
// check for the existence of existing media link in body
-
static function media_not_in_body($s, $body) {
if ((strpos($body, ']' . $s . '[/img]') === false) &&
@@ -3426,7 +3309,6 @@ class Activity {
return false;
}
-
static function bb_content($content, $field) {
require_once('include/html2bbcode.php');
@@ -3455,7 +3337,6 @@ class Activity {
return $ret;
}
-
static function get_content($act) {
$content = [];
@@ -3511,7 +3392,6 @@ class Activity {
return $content;
}
-
static function get_textfield($act, $field) {
$content = false;
@@ -3528,7 +3408,6 @@ class Activity {
// Find either an Authorization: Bearer token or 'token' request variable
// in the current web request and return it
-
static function token_from_request() {
foreach (['REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION'] as $s) {
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php
index f877fbb45..ba7ec0c65 100644
--- a/Zotlabs/Lib/ActivityStreams.php
+++ b/Zotlabs/Lib/ActivityStreams.php
@@ -7,25 +7,24 @@ namespace Zotlabs\Lib;
*
* Parses an ActivityStream JSON string.
*/
-
class ActivityStreams {
- public $raw = null;
- public $data = null;
- public $valid = false;
- public $deleted = false;
- public $id = '';
- public $parent_id = '';
- public $type = '';
- public $actor = null;
- public $obj = null;
- public $tgt = null;
- public $origin = null;
- public $owner = null;
- public $signer = null;
- public $ldsig = null;
- public $sigok = false;
- public $recips = null;
+ public $raw = null;
+ public $data = null;
+ public $valid = false;
+ public $deleted = false;
+ public $id = '';
+ public $parent_id = '';
+ public $type = '';
+ public $actor = null;
+ public $obj = null;
+ public $tgt = null;
+ public $origin = null;
+ public $owner = null;
+ public $signer = null;
+ public $ldsig = null;
+ public $sigok = false;
+ public $recips = null;
public $raw_recips = null;
/**
@@ -37,29 +36,29 @@ class ActivityStreams {
*/
function __construct($string) {
- $this->raw = $string;
+ $this->raw = $string;
- if(is_array($string)) {
+ if (is_array($string)) {
$this->data = $string;
}
else {
$this->data = json_decode($string, true);
}
- if($this->data) {
+ if ($this->data) {
// verify and unpack JSalmon signature if present
- if(is_array($this->data) && array_key_exists('signed',$this->data)) {
+ if (is_array($this->data) && array_key_exists('signed', $this->data)) {
$ret = JSalmon::verify($this->data);
$tmp = JSalmon::unpack($this->data['data']);
- if($ret && $ret['success']) {
- if($ret['signer']) {
- $saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
- $this->data = $tmp;
- $this->data['signer'] = $ret['signer'];
+ if ($ret && $ret['success']) {
+ if ($ret['signer']) {
+ $saved = json_encode($this->data, JSON_UNESCAPED_SLASHES);
+ $this->data = $tmp;
+ $this->data['signer'] = $ret['signer'];
$this->data['signed_data'] = $saved;
- if($ret['hubloc']) {
+ if ($ret['hubloc']) {
$this->data['hubloc'] = $ret['hubloc'];
}
}
@@ -68,57 +67,57 @@ class ActivityStreams {
$this->valid = true;
- if(array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
- if($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
+ if (array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
+ if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor'];
- $this->valid = false;
+ $this->valid = false;
}
}
}
- if($this->is_valid()) {
+ if ($this->is_valid()) {
$this->id = $this->get_property_obj('id');
$this->type = $this->get_primary_type();
- $this->actor = $this->get_actor('actor','','');
+ $this->actor = $this->get_actor('actor', '', '');
$this->obj = $this->get_compound_property('object');
$this->tgt = $this->get_compound_property('target');
$this->origin = $this->get_compound_property('origin');
$this->recips = $this->collect_recips();
$this->ldsig = $this->get_compound_property('signature');
- if($this->ldsig) {
- $this->signer = $this->get_compound_property('creator',$this->ldsig);
- if($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
- $this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
+ if ($this->ldsig) {
+ $this->signer = $this->get_compound_property('creator', $this->ldsig);
+ if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
+ $this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
}
}
- if(! $this->obj) {
- $this->obj = $this->data;
+ if (!$this->obj) {
+ $this->obj = $this->data;
$this->type = 'Create';
- if(! $this->actor) {
- $this->actor = $this->get_actor('attributedTo',$this->obj);
+ if (!$this->actor) {
+ $this->actor = $this->get_actor('attributedTo', $this->obj);
}
}
// fetch recursive or embedded activities
- if ($this->obj && is_array($this->obj) && array_key_exists('object',$this->obj)) {
+ if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
}
- if($this->obj && is_array($this->obj) && $this->obj['actor'])
- $this->obj['actor'] = $this->get_actor('actor',$this->obj);
- if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
- $this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
+ if ($this->obj && is_array($this->obj) && $this->obj['actor'])
+ $this->obj['actor'] = $this->get_actor('actor', $this->obj);
+ if ($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
+ $this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
$this->parent_id = $this->get_property_obj('inReplyTo');
- if((! $this->parent_id) && is_array($this->obj)) {
+ if ((!$this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['inReplyTo'];
}
- if((! $this->parent_id) && is_array($this->obj)) {
+ if ((!$this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['id'];
}
}
@@ -147,19 +146,19 @@ class ActivityStreams {
function collect_recips($base = '', $namespace = '') {
$x = [];
- $fields = [ 'to', 'cc', 'bto', 'bcc', 'audience'];
- foreach($fields as $f) {
+ $fields = ['to', 'cc', 'bto', 'bcc', 'audience'];
+ foreach ($fields as $f) {
$y = $this->get_compound_property($f, $base, $namespace);
- if($y) {
- if (! is_array($this->raw_recips)) {
+ if ($y) {
+ if (!is_array($this->raw_recips)) {
$this->raw_recips = [];
}
- if (! is_array($y)) {
- $y = [ $y ];
+ if (!is_array($y)) {
+ $y = [$y];
}
$this->raw_recips[$f] = $y;
- $x = array_merge($x, $y);
+ $x = array_merge($x, $y);
}
}
// not yet ready for prime time
@@ -167,21 +166,21 @@ class ActivityStreams {
return $x;
}
- function expand($arr,$base = '',$namespace = '') {
+ function expand($arr, $base = '', $namespace = '') {
$ret = [];
// right now use a hardwired recursion depth of 5
- for($z = 0; $z < 5; $z ++) {
- if(is_array($arr) && $arr) {
- foreach($arr as $a) {
- if(is_array($a)) {
+ for ($z = 0; $z < 5; $z++) {
+ if (is_array($arr) && $arr) {
+ foreach ($arr as $a) {
+ if (is_array($a)) {
$ret[] = $a;
}
else {
- $x = $this->get_compound_property($a,$base,$namespace);
- if($x) {
- $ret = array_merge($ret,$x);
+ $x = $this->get_compound_property($a, $base, $namespace);
+ if ($x) {
+ $ret = array_merge($ret, $x);
}
}
}
@@ -202,33 +201,33 @@ class ActivityStreams {
*/
function get_namespace($base, $namespace) {
- if(! $namespace)
+ if (!$namespace)
return '';
$key = null;
- foreach( [ $this->data, $base ] as $b ) {
- if(! $b)
+ foreach ([$this->data, $base] as $b) {
+ if (!$b)
continue;
- if(array_key_exists('@context', $b)) {
- if(is_array($b['@context'])) {
- foreach($b['@context'] as $ns) {
- if(is_array($ns)) {
- foreach($ns as $k => $v) {
- if($namespace === $v)
+ if (array_key_exists('@context', $b)) {
+ if (is_array($b['@context'])) {
+ foreach ($b['@context'] as $ns) {
+ if (is_array($ns)) {
+ foreach ($ns as $k => $v) {
+ if ($namespace === $v)
$key = $k;
}
}
else {
- if($namespace === $ns) {
+ if ($namespace === $ns) {
$key = '';
}
}
}
}
else {
- if($namespace === $b['@context']) {
+ if ($namespace === $b['@context']) {
$key = '';
}
}
@@ -248,14 +247,14 @@ class ActivityStreams {
*/
function get_property_obj($property, $base = '', $namespace = '') {
$prefix = $this->get_namespace($base, $namespace);
- if($prefix === null)
+ if ($prefix === null)
return null;
- $base = (($base) ? $base : $this->data);
+ $base = (($base) ? $base : $this->data);
$propname = (($prefix) ? $prefix . ':' : '') . $property;
- if(! is_array($base)) {
- btlogger('not an array: ' . print_r($base,true));
+ if (!is_array($base)) {
+ btlogger('not an array: ' . print_r($base, true));
return null;
}
@@ -279,14 +278,14 @@ class ActivityStreams {
}
static function is_an_actor($s) {
- return (in_array($s, [ 'Application','Group','Organization','Person','Service' ]));
+ return (in_array($s, ['Application', 'Group', 'Organization', 'Person', 'Service']));
}
static function is_response_activity($s) {
- if (! $s) {
+ if (!$s) {
return false;
}
- return (in_array($s, [ 'Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact' ]));
+ return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
}
/**
@@ -298,9 +297,9 @@ class ActivityStreams {
* @return NULL|mixed
*/
- function get_actor($property,$base='',$namespace = '') {
+ function get_actor($property, $base = '', $namespace = '') {
$x = $this->get_property_obj($property, $base, $namespace);
- if($this->is_url($x)) {
+ if ($this->is_url($x)) {
// SECURITY: If we have already stored the actor profile, re-generate it
// from cached data - don't refetch it from the network
@@ -308,15 +307,15 @@ class ActivityStreams {
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
dbesc($x)
);
- if($r) {
- $y = Activity::encode_person($r[0]);
+ if ($r) {
+ $y = Activity::encode_person($r[0]);
$y['cached'] = true;
return $y;
}
}
- $actor = $this->get_compound_property($property,$base,$namespace,true);
- if(is_array($actor) && self::is_an_actor($actor['type'])) {
- if(array_key_exists('id',$actor) && (! array_key_exists('inbox',$actor))) {
+ $actor = $this->get_compound_property($property, $base, $namespace, true);
+ if (is_array($actor) && self::is_an_actor($actor['type'])) {
+ if (array_key_exists('id', $actor) && (!array_key_exists('inbox', $actor))) {
$actor = $this->fetch_property($actor['id']);
}
return $actor;
@@ -336,7 +335,7 @@ class ActivityStreams {
*/
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
$x = $this->get_property_obj($property, $base, $namespace);
- if($this->is_url($x)) {
+ if ($this->is_url($x)) {
$y = $this->fetch_property($x);
if (is_array($y)) {
$x = $y;
@@ -345,22 +344,22 @@ class ActivityStreams {
// verify and unpack JSalmon signature if present
- if(is_array($x) && array_key_exists('signed',$x)) {
+ if (is_array($x) && array_key_exists('signed', $x)) {
$ret = JSalmon::verify($x);
$tmp = JSalmon::unpack($x['data']);
- if($ret && $ret['success']) {
- if($ret['signer']) {
- $saved = json_encode($x,JSON_UNESCAPED_SLASHES);
- $x = $tmp;
- $x['signer'] = $ret['signer'];
+ if ($ret && $ret['success']) {
+ if ($ret['signer']) {
+ $saved = json_encode($x, JSON_UNESCAPED_SLASHES);
+ $x = $tmp;
+ $x['signer'] = $ret['signer'];
$x['signed_data'] = $saved;
- if($ret['hubloc']) {
+ if ($ret['hubloc']) {
$x['hubloc'] = $ret['hubloc'];
}
}
}
}
- if($first && is_array($x) && array_key_exists(0,$x)) {
+ if ($first && is_array($x) && array_key_exists(0, $x)) {
return $x[0];
}
@@ -374,7 +373,7 @@ class ActivityStreams {
* @return boolean
*/
function is_url($url) {
- if(($url) && (! is_array($url)) && (strpos($url, 'http') === 0)) {
+ if (($url) && (!is_array($url)) && (strpos($url, 'http') === 0)) {
return true;
}
@@ -389,13 +388,13 @@ class ActivityStreams {
* @return NULL|mixed
*/
function get_primary_type($base = '', $namespace = '') {
- if(! $base)
+ if (!$base)
$base = $this->data;
$x = $this->get_property_obj('type', $base, $namespace);
- if(is_array($x)) {
- foreach($x as $y) {
- if(strpos($y, ':') === false) {
+ if (is_array($x)) {
+ foreach ($x as $y) {
+ if (strpos($y, ':') === false) {
return $y;
}
}
@@ -409,15 +408,32 @@ class ActivityStreams {
return $x;
}
- static function is_as_request() {
+ static function is_as_request($channel = null) {
+
+ $hookdata = [];
+ if ($channel)
+ $hookdata['channel'] = $channel;
+
+ $hookdata['data'] = ['application/x-zot-activity+json'];
+
+ call_hooks('is_as_request', $hookdata);
+
+ $x = getBestSupportedMimeType($hookdata['data']);
+ return (($x) ? true : false);
+
+ }
+
+ static function get_accept_header_string($channel = null) {
+
+ $hookdata = [];
+ if ($channel)
+ $hookdata['channel'] = $channel;
+
+ $hookdata['data'] = 'application/x-zot-activity+json';
- $x = getBestSupportedMimeType([
- 'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
- 'application/activity+json',
- 'application/ld+json;profile="http://www.w3.org/ns/activitystreams"'
- ]);
+ call_hooks('get_accept_header_string', $hookdata);
- return(($x) ? true : false);
+ return $hookdata['data'];
}
diff --git a/Zotlabs/Lib/ZotURL.php b/Zotlabs/Lib/ZotURL.php
index fa3959f69..6bb01fd7a 100644
--- a/Zotlabs/Lib/ZotURL.php
+++ b/Zotlabs/Lib/ZotURL.php
@@ -21,12 +21,10 @@ class ZotURL {
}
$portable_url = substr($url,6);
- $u = explode('/',$portable_url);
+ $u = explode('/',$portable_url);
$portable_id = $u[0];
- hz_syslog(print_r($u,true));
-
$hosts = self::lookup($portable_id);
- hz_syslog(print_r($hosts,true));
+
if(! $hosts) {
return $ret;
}
@@ -40,8 +38,8 @@ class ZotURL {
if($channel && $m) {
- $headers = [
- 'Accept' => 'application/x-zot+json',
+ $headers = [
+ 'Accept' => 'application/x-zot+json',
'Content-Type' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
@@ -51,9 +49,9 @@ class ZotURL {
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
}
else {
- $h = [ 'Accept: application/x-zot+json' ];
+ $h = [ 'Accept: application/x-zot+json' ];
}
-
+
$result = [];
$redirects = 0;
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index 11f4d3a52..915e0ea60 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -4,10 +4,12 @@ namespace Zotlabs\Module;
use App;
-use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\PermissionDescription;
+use Zotlabs\Web\Controller;
use Zotlabs\Web\HTTPSig;
-use Zotlabs\Lib\Libzot;
require_once('include/items.php');
require_once('include/security.php');
@@ -20,86 +22,116 @@ require_once('include/opengraph.php');
* @brief Channel Controller
*
*/
-
class Channel extends Controller {
function init() {
- if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']))
+ if (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
goaway('search' . '?f=&search=' . $_GET['search']);
$which = null;
- if(argc() > 1)
+ if (argc() > 1)
$which = argv(1);
- if(! $which) {
- if(local_channel()) {
+ if (!$which) {
+ if (local_channel()) {
$channel = App::get_channel();
- if($channel && $channel['channel_address'])
- $which = $channel['channel_address'];
+ if ($channel && $channel['channel_address'])
+ $which = $channel['channel_address'];
}
}
- if(! $which) {
- notice( t('You must be logged in to see this page.') . EOL );
+ if (!$which) {
+ notice(t('You must be logged in to see this page.') . EOL);
return;
}
$profile = 0;
$channel = App::get_channel();
- if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
- $which = $channel['channel_address'];
+ if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
+ $which = $channel['channel_address'];
$profile = argv(1);
}
$channel = channelx_by_nick($which);
- if(! $channel) {
+ if (!$channel) {
http_status_exit(404, 'Not found');
}
// handle zot6 channel discovery
- if(Libzot::is_zot_request()) {
+ if (Libzot::is_zot_request()) {
$sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6');
- if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
- $data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
- $s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
+ if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
+ $data = json_encode(Libzot::zotinfo(['address' => $channel['channel_address'], 'target_url' => $sigdata['signer']]));
+ $s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($sigdata['signer'])
);
- if($s) {
- $data = json_encode(crypto_encapsulate($data,$s[0]['hubloc_sitekey'],Libzot::best_algorithm($s[0]['site_crypto'])));
+ if ($s) {
+ $data = json_encode(crypto_encapsulate($data, $s[0]['hubloc_sitekey'], Libzot::best_algorithm($s[0]['site_crypto'])));
}
}
else {
- $data = json_encode(Libzot::zotinfo([ 'guid_hash' => $channel['channel_hash'] ]));
+ $data = json_encode(Libzot::zotinfo(['guid_hash' => $channel['channel_hash']]));
}
$headers = [
'Content-Type' => 'application/x-zot+json',
'Digest' => HTTPSig::generate_digest_header($data),
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
- ];
- $h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
+ ];
+ $h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
HTTPSig::set_headers($h);
echo $data;
killme();
}
- if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
- $which = $channel['channel_address'];
+ if (ActivityStreams::is_as_request($channel)) {
+
+ // Somebody may attempt an ActivityStreams fetch on one of our message permalinks
+ // Make it do the right thing.
+
+ $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
+ if ($mid && strpos($mid, 'b64.') === 0) {
+ $decoded = @base64url_decode(substr($mid, 4));
+ if ($decoded) {
+ $mid = $decoded;
+ }
+ }
+ if ($mid) {
+ $obj = null;
+ if (strpos($mid, z_root() . '/item/') === 0) {
+ App::$argc = 2;
+ App::$argv = ['item', basename($mid)];
+ $obj = new Item();
+ }
+ if (strpos($mid, z_root() . '/activity/') === 0) {
+ App::$argc = 2;
+ App::$argv = ['activity', basename($mid)];
+ $obj = new Activity();
+ }
+ if ($obj) {
+ $obj->init();
+ }
+ }
+ as_return_and_die(Activity::encode_person($channel, true), $channel);
+ }
+
+ if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
+ $which = $channel['channel_address'];
$profile = argv(1);
}
- head_add_link( [
+ head_add_link([
'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Posts and comments'),
'href' => z_root() . '/feed/' . $which
]);
- head_add_link( [
+ head_add_link([
'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Only posts'),
@@ -109,18 +141,18 @@ class Channel extends Controller {
// Run profile_load() here to make sure the theme is set before
// we start loading content
- profile_load($which,$profile);
+ profile_load($which, $profile);
// Add Opengraph markup
- $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
- if(strpos($mid,'b64.') === 0)
- $mid = @base64url_decode(substr($mid,4));
-
- if($mid)
- $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
- dbesc($mid),
- intval($channel['channel_id'])
- );
+ $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
+ if (strpos($mid, 'b64.') === 0)
+ $mid = @base64url_decode(substr($mid, 4));
+
+ if ($mid)
+ $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
+ dbesc($mid),
+ intval($channel['channel_id'])
+ );
opengraph_add_meta($r ? $r[0] : [], $channel);
}
@@ -131,99 +163,99 @@ class Channel extends Controller {
$category = $datequery = $datequery2 = '';
- $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
+ $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
- if(strpos($mid,'b64.') === 0)
- $decoded = @base64url_decode(substr($mid,4));
- if($decoded)
+ if (strpos($mid, 'b64.') === 0)
+ $decoded = @base64url_decode(substr($mid, 4));
+ if ($decoded)
$mid = $decoded;
- $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']) : '');
+ $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']) : '');
- if(observer_prohibited(true)) {
+ if (observer_prohibited(true)) {
return login();
}
- $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
- $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
- $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'post');
- $search = ((x($_GET,'search')) ? $_GET['search'] : EMPTY_STR);
+ $category = ((x($_REQUEST, 'cat')) ? $_REQUEST['cat'] : '');
+ $hashtags = ((x($_REQUEST, 'tag')) ? $_REQUEST['tag'] : '');
+ $order = ((x($_GET, 'order')) ? notags($_GET['order']) : 'post');
+ $search = ((x($_GET, 'search')) ? $_GET['search'] : EMPTY_STR);
- $groups = array();
+ $groups = [];
$o = '';
- if($update) {
+ if ($update) {
// Ensure we've got a profile owner if updating.
App::$profile['profile_uid'] = App::$profile_uid = $update;
}
$is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false);
- $channel = App::get_channel();
+ $channel = App::get_channel();
$observer = App::get_observer();
- $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
+ $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
- $perms = get_all_perms(App::$profile['profile_uid'],$ob_hash);
+ $perms = get_all_perms(App::$profile['profile_uid'], $ob_hash);
- if(! $perms['view_stream']) {
+ if (!$perms['view_stream']) {
// We may want to make the target of this redirect configurable
- if($perms['view_profile']) {
- notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
- goaway (z_root() . "/profile/" . App::$profile['channel_address']);
+ if ($perms['view_profile']) {
+ notice(t('Insufficient permissions. Request redirected to profile page.') . EOL);
+ goaway(z_root() . "/profile/" . App::$profile['channel_address']);
}
- notice( t('Permission denied.') . EOL);
+ notice(t('Permission denied.') . EOL);
return;
}
- if(! $update) {
+ if (!$update) {
nav_set_selected('Channel Home');
// 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 ($search) {
+ $o .= replace_macros(get_markup_template("section_title.tpl"), [
+ '$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT, 'UTF-8')
+ ]);
}
- if($channel && $is_owner) {
- $channel_acl = array(
+ if ($channel && $is_owner) {
+ $channel_acl = [
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
- 'deny_cid' => $channel['channel_deny_cid'],
- 'deny_gid' => $channel['channel_deny_gid']
- );
+ 'deny_cid' => $channel['channel_deny_cid'],
+ 'deny_gid' => $channel['channel_deny_gid']
+ ];
}
else {
- $channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
+ $channel_acl = ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''];
}
- if($perms['post_wall']) {
-
- $x = array(
- 'is_owner' => $is_owner,
- 'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
- 'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''),
- 'nickname' => App::$profile['channel_address'],
- 'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
- 'acl' => (($is_owner) ? populate_acl($channel_acl,true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
- 'permissions' => $channel_acl,
- 'showacl' => (($is_owner) ? 'yes' : ''),
- 'bang' => '',
- 'visitor' => (($is_owner || $observer) ? true : false),
- 'profile_uid' => App::$profile['profile_uid'],
+ if ($perms['post_wall']) {
+
+ $x = [
+ 'is_owner' => $is_owner,
+ 'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'], 'system', 'use_browser_location')))) ? true : false),
+ 'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''),
+ 'nickname' => App::$profile['channel_address'],
+ 'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
+ 'acl' => (($is_owner) ? populate_acl($channel_acl, true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
+ 'permissions' => $channel_acl,
+ 'showacl' => (($is_owner) ? 'yes' : ''),
+ 'bang' => '',
+ 'visitor' => (($is_owner || $observer) ? true : false),
+ 'profile_uid' => App::$profile['profile_uid'],
'editor_autocomplete' => true,
- 'bbco_autocomplete' => 'bbcode',
- 'bbcode' => true,
- 'jotnets' => true,
- 'reset' => t('Reset form')
- );
+ 'bbco_autocomplete' => 'bbcode',
+ 'bbcode' => true,
+ 'jotnets' => true,
+ 'reset' => t('Reset form')
+ ];
- $o .= status_editor($a,$x,false,'Channel');
+ $o .= status_editor($a, $x, false, 'Channel');
}
}
@@ -233,15 +265,15 @@ class Channel extends Controller {
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
*/
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0
and item.item_unpublished = 0 and item.item_pending_remove = 0
and item.item_blocked = 0 ";
- if (! $is_owner)
- $item_normal .= "and item.item_delayed = 0 ";
+ if (!$is_owner)
+ $item_normal .= "and item.item_delayed = 0 ";
$item_normal_update = item_normal_update();
- $sql_extra = item_permissions_sql(App::$profile['profile_uid']);
+ $sql_extra = item_permissions_sql(App::$profile['profile_uid']);
- if(feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (! $mid))
+ if (feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (!$mid))
$page_mode = 'list';
else
$page_mode = 'client';
@@ -249,13 +281,13 @@ class Channel extends Controller {
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
$simple_update = '';
- if($update && $_SESSION['loadtime'])
- $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
+ if ($update && $_SESSION['loadtime'])
+ $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) ";
- if($search) {
+ if ($search) {
$search = escape_tags($search);
- if(strpos($search,'#') === 0) {
- $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
+ if (strpos($search, '#') === 0) {
+ $sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG, TERM_COMMUNITYTAG);
}
else {
$sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ",
@@ -272,9 +304,9 @@ class Channel extends Controller {
'title' => 'oembed'
]);
- if(($update) && (! $load)) {
+ if (($update) && (!$load)) {
- if($mid) {
+ if ($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
AND item_wall = 1 $simple_update $sql_extra limit 1",
dbesc($mid . '%'),
@@ -295,40 +327,40 @@ class Channel extends Controller {
}
else {
- if(x($category)) {
- $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
+ if (x($category)) {
+ $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
}
- if(x($hashtags)) {
- $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
+ if (x($hashtags)) {
+ $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
- if($datequery) {
- $sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
- $order = 'post';
+ 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))));
+ if ($datequery2) {
+ $sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2))));
}
- if($order === 'post')
+ if ($order === 'post')
$ordering = "created";
else
$ordering = "commented";
- $itemspage = get_pconfig(local_channel(),'system','itemspage');
+ $itemspage = get_pconfig(local_channel(), 'system', 'itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
- if($noscript_content || $load) {
- if($mid) {
+ if ($noscript_content || $load) {
+ if ($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid . '%'),
intval(App::$profile['profile_uid'])
);
- if (! $r) {
- notice( t('Permission denied.') . EOL);
+ if (!$r) {
+ notice(t('Permission denied.') . EOL);
}
}
else {
@@ -344,12 +376,12 @@ class Channel extends Controller {
}
}
else {
- $r = array();
+ $r = [];
}
}
- if($r) {
+ if ($r) {
- $parents_str = ids_to_querystr($r,'item_id');
+ $parents_str = ids_to_querystr($r, 'item_id');
$r = q("SELECT item.*, item.id AS item_id
FROM item
@@ -362,37 +394,38 @@ class Channel extends Controller {
xchan_query($r);
$items = fetch_post_tags($r, true);
- $items = conv_sort($items,$ordering);
+ $items = conv_sort($items, $ordering);
- if($load && $mid && (! count($items))) {
+ if ($load && $mid && (!count($items))) {
// This will happen if we don't have sufficient permissions
// to view the parent item (or the item itself if it is toplevel)
- notice( t('Permission denied.') . EOL);
+ notice(t('Permission denied.') . EOL);
}
- } else {
- $items = array();
+ }
+ else {
+ $items = [];
}
// Add pinned content
- if(! x($_REQUEST,'mid') && ! $search) {
+ if (!x($_REQUEST, 'mid') && !$search) {
$pinned = new \Zotlabs\Widget\Pinned;
- $r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
- $o .= $r['html'];
+ $r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
+ $o .= $r['html'];
}
$mode = (($search) ? 'search' : 'channel');
- if((! $update) && (! $load)) {
+ if ((!$update) && (!$load)) {
- if($decoded)
+ if ($decoded)
$mid = 'b64.' . base64url_encode($mid);
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
- $maxheight = get_pconfig(App::$profile['profile_uid'],'system','channel_divmore_height');
- if(! $maxheight)
+ $maxheight = get_pconfig(App::$profile['profile_uid'], 'system', 'channel_divmore_height');
+ if (!$maxheight)
$maxheight = 400;
$o .= '<div id="live-channel"></div>' . "\r\n";
@@ -400,48 +433,48 @@ class Channel extends Controller {
. "; var netargs = '?f='; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . ";</script>\r\n";
- App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
- '$baseurl' => z_root(),
- '$pgtype' => 'channel',
- '$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'),
- '$gid' => '0',
- '$cid' => '0',
- '$cmin' => '(-1)',
- '$cmax' => '(-1)',
- '$star' => '0',
- '$liked' => '0',
- '$conv' => '0',
- '$spam' => '0',
- '$nouveau' => '0',
- '$wall' => '1',
- '$fh' => '0',
- '$dm' => '0',
- '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
- '$search' => $search,
- '$xchan' => '',
- '$order' => (($order) ? urlencode($order) : ''),
- '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
- '$file' => '',
- '$cats' => (($category) ? urlencode($category) : ''),
- '$tags' => (($hashtags) ? urlencode($hashtags) : ''),
- '$mid' => (($mid) ? urlencode($mid) : ''),
- '$verb' => '',
- '$net' => '',
- '$dend' => $datequery,
- '$dbegin' => $datequery2,
+ App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"), [
+ '$baseurl' => z_root(),
+ '$pgtype' => 'channel',
+ '$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'),
+ '$gid' => '0',
+ '$cid' => '0',
+ '$cmin' => '(-1)',
+ '$cmax' => '(-1)',
+ '$star' => '0',
+ '$liked' => '0',
+ '$conv' => '0',
+ '$spam' => '0',
+ '$nouveau' => '0',
+ '$wall' => '1',
+ '$fh' => '0',
+ '$dm' => '0',
+ '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
+ '$search' => $search,
+ '$xchan' => '',
+ '$order' => (($order) ? urlencode($order) : ''),
+ '$list' => ((x($_REQUEST, 'list')) ? intval($_REQUEST['list']) : 0),
+ '$file' => '',
+ '$cats' => (($category) ? urlencode($category) : ''),
+ '$tags' => (($hashtags) ? urlencode($hashtags) : ''),
+ '$mid' => (($mid) ? urlencode($mid) : ''),
+ '$verb' => '',
+ '$net' => '',
+ '$dend' => $datequery,
+ '$dbegin' => $datequery2,
'$conv_mode' => 'channel',
'$page_mode' => $page_mode
- ));
+ ]);
}
- if($update) {
- $o .= conversation($items,$mode,$update,$page_mode);
+ if ($update) {
+ $o .= conversation($items, $mode, $update, $page_mode);
}
else {
$o .= '<noscript>';
- if($noscript_content) {
- $o .= conversation($items,$mode,$update,'traditional');
+ if ($noscript_content) {
+ $o .= conversation($items, $mode, $update, 'traditional');
$o .= alt_pager(count($items));
}
else {
@@ -449,14 +482,14 @@ class Channel extends Controller {
}
$o .= '</noscript>';
- $o .= conversation($items,$mode,$update,$page_mode);
+ $o .= conversation($items, $mode, $update, $page_mode);
if ($mid && $items[0]['title'])
App::$page['title'] = $items[0]['title'] . " - " . App::$page['title'];
}
- if($mid)
+ if ($mid)
$o .= '<div id="content-complete"></div>';
$_SESSION['loadtime'] = datetime_convert();
diff --git a/Zotlabs/Module/Profile.php b/Zotlabs/Module/Profile.php
index 0373630a9..118f11f64 100644
--- a/Zotlabs/Module/Profile.php
+++ b/Zotlabs/Module/Profile.php
@@ -1,5 +1,13 @@
<?php
-namespace Zotlabs\Module; /** @file */
+
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Web\Controller;
+
+/** @file */
require_once('include/contact_widgets.php');
require_once('include/items.php');
@@ -9,110 +17,115 @@ require_once('include/conversation.php');
require_once('include/acl_selectors.php');
-
-class Profile extends \Zotlabs\Web\Controller {
+class Profile extends Controller {
function init() {
-
- if(argc() > 1)
+
+ if (argc() > 1)
$which = argv(1);
else {
- notice( t('Requested profile is not available.') . EOL );
- \App::$error = 404;
+ notice(t('Requested profile is not available.') . EOL);
+ App::$error = 404;
return;
}
- nav_set_selected('Profile');
-
$profile = '';
- $channel = \App::get_channel();
-
- if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
- $which = $channel['channel_address'];
- $profile = argv(1);
- $r = q("select profile_guid from profile where id = %d and uid = %d limit 1",
+ $channel = App::get_channel();
+
+ if (!$channel)
+ http_status_exit(404, 'Not found');
+
+ if (ActivityStreams::is_as_request()) {
+ $p = Activity::encode_person($channel, true);
+ as_return_and_die(['type' => 'Profile', 'describes' => $p], $channel);
+ }
+
+ nav_set_selected('Profile');
+
+ if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
+ $which = $channel['channel_address'];
+ $profile = argv(1);
+ $r = q("select profile_guid from profile where id = %d and uid = %d limit 1",
intval($profile),
intval(local_channel())
);
- if(! $r)
+ if (!$r)
$profile = '';
$profile = $r[0]['profile_guid'];
}
-
- head_add_link( [
- 'rel' => 'alternate',
+
+ head_add_link([
+ 'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Posts and comments'),
'href' => z_root() . '/feed/' . $which
]);
- head_add_link( [
- 'rel' => 'alternate',
+ head_add_link([
+ 'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Only posts'),
'href' => z_root() . '/feed/' . $which . '?f=&top=1'
]);
- if(! $profile) {
+ if (!$profile) {
$x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1",
dbesc(argv(1))
);
- if($x) {
- \App::$profile = $x[0];
+ if ($x) {
+ App::$profile = $x[0];
}
}
-
- profile_load($which,$profile);
-
-
+
+ profile_load($which, $profile);
+
+
}
-
+
function get() {
-
- if(observer_prohibited(true)) {
+
+ if (observer_prohibited(true)) {
return login();
}
-
- $groups = array();
+ $groups = [];
$tab = 'profile';
- $o = '';
-
- if(! (perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(), 'view_profile'))) {
- notice( t('Permission denied.') . EOL);
+ $o = '';
+
+ if (!(perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_profile'))) {
+ notice(t('Permission denied.') . EOL);
return;
}
-
- if(argc() > 2 && argv(2) === 'vcard') {
+ if (argc() > 2 && argv(2) === 'vcard') {
header('Content-type: text/vcard');
- header('content-disposition: attachment; filename="' . t('vcard') . '-' . \App::$profile['channel_address'] . '.vcf"' );
- echo \App::$profile['profile_vcard'];
+ header('content-disposition: attachment; filename="' . t('vcard') . '-' . App::$profile['channel_address'] . '.vcf"');
+ echo App::$profile['profile_vcard'];
killme();
}
-
- $is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false);
-
- if(\App::$profile['hidewall'] && (! $is_owner) && (! remote_channel())) {
- notice( t('Permission denied.') . EOL);
+
+ $is_owner = ((local_channel()) && (local_channel() == App::$profile['profile_uid']) ? true : false);
+
+ if (App::$profile['hidewall'] && (!$is_owner) && (!remote_channel())) {
+ notice(t('Permission denied.') . EOL);
return;
}
-
- head_add_link([
+
+ head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
- 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
+ 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
$o .= advanced_profile();
- call_hooks('profile_advanced',$o);
+ call_hooks('profile_advanced', $o);
return $o;
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php
index 95510c349..eeeff9613 100644
--- a/Zotlabs/Module/Search.php
+++ b/Zotlabs/Module/Search.php
@@ -58,15 +58,13 @@ class Search extends Controller {
$o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false));
- if (local_channel() && strpos($search, 'https://') === 0) {
+ if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) {
$j = Activity::fetch($search, App::get_channel());
if ($j) {
$AS = new ActivityStreams($j);
-
if ($AS->is_valid()) {
// check if is_an_actor, otherwise import activity
if (is_array($AS->obj) && !ActivityStreams::is_an_actor($AS->obj)) {
- // The boolean flag enables html cache of the item
$item = Activity::decode_note($AS);
if ($item) {
logger('parsed_item: ' . print_r($item, true), LOGGER_DATA);
@@ -76,6 +74,14 @@ class Search extends Controller {
}
}
}
+ else {
+ // try other fetch providers (e.g. diaspora)
+ $hookdata = [
+ 'channel' => App::get_channel(),
+ 'data' => $search
+ ];
+ call_hooks('fetch_provider', $hookdata);
+ }
}
if (strpos($search, '#') === 0) {
@@ -120,7 +126,7 @@ class Search extends Controller {
// Here is the way permissions work in the search module...
// Only public posts can be shown
// OR your own posts if you are a logged in member
- // No items will be shown if the member has a blocked profile wall.
+ // No items will be shown if the member has a blocked profile wall.
if ((!$update) && (!$load)) {
diff --git a/doc/pl/admin/administrator_guide.md b/doc/pl/admin/administrator_guide.md
index 540828e0d..86e5fd80c 100644
--- a/doc/pl/admin/administrator_guide.md
+++ b/doc/pl/admin/administrator_guide.md
@@ -1,11 +1,6 @@
### Przegląd
-$Projectname to więcej niż prosta aplikacja internetowa. Jest to złożony system
-komunikacyjny, który bardziej przypomina serwer poczty elektronicznej niż serwer
-WWW. Aby zapewnić niezawodność i wydajność, wiadomości są dostarczane w tle i
-umieszczane w kolejce do późniejszego dostarczenia, gdy lokacje są wyłączone.
-Ten rodzaj funkcjonalności wymaga nieco więcej zasobów hosta niż typowy dziennik.
-Nie każdy dostawca hostingu PHP-MySQL będzie w stanie obsługiwać $Projectname. Tak więc, przed instalacją zapoznaj się z wymaganiami i potwierdź je u dostawcy usług hostingowych.
+$Projectname to więcej niż prosta aplikacja internetowa. Jest to złożony system komunikacyjny, który bardziej przypomina serwer poczty elektronicznej niż serwer WWW. Aby zapewnić niezawodność i wydajność, wiadomości są dostarczane w tle i umieszczane w kolejce do późniejszego dostarczenia, gdy lokacje są wyłączone. Ten rodzaj funkcjonalności wymaga nieco więcej zasobów hosta niż typowy dziennik. Nie każdy dostawca hostingu PHP-MySQL będzie w stanie obsługiwać $Projectname. Tak więc, przed instalacją zapoznaj się z wymaganiami i potwierdź je u dostawcy usług hostingowych.
Bardzo staraliśmy się, aby Hubzilla działała na zwykłych platformach hostingowych, takich jak te używane do hostowania blogów Wordpress i stron internetowych Drupal. Będzie ona działać na większości systemów VPS Linux. Platformy Windows LAMP, takie jak XAMPP i WAMP, nie są obecnie oficjalnie obsługiwane, jednak mile widziane są poprawki, jeśli uda Ci się je uruchomić.
@@ -17,50 +12,24 @@ Jeśli napotkasz problemy lub sam masz jakiś problem, które nie zostały opisa
#### Wybierz nazwę domeny lub subdomeny dla swojego serwera
-Platformę $Projectname można zainstalować tylko w katalogu głównym domeny lub
-subdomeny i nie może ona działać na niestandardowych portach TCP.
+Platformę $Projectname można zainstalować tylko w katalogu głównym domeny lub subdomeny i nie może ona działać na niestandardowych portach TCP.
#### Zdecyduj, czy będziesz używać SSL i uzyskaj certyfikat SSL przed instalacją oprogramowania
-POWINNO się używać SSL. Jeśli używasz SSL, MUSISZ użyć certyfikatu uznawanego
-przez przeglądarki. **NIE WOLNO używać certyfikatów z podpisem własnym!**
-
-Przetestuj swój certyfikat przed instalacją. Narzędzie internetowe do testowania
-certyfikatu jest dostępne pod adresem `http://www.digicert.com/help/`.
-Odwiedzając witrynę po raz pierwszy, użyj adresu URL SSL (`https: //`), jeśli
-protokół SSL jest dostępny. Pozwoli to uniknąć późniejszych problemów. Procedura
-instalacji nie pozwoli na użycie certyfikatu, który nie jest zaufany dla przeglądarki.
-
-To ograniczenie zostało wprowadzone, ponieważ Twoje publiczne wpisy mogą zawierać
-odniesienia do obrazów na Twoim hubie. Inni członkowie przeglądający swój strumień
-w innych centrach otrzymają ostrzeżenia, jeśli Twój certyfikat nie jest zaufany
-w ich przeglądarce internetowej. To zmyli wiele osób, ponieważ jest to
-zdecentralizowana sieć i otrzymają ostrzeżenie o Twoim hubie podczas przeglądania
-własnego huba i mogą pomyśleć, że ich własny hub ma problem. Te ostrzeżenia
-są bardzo techniczne i przerażające dla niektórych osób, z których wielu nie
-będzie wiedziało, jak postępować, z wyjątkiem przestrzegania zaleceń przeglądarki.
-Jest to destrukcyjne dla społeczności. To powiedziawszy, zdajemy sobie sprawę z
-problemów związanych z obecną infrastrukturą certyfikatów i zgadzamy się, że
-istnieje wiele problemów, ale to nie zmienia wymagania.
-
-Bezpłatne certyfikaty zgodne z przeglądarkami są dostępne od dostawców, takich
-jak StartSSL i LetsEncrypt.
-
-Jeśli NIE używasz SSL, może wystąpić opóźnienie do minuty dla startowego skryptu
-instalacyjnego - podczas sprawdzania portu SSL, aby zobaczyć, czy tam jest wszystko
-w porządku. Podczas komunikowania się z nowymi witrynami Hubzilla zawsze najpierw
-próbuje połączyć się z portem SSL, zanim powróci do mniej bezpiecznego połączenia.
-Jeśli nie używasz SSL, twój serwer WWW NIE MOŻE w ogóle nasłuchiwać na porcie 443.
-
-Jeśli używasz LetsEncrypt do dostarczania certyfikatów i tworzenia pliku pod
-`well-known` lub `acme-challenge`, aby LetsEncrypt mógł zweryfikować własność
-domeny, usuń lub zmień nazwę katalogu `.well-known` zaraz po wygenerowaniu
-certyfikatu. $Projectname zapewni własną procedurę obsługi usług `.well-know` po
-zainstalowaniu, a istniejący katalog w tej lokalizacji może uniemożliwić poprawne
-działanie niektórych z tych usług. Nie powinno to stanowić problemu w przypadku
-Apache, ale może to być problem z Nginx lub innymi platformami serwera internetowego.
+POWINNO się używać SSL. Jeśli używasz SSL, MUSISZ użyć certyfikatu uznawanego przez przeglądarki. **NIE WOLNO używać certyfikatów z podpisem własnym!**
+
+Przetestuj swój certyfikat przed instalacją. Narzędzie internetowe do testowania certyfikatu jest dostępne pod adresem http://www.digicert.com/help/. Odwiedzając witrynę po raz pierwszy, użyj adresu URL SSL (https://), jeśli protokół SSL jest dostępny. Pozwoli to uniknąć późniejszych problemów. Procedura instalacji nie pozwoli na użycie certyfikatu, który nie jest zaufany dla przeglądarki.
+
+To ograniczenie zostało wprowadzone, ponieważ Twoje publiczne wpisy mogą zawierać odniesienia do obrazów na Twoim hubie. Inni członkowie przeglądający swój strumień w innych centrach otrzymają ostrzeżenia, jeśli Twój certyfikat nie jest zaufany w ich przeglądarce internetowej. To zmyli wiele osób, ponieważ jest to zdecentralizowana sieć i otrzymają ostrzeżenie o Twoim hubie podczas przeglądania własnego huba i mogą pomyśleć, że ich własny hub ma problem. Te ostrzeżenia są bardzo techniczne i przerażające dla niektórych osób, z których wielu nie będzie wiedziało, jak postępować, z wyjątkiem przestrzegania zaleceń przeglądarki. Jest to destrukcyjne dla społeczności. To powiedziawszy, zdajemy sobie sprawę z problemów związanych z obecną infrastrukturą certyfikatów i zgadzamy się, że istnieje wiele problemów, ale to nie zmienia wymagania.
+
+Bezpłatne certyfikaty zgodne z przeglądarkami są dostępne od dostawców, takich jak StartSSL i LetsEncrypt.
+
+Jeśli NIE używasz SSL, może wystąpić opóźnienie do minuty dla startowego skryptu instalacyjnego - podczas sprawdzania portu SSL, aby zobaczyć, czy tam jest wszystko w porządku. Podczas komunikowania się z nowymi witrynami Hubzilla zawsze najpierw próbuje połączyć się z portem SSL, zanim powróci do mniej bezpiecznego połączenia. Jeśli nie używasz SSL, twój serwer WWW NIE MOŻE w ogóle nasłuchiwać na porcie 443.
+
+Jeśli używasz LetsEncrypt do dostarczania certyfikatów i tworzenia pliku pod _well-known_ lub _acme-challenge_, aby LetsEncrypt mógł zweryfikować własność domeny, usuń lub zmień nazwę katalogu _.well-known_ zaraz po wygenerowaniu certyfikatu. $Projectname zapewni własną procedurę obsługi usług *.well-know* po zainstalowaniu, a istniejący katalog w tej lokalizacji może uniemożliwić poprawne działanie niektórych z tych usług. Nie powinno to stanowić problemu w przypadku Apache, ale może to być problem z Nginx lub innymi platformami serwera internetowego.
### Wdrożenie
+
Nowy hub można wdrożyć na kilka sposobów:
* ręczna inastalaja na istniejącym serwerze;
@@ -68,22 +37,15 @@ Nowy hub można wdrożyć na kilka sposobów:
* automatyczne wdrożenie przy użyciu prywatnego serwera wirtualnego OpenShift (VPS).)
### Wymagania
-* Apache z włączonym modułem `mod-rewrite` i ustawioną dyrektywą "AllowOverride
- All", tak aby można było stosować plik `.htaccess`. Niektóre osoby z powodzeniem
- stosowały Nginx czy Lighttpd.Przykładowe skrypty konfiguracyjne są dostępne na
- tej platformie w [doc/install](). Apache and Nginx mają najlepsze wsparcie.
+
+* Apache z włączonym modułem _mod-rewrite_ i ustawioną dyrektywą "AllowOverride All", tak aby można było stosować plik _.htaccess_. Niektóre osoby z powodzeniem stosowały Nginx czy Lighttpd.Przykładowe skrypty konfiguracyjne są dostępne na tej platformie w [doc/install](). Apache and Nginx mają najlepsze wsparcie.
* PHP 7.1 lub w wersji wyższej.
- * _Proszę mieć na uwadze, że w niektórych środowiskach hostinu
- współdzielonego, wersja wiersza poleceń PHP różni się od wersji
- serwera internetowego_
+ * _Proszę mieć na uwadze, że w niektórych środowiskach hostinu współdzielonego, wersja wiersza poleceń PHP różni się od wersji serwera internetowego_
-* Dostęp do wiersza poleceń PHP z ustawionym w pliku php.ini parametrem
- `register_argc_argv` na `true` i bez ograniczeń dostawcy hostingu w zakresie
- stosowania fumkcji `exec()` i `proc_open()`.
+* Dostęp do wiersza poleceń PHP z ustawionym w pliku php.ini parametrem _register_argc_argv_ na true i bez ograniczeń dostawcy hostingu w zakresie stosowania funkcji _exec()_ i _proc_open()_.
-* Rozszerzenia curl, gd (z obsługą co najmmniej jpeg i png), mysqli, mbstring,
- mcrypt, zip i openssl. Tozszerzenie imagick nie jest wymagane ale jest zalecane.
+* Rozszerzenia curl, gd (z obsługą co najmmniej jpeg i png), mysqli, mbstring, mcrypt, zip i openssl. Tozszerzenie imagick nie jest wymagane ale jest zalecane.
* Wymagane jest rozszerzenie xml, jeśli chce sie mieć działajacą obsługę webdav.
@@ -93,21 +55,15 @@ Nowy hub można wdrożyć na kilka sposobów:
* Możliwość planowania zadań dla crona.
-* WYMAGANA jest instalacja w katalogu głównym hosta WWW (wirtualnego hosta w
- Apache i bloku w Nginx).
+* WYMAGANA jest instalacja w katalogu głównym hosta WWW (wirtualnego hosta w Apache i bloku w Nginx).
### Instalacja ręczna
##### Krok 1.
-Rozpakuj pliki $Projectname do katalogu głównego obszaru dokumentów serwera WWW.
-Jeśli kopiujesz drzewo katalogów na swój serwer WWW, upewnij się, że dołączasz
-ukryte pliki, takie jak `.htaccess`.
+Rozpakuj pliki $Projectname do katalogu głównego obszaru dokumentów serwera WWW. Jeśli kopiujesz drzewo katalogów na swój serwer WWW, upewnij się, że dołączasz ukryte pliki, takie jak _.htaccess_.
-Jeśli możesz to zrobić, zalecamy użycie Git do sklonowania repozytorium źródłowego
-zamiast używania spakowanego pliku tar lub zip. To znacznie ułatwia późniejszą
-aktualizację oprogramowania. Polecenie Linux do sklonowania repozytorium do katalogu
-"mywebsite: wyglądałoby tak:
+Jeśli możesz to zrobić, zalecamy użycie Git do sklonowania repozytorium źródłowego zamiast używania spakowanego pliku tar lub zip. To znacznie ułatwia późniejszą aktualizację oprogramowania. Polecenie Linux do sklonowania repozytorium do katalogu "mywebsite: wyglądałoby tak:
git clone https://framagit.org/hubzilla/core.git mywebsite
@@ -115,111 +71,71 @@ a następnie, w dowolnym momencie, możesz pobrać najnowsze zmiany za pomocą:
git pull
-upewnij się, że istniejeją foldery `store/[data]/smarty3` i `store` i że są
-one możliwe do zapisu przez właściciela procesu serwera WWW:
+upewnij się, że istniejeją foldery `store/[data]/smarty3` i `store` i że są one możliwe do zapisu przez właściciela procesu serwera WWW:
mkdir -p "store/[data]/smarty3"
chmod -R 777 store
-To uprawnienie (777) jest bardzo niebezpieczne i jeśli masz wystarczające
-uprawnienia i wiedzę powinieneś umożliwić zapisywanie w tych katalogach tylko
-przez serwer WWW i użytkownika, który uruchomia crona (patrz poniżej), jeśli jest
-taki. W wielu współdzielonych środowiskach hostingowych może to być trudne, bez
-zgłoszenia problemu u dostawcy. Powyższe uprawnienia pozwolą oprogramowaniu
-działać, ale nie są optymalne.
+To uprawnienie (777) jest bardzo niebezpieczne i jeśli masz wystarczające uprawnienia i wiedzę powinieneś umożliwić zapisywanie w tych katalogach tylko przez serwer WWW i użytkownika, który uruchomia crona (patrz poniżej), jeśli jest taki. W wielu współdzielonych środowiskach hostingowych może to być trudne, bez zgłoszenia problemu u dostawcy. Powyższe uprawnienia pozwolą oprogramowaniu działać, ale nie są optymalne.
-Aby działały niektóre internetowe narzędzia administracyjne, serwer WWW musi mieć
-możliwość zapisu w następujących katalogach:
+Aby działały niektóre internetowe narzędzia administracyjne, serwer WWW musi mieć możliwość zapisu w następujących katalogach:
-* `addon`
-* `extend`
-* `view/theme`
-* `widget`
+* _addon_
+* _extend_
+* _view/theme_
+* _widget_
##### Krok 2.
-Utwórz pustą bazę danych i zanotuj szczegóły dostępu (nazwa hosta, nazwa
-użytkownika, hasło, nazwa bazy danych). Biblioteki bazy danych PDO powracają do
-komunikacji przez gniazdo uniksowe, gdy nazwą hosta jest `localhost`, ale
-niektóre osoby zgłosiły problemy z implementacją gniazda. Użyj gniazd, jeśli
-Twoje uprawnienia na to pozwalają. W przeciwnym razie, jeśli baza danych jest
-udostępniana na hoście `localhost`, jako nazwę hosta wpisz `127.0.0.1`.
+Utwórz pustą bazę danych i zanotuj szczegóły dostępu (nazwa hosta, nazwa użytkownika, hasło, nazwa bazy danych). Biblioteki bazy danych PDO powracają do komunikacji przez gniazdo uniksowe, gdy nazwą hosta jest _localhost_, ale niektóre osoby zgłosiły problemy z implementacją gniazda. Użyj gniazd, jeśli Twoje uprawnienia na to pozwalają. W przeciwnym razie, jeśli baza danych jest udostępniana na hoście _localhost_, jako nazwę hosta wpisz _127.0.0.1_.
-Wewnętrznie używamy teraz biblioteki PDO do połączeń z bazą danych. Jeśli masz
-do czynienia z konfigyracją bazy danych, którą nie możesz obsłużyć poprzez
-formularz konfiguracyjny (ma przykład w przypadku uzywania MySQL z nietypową
-lokalizacją gniazd) - możesz podać ciąg połączenia PDO jako nazwę hosta.
-Na przykład:
+Wewnętrznie używamy teraz biblioteki PDO do połączeń z bazą danych. Jeśli masz do czynienia z konfigyracją bazy danych, którą nie możesz obsłużyć poprzez formularz konfiguracyjny (ma przykład w przypadku uzywania MySQL z nietypową lokalizacją gniazd) - możesz podać ciąg połączenia PDO jako nazwę hosta. Na przykład:
:/path/to/socket.file
-W razie potrzeby nadal trzeba wypełnić w formularzu konfiguracyjnym wszystkie
-inne wartości mające zastosowanie.
+W razie potrzeby nadal trzeba wypełnić w formularzu konfiguracyjnym wszystkie inne wartości mające zastosowanie.
##### Krok 3.
-Utwórz pusty plik o nazwie `.htconfig.php` i uczyń go możliwymm do zapisania
-przez serwer WWW. Krok ten wykonaj, jeśli wiesz, że serwer WWW nie będzie
-mógł sam utworzyć tego pliku.
+Utwórz pusty plik o nazwie _.htconfig.php_ i uczyń go możliwymm do zapisania przez serwer WWW. Krok ten wykonaj, jeśli wiesz, że serwer WWW nie będzie mógł sam utworzyć tego pliku.
##### Krok 4.
-Odwiedź swoją witrynę za pomocą przeglądarki internetowej i postępuj zgodnie z
-instrukcjami. Zanotuj wszelkie komunikaty o błędach i popraw je przed
-kontynuowaniem. Jeśli używasz protokołu SSL (od znanego urzędu autoryzacyjnego),
-użyj schematu `https` w adresie URL swojej witryny.
+Odwiedź swoją witrynę za pomocą przeglądarki internetowej i postępuj zgodnie z instrukcjami. Zanotuj wszelkie komunikaty o błędach i popraw je przed kontynuowaniem. Jeśli używasz protokołu SSL (od znanego urzędu autoryzacyjnego), użyj schematu _https_ w adresie URL swojej witryny.
##### Krok 5.
-Jeśli automatyczna instalacja nie powiedzie się z jakiegoś powodu,
-sprawdź następujące rzeczy:
+Jeśli automatyczna instalacja nie powiedzie się z jakiegoś powodu, sprawdź następujące rzeczy:
-* Czy istnieje plik `.htconfig.php`? Jeśli nie, edytuj plik `htconfig.php`
- i zmień w nim ustawienia systemowe. Następnie zmień jego nazwę na .htconfig.php.
-* Czy baza danych jest wypełniona. Jeśli nie, zaimportuj treść skryptu
- `install/schema_xxxxx.sql` w phpmyadmin lub wierszu poleceń mysql (zamień
- 'xxxxx' na własciwy typ bazy danych).
+* Czy istnieje plik _.htconfig.php_? Jeśli nie, edytuj plik _htconfig.php_ i zmień w nim ustawienia systemowe. Następnie zmień jego nazwę na _.htconfig.php_.
+* Czy baza danych jest wypełniona. Jeśli nie, zaimportuj treść skryptu _install/schema_xxxxx.sql_ w phpmyadmin lub wierszu poleceń mysql (zamień 'xxxxx' na własciwy typ bazy danych).
##### Krok 6.
-Po udanej instalacji odwiedż ponownie swoją witrynę i zarejestruj swoje osobiste
-konto. Błędy rejestracji powinny dać sie naprawić automatycznie.
+Po udanej instalacji odwiedż ponownie swoją witrynę i zarejestruj swoje osobiste konto. Błędy rejestracji powinny dać sie naprawić automatycznie.
-Jeśli w tym momencie wystąpiła jakakolwiek *krytyczna* awaria, to na ogół
-przyczyna leży w źle funkcjonującej bazie danych. W takim przypadku, aby zacząć
-od nowa, usuń lub zmień nazwę pliku `.htconfig.php` i usuń tabele bazy danych.
+Jeśli w tym momencie wystąpiła jakakolwiek *krytyczna* awaria, to na ogół przyczyna leży w źle funkcjonującej bazie danych. W takim przypadku, aby zacząć od nowa, usuń lub zmień nazwę pliku _.htconfig.php_ i usuń tabele bazy danych.
-Aby Twoje konto miało dostęp administratora, powinno to być utworzone jako
-pierwsze, a adres e-mail podany podczas rejestracji musi być zgodny z adresem
-administratora podanym podczas instalacji. Jeśli stało sie inaczej, aby dać
-dostęp administracyjny jakiemuś kontu, dodaj `4096` w rekordzie tabeli
-`account_roles` tego konta.
+Aby Twoje konto miało dostęp administratora, powinno to być utworzone jako pierwsze, a adres e-mail podany podczas rejestracji musi być zgodny z adresem administratora podanym podczas instalacji. Jeśli stało sie inaczej, aby dać dostęp administracyjny jakiemuś kontu, dodaj _4096_ w rekordzie tabeli _account_roles_ tego konta.
-Ze względu na bezpieczeństwo witryny, nie ma możliwości zapewnienia dostępu
-administracyjnego za pomocą formularzy konfiguracyjnych.
+Ze względu na bezpieczeństwo witryny, nie ma możliwości zapewnienia dostępu administracyjnego za pomocą formularzy konfiguracyjnych.
##### Krok 7. BARDZO WAŻNY!
-Skonfiguruj zadanie Crona lub *zadanie zaplanowane*, tak aby uruchamiać menedżera
-Crona co 10-15 minut w celu przetwarzania i konserwacji w tle. Przykład:
+Skonfiguruj zadanie Crona lub *zadanie zaplanowane*, tak aby uruchamiać menedżera Crona co 10-15 minut w celu przetwarzania i konserwacji w tle. Przykład:
cd /base/directory; /path/to/php Zotlabs/Daemon/Master.php Cron
Zmień tutaj `/base/directory` i `/path/to/php` na właściwe dla siebie ścieżki.
-Jeśli używasz serwera linuksowego, uruchom polecenie `crontab -e` i dodaj wiersz
-taki jak poniżej, zmieniając odpowiednio ścieżki i ustawienia:
+Jeśli używasz serwera linuksowego, uruchom polecenie `crontab -e` i dodaj wiersz taki jak poniżej, zmieniając odpowiednio ścieżki i ustawienia:
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php Zotlabs/Daemon/Master.php Cron > /dev/null 2>&1
-Lokalizację PHP na ogół można ustalić wykonując polecenie `which php`. Jeśli
-masz problemy z ustawienie Crona, skontaktuj się z dostawcą hostingu w celu
-uzyskania pomocy. Hubzilla nie będzie działać prawidłowo bez tego kroku.
+Lokalizację PHP na ogół można ustalić wykonując polecenie _which php_. Jeśli masz problemy z ustawienie Crona, skontaktuj się z dostawcą hostingu w celu uzyskania pomocy. Hubzilla nie będzie działać prawidłowo bez tego kroku.
-Powinno się również sprawdzić ustawienie parametru
-`App::$config['system']['php_path']` w pliku `.htconfig.php`.
-Powinno to wyglądać tak (zmień to zgodnie z lokalizacją PHP w swoim systemie):
+Powinno się również sprawdzić ustawienie parametru _App::$config['system']['php_path']_ w pliku _.htconfig.php_. Powinno to wyglądać tak (zmień to zgodnie z lokalizacją PHP w swoim systemie):
App::$config['system']['php_path'] = '/usr/local/php56/bin/php';
@@ -228,39 +144,30 @@ Powinno to wyglądać tak (zmień to zgodnie z lokalizacją PHP w swoim systemie
##### Instalacja
-Przejdź do swojej witryny. Następnie sklonuj repozytorium dodatków (osobno).
-Nadamy temu repozytorium pseudonim `hzaddons`. Możesz pobrać inne repozytoria
-dodatków Hubzilla, nadając im różne pseudonimy:
+Przejdź do swojej witryny. Następnie sklonuj repozytorium dodatków (osobno). Nadamy temu repozytorium pseudonim `hzaddons`. Możesz pobrać inne repozytoria dodatków Hubzilla, nadając im różne pseudonimy:
cd mywebsite
util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons
##### Aktualizacja
-W celu aktualizacji drzewa dodatków, powinno się, z poziomu głównego katalogu
-witryny, wydać polecenie aktualizacji tego repozytorium:
+W celu aktualizacji drzewa dodatków, powinno się, z poziomu głównego katalogu witryny, wydać polecenie aktualizacji tego repozytorium:
cd mywebsite
util/update_addon_repo hzaddons
-Stwórz reprezentację dokumentacji online z możliwością wyszukiwania. Możesz to
-zrobić za każdym razem, gdy dokumentacja jest aktualizowana:
+Stwórz reprezentację dokumentacji online z możliwością wyszukiwania. Możesz to zrobić za każdym razem, gdy dokumentacja jest aktualizowana:
cd mywebsite
util/importdoc
### Automatyczna instalacja poprzez skrypt .homeinstall
-Istnieje skrypt powłoki `.homeinstall/hubzilla-setup.sh`, który po
-uruchomieniu zainstaluje Hubzillę i jego zależności na nowej instalacji stabilnej
-dystrybucji Debiana 9 (Stetch). Powinien działać na podobnych systemach Linux,
-ale wyniki mogą się różnić.
+Istnieje skrypt powłoki _.homeinstall/hubzilla-setup.sh_, który po uruchomieniu zainstaluje Hubzillę i jego zależności na nowej instalacji stabilnej dystrybucji Debiana 9 (Stetch). Powinien działać na podobnych systemach Linux, ale wyniki mogą się różnić.
#### Wymagania
-Skrypt instalacyjny został pierwotnie zaprojektowany dla małego serwera
-sprzętowego za routerem domowym. Jednak został przetestowany też na kilku
-systemach z Debian 9:
+Skrypt instalacyjny został pierwotnie zaprojektowany dla małego serwera sprzętowego za routerem domowym. Jednak został przetestowany też na kilku systemach z Debian 9:
* Home-PC (Debian-9.2-amd64) i Rapberry-Pi 3 (Rasbian = Debian 9.3)
* Połączenie z Internetem i domowy router
@@ -270,14 +177,15 @@ systemach z Debian 9:
* Router z otwartymi portami 80 i 443 dla Debiana
#### Etapy instalacji
-1. `apt-get install git`
-1. `mkdir -p /var/www/html`
-1. `cd /var/www/html`
-1. `git clone https://framagit.org/hubzilla/core.git .`
-1. `nano .homeinstall/hubzilla-config.txt`
-1. `cd .homeinstall/`
-1. `./hubzilla-setup.sh`
-1. `service apache2 reload`
+
+1. _apt-get install git_
+1. _mkdir -p /var/www/html_
+1. _cd /var/www/html_
+1. _git clone https://framagit.org/hubzilla/core.git ._
+1. _nano .homeinstall/hubzilla-config.txt_
+1. _cd .homeinstall/_
+1. _./hubzilla-setup.sh_
+1. _service apache2 reload_
1. Open your domain with a browser and step throught the initial configuration of $Projectname.
### Zalecane dodatki
@@ -289,31 +197,15 @@ Zalecamy zainstalowanie następujących dodatków we wszystkich publicznych witr
### Dodatki federacyjne
-Kilka społeczności internetowych zaczęło łączyć się przy użyciu wspólnych
-protokołów. Stosowane protokoły mają nieco ograniczone możliwości. Na przykład
-protokół GNU-Social nie oferuje żadnych trybów prywatności, a protokół Diaspora
-jest nieco bardziej restrykcyjny w zakresie dozwolonych rodzajów komunikacji.
-Wszystkie komentarze muszą być podpisane w bardzo unikalny sposób przez
-oryginalnego autora. Rozważany jest również protokół ActivityPub, który może być
-obsługiwany w przyszłości. Żaden inny istniejący protokół nie obsługuje
-lokalizacji nomadycznej używanej w tym projekcie. Stwarza to pewne problemy z
-obsługą, ponieważ niektóre funkcje działają w niektórych sieciach, a w innych nie.
-Niemniej jednak protokoły federacyjne umożliwiają nawiązywanie połączeń ze znacznie
-większą społecznością ludzi na całym świecie. Są dostarczane jako dodatki.
-
-* _diaspora_ - protokół diaspory używany przez Diasporę i Friendica. Najpierw
- należy włączyć „Diaspora Statistics” (statystyki), aby włączyć wszystkie
- dostępne funkcje.
-
-* _gnusoc_ - protokół społecznościowy GNU, używany przez GNU-Social, Mastodon i
- kilka innych społeczności. Ten dodatek wymaga najpierw zainstalowania usługi
- `pubsubhubbub` (także dodatku).
-
-Każdy członek Twojej siatki musi indywidualnie zdecydować, czy zezwolić na te
-protokoły, ponieważ mogą one kolidować z kilkoma pożądanymi podstawowymi funkcjami
-i możliwościami Hubzilla (takimi jak migracja kanałów i klonowanie). Robi się to
-na swojej stronie _Ustawienia_ -> _Ustawienia funkcji i dodatków_. Administrator
-może również ustawić:
+Kilka społeczności internetowych zaczęło łączyć się przy użyciu wspólnych protokołów. Stosowane protokoły mają nieco ograniczone możliwości. Na przykład protokół GNU-Social nie oferuje żadnych trybów prywatności, a protokół Diaspora
+jest nieco bardziej restrykcyjny w zakresie dozwolonych rodzajów komunikacji. Wszystkie komentarze muszą być podpisane w bardzo unikalny sposób przez oryginalnego autora. Rozważany jest również protokół ActivityPub, który może być obsługiwany w przyszłości. Żaden inny istniejący protokół nie obsługuje lokalizacji nomadycznej używanej w tym projekcie. Stwarza to pewne problemy z obsługą, ponieważ niektóre funkcje działają w niektórych sieciach, a w innych nie. Niemniej jednak protokoły federacyjne umożliwiają nawiązywanie połączeń ze znacznie większą społecznością ludzi na całym świecie. Są dostarczane jako dodatki.
+
+* _diaspora_ - protokół diaspory używany przez Diasporę i Friendica. Najpierw należy włączyć „Diaspora Statistics” (statystyki), aby włączyć wszystkie dostępne funkcje.
+
+* _gnusoc_ - protokół społecznościowy GNU, używany przez GNU-Social, Mastodon i kilka innych społeczności. Ten dodatek wymaga najpierw zainstalowania usługi _pubsubhubbub_ (także dodatku).
+
+Każdy członek Twojej siatki musi indywidualnie zdecydować, czy zezwolić na te protokoły, ponieważ mogą one kolidować z kilkoma pożądanymi podstawowymi funkcjami i możliwościami Hubzilla (takimi jak migracja kanałów i klonowanie). Robi się to
+na swojej stronie _Ustawienia_ -> _Ustawienia funkcji i dodatków_. Administrator może również ustawić:
util/config system.diaspora_allowed 1
util/config system.gnusoc_allowed 1
@@ -322,11 +214,7 @@ i włączać te protokoły automatycznie dla wszystkich nowo tworzonych kanałó
### Klasy usług
-Klasy usług pozwalają na ustawienie limitów zasobów systemowych poprzez
-ograniczenie tego, co mogą robić poszczególne konta, w tym przechowywania plików
-i najwyższych limitów wpisów. Zdefiniuj niestandardowe klasy usług zgodnie ze
-swoimi potrzebami w pliku `.htconfig.php`. Na przykład utwórz klasę standard
-i premium, używając następujących wierszy:
+Klasy usług pozwalają na ustawienie limitów zasobów systemowych poprzez ograniczenie tego, co mogą robić poszczególne konta, w tym przechowywania plików i najwyższych limitów wpisów. Zdefiniuj niestandardowe klasy usług zgodnie ze swoimi potrzebami w pliku _.htconfig.php_. Na przykład utwórz klasę standard i premium, używając następujących wierszy:
// Service classes
@@ -352,49 +240,48 @@ i premium, używając następujących wierszy:
'attach_upload_limit' =>20000000000, // total attachment storage limit per channel (here 20GB)
'chatters_inroom' =>100);
-Aby zastosować klasę usług do istniejącego konta, użyj narzędzia wiersza poleceń
-z katalogu głównego instalacji Hubzilla:
+Aby zastosować klasę usług do istniejącego konta, użyj narzędzia wiersza poleceń z katalogu głównego instalacji Hubzilla:
* uzyskanie listy klas usług:
util/service_class
-* ustawienie domyślnej klasy usług na `firstclass`:
+* ustawienie domyślnej klasy usług na _firstclass_:
util/config system default_service_class firstclass
-* uzyskanie listy usług, które należą do klasy `firstclass`:
+* uzyskanie listy usług, które należą do klasy _firstclass_:
util/service_class firstclass
-* ustawienie całkowitego użycia dysku ze zdjęciami `firstclass` na 10 milionów bajtów
+* ustawienie całkowitego użycia dysku ze zdjęciami _firstclass_ na 10 milionów bajtów
util/service_class firstclass photo_upload_limit 10000000
-* ustawienie konta z identyfikatorem 5 na klasę `firstclass` (z potwierdzeniem):
+* ustawienie konta z identyfikatorem 5 na klasę _firstclass_ (z potwierdzeniem):
util/service_class --account=5 firstclass
-* ustawienie konta, które jest właścicielem kanału `bdziennikchan` na klasę `firstclass` (z potwierdzeniem)
+* ustawienie konta, które jest właścicielem kanału `bdziennikchan` na klasę _firstclass_ (z potwierdzeniem)
util/service_class --channel=bdziennikchan firstclass
-**Service class limit options**
+**Opcje limitu klas usług**
##### Opcje limitów klas usług:
-* `photo_upload_limit` - maksymalna łączna liczba bajtów na zdjęcia
-* `total_items` - maksymalna liczba wpisów na najwyższym poziomie
-* `total_pages` - maksymalna liczba stron comanche
-* `total_identities` - maksymalna liczba kanałów posiadanych na koncie
-* `total_channels` - maksymalna liczba kanałów
-* `total_feeds` - maksymalna liczba kanałów RSS
-* `attach_upload_limit` - maksymalna pojemność przesyłania plików (w bajtach)
-* `minimum_feedcheck_minutes` - najniższe ustawienie dozwolone dla odpytywania kanałów RSS
-* `chatrooms` - maksymalna liczba czatów
-* `chatters_inroom` - maksymalna liczba rozmówców w czacie
-* `access_tokens` - maksymalna liczba tokenów dostępu gościa na kanał
+* _photo_upload_limit_ - maksymalna łączna liczba bajtów na zdjęcia
+* _total_items_ - maksymalna liczba wpisów na najwyższym poziomie
+* _total_pages_ - maksymalna liczba stron comanche
+* _total_identities_ - maksymalna liczba kanałów posiadanych na koncie
+* _total_channels_ - maksymalna liczba kanałów
+* _total_feeds_ - maksymalna liczba kanałów RSS
+* _attach_upload_limit_ - maksymalna pojemność przesyłania plików (w bajtach)
+* _minimum_feedcheck_minutes_ - najniższe ustawienie dozwolone dla odpytywania kanałów RSS
+* _chatrooms_ - maksymalna liczba czatów
+* _chatters_inroom_ - maksymalna liczba rozmówców w czacie
+* _access_tokens_ - maksymalna liczba tokenów dostępu gościa na kanał
### Zarządzanie motywami
@@ -421,15 +308,11 @@ z katalogu głównego instalacji Hubzilla:
#### Słowa kluczowe
-Na stronie katalogu kanałów może pojawiać się „chmura tagów” słów kluczowych.
-Jeśli chcesz ukryć te słowa kluczowe, które są pobierane z serwera katalogów,
-możesz użyć narzędzia `config`:
+Na stronie katalogu kanałów może pojawiać się chmura słów kluczowych. Jeśli chcesz ukryć te słowa kluczowe, które są pobierane z serwera katalogów, możesz użyć narzędzia _config_:
util/config system disable_directory_keywords 1
-Jeśli twój hub pracuje w trybie autonomicznym, ponieważ nie chcesz łączyć się
-z globalną siecią, możesz zamiast tego ustawić opcję systemową `directory_server`
-na wartość pustą:
+Jeśli twój hub pracuje w trybie autonomicznym, ponieważ nie chcesz łączyć się z globalną siecią, możesz zamiast tego ustawić opcję systemową _directory_server_ na wartość pustą:
util/config system directory_server ""
@@ -437,131 +320,53 @@ na wartość pustą:
#### Administrowanie witryną
-Administracja witryną jest zwykle wykonywana za pośrednictwem strony administratora
-znajdującej się na ścieżce `/admin` adresu URL Twojej witryny. Aby uzyskać dostęp
-do tej strony, trzeba mieć uprawnienia administratora na serwerze. Prawa
-administracyjne są przyznawane pierwszemu kontu, które zostało zarejestrowane w
-witrynie, pod warunkiem, że adres e-mail tego konta dokładnie odpowiada adresowi
-e-mail podanemu jako adres e-mail administratora podczas konfiguracji.
-
-Istnieje kilka sposobów, w jakie może to się nie powieść i pozostawić system bez
-konta administratora, na przykład jeśli pierwsze konto, które zostało utworzone,
-miało inny adres e-mail niż adres e-mail administratora, który został podany
-podczas konfiguracji.
-
-Ze względów bezpieczeństwa w systemie nie ma strony internetowej ani interfejsu,
-który daje dostęp administratora. Jeśli potrzebujesz poprawić sytuację, w której
-system nie ma konta administratora, musisz to zrobić edytując tabelę kont w bazie
-danych. Nie ma innego wyjścia. Aby to zrobić, będziesz musiał zlokalizować wpis
-w tabeli kont, który należy do żądanego administratora i ustawić `account_roles`
-dla tego wpisu na `4096`. Będziesz wtedy mógł uzyskać dostęp do strony
-administratora z menu profilu twojego systemu lub bezpośrednio na ścieżce `/admin`.
-
-Hub może mieć wielu administratorów i nie ma ograniczeń co do ich liczby.
-Powtórz powyższą procedurę dla każdego konta, któremu chcesz przyznać uprawnienia
-administracyjne.
+Administracja witryną jest zwykle wykonywana za pośrednictwem strony administratora znajdującej się na ścieżce _/admin_ adresu URL Twojej witryny. Aby uzyskać dostęp do tej strony, trzeba mieć uprawnienia administratora na serwerze. Prawa administracyjne są przyznawane pierwszemu kontu, które zostało zarejestrowane w witrynie, pod warunkiem, że adres e-mail tego konta dokładnie odpowiada adresowi e-mail podanemu jako adres e-mail administratora podczas konfiguracji.
+
+Istnieje kilka sposobów, w jakie może to się nie powieść i pozostawić system bez konta administratora, na przykład jeśli pierwsze konto, które zostało utworzone, miało inny adres e-mail niż adres e-mail administratora, który został podany podczas konfiguracji.
+
+Ze względów bezpieczeństwa w systemie nie ma strony internetowej ani interfejsu, który daje dostęp administratora. Jeśli potrzebujesz poprawić sytuację, w której system nie ma konta administratora, musisz to zrobić edytując tabelę kont w bazie danych. Nie ma innego wyjścia. Aby to zrobić, będziesz musiał zlokalizować wpis w tabeli kont, który należy do żądanego administratora i ustawić _account_roles_ dla tego wpisu na _4096_. Będziesz wtedy mógł uzyskać dostęp do strony administratora z menu profilu twojego systemu lub bezpośrednio na ścieżce _/admin_.
+
+Hub może mieć wielu administratorów i nie ma ograniczeń co do ich liczby. Powtórz powyższą procedurę dla każdego konta, któremu chcesz przyznać uprawnienia administracyjne.
### Rozwiązywanie problemów
#### Pliki dzienników
-Plik dziennika systemowego jest niezwykle przydatnym źródłem informacji do
-śledzenia błędów. Można to włączyć na stronie konfiguracji `admin/dziennik`.
-Ustawienie poziomu o wartości `dziennikGER_DEBUG` jest preferowany w stabilnej
-instalacji produkcyjnej. Większość problemów związanych z komunikacją lub
-przechowywaniem jest tutaj wymieniona. Ustawienie na `dziennikGER_DATA`
-zapewnia znacznie więcej szczegółów, ale może wypełnić dysk. W obu przypadkach
-zalecamy użycie `dziennikrotate` w systemie operacyjnym do cyklicznego tworzenia
-dzienników i usuwania starszych wpisów.
-
-Na dole twojego `.htconfig.php` znajduje się kilka linii (zakomentowanych),
-które umożliwiają rejestrowanie błędów PHP. Zgłaszane są problemy ze składnią i
-wykonywaniem kodu i jest to też pierwszym miejscem, w którym należy szukać
-problemów, które powodują "biały ekran" lub pustą stronę. Zwykle jest to wynikiem
-problemów z kodem lub składnią. Błędy bazy danych są zgłaszane do pliku dziennika
-systemowego, ale uznaliśmy, że przydatne jest umieszczenie w katalogu najwyższego
-poziomu pliku `dbfail.out`, który gromadzi tylko informacje o problemach
-związanych z bazą danych. Jeśli plik istnieje i można go zapisać, będą rejestrowane
-w nim błędy bazy danych, a także w pliku dziennika systemowego.
-
-W przypadku błędów "500: problemy mogą być często rejestrowane w dziennikach
-serwera internetowego, często w `/var/dziennik/apache2/error.dziennik` lub
-podobnym. Zapoznaj się z dokumentacją systemu operacyjnego.
+Plik dziennika systemowego jest niezwykle przydatnym źródłem informacji do śledzenia błędów. Można to włączyć na stronie konfiguracji _admin/log_. Ustawienie poziomu o wartości *LOGGER_DEBUG* jest preferowany w stabilnej instalacji produkcyjnej. Większość problemów związanych z komunikacją lub przechowywaniem jest tutaj wymieniona. Ustawienie na *LOGGER_DATA* zapewnia znacznie więcej szczegółów, ale może wypełnić dysk. W obu przypadkach zalecamy użycie *logrotate* w systemie operacyjnym do cyklicznego tworzenia dzienników i usuwania starszych wpisów.
+
+Na dole twojego *.htconfig.php* znajduje się kilka linii (zakomentowanych), które umożliwiają rejestrowanie błędów PHP. Zgłaszane są problemy ze składnią i wykonywaniem kodu i jest to też pierwszym miejscem, w którym należy szukać problemów, które powodują "biały ekran" lub pustą stronę. Zwykle jest to wynikiem problemów z kodem lub składnią. Błędy bazy danych są zgłaszane do pliku dziennika systemowego, ale uznaliśmy, że przydatne jest umieszczenie w katalogu najwyższego poziomu pliku *dbfail.out*, który gromadzi tylko informacje o problemach związanych z bazą danych. Jeśli plik istnieje i można go zapisać, będą rejestrowane w nim błędy bazy danych, a także w pliku dziennika systemowego.
+
+W przypadku błędów "500: problemy mogą być często rejestrowane w dziennikach serwera internetowego, często w */var/log/apache2/error.log* lub podobnym. Zapoznaj się z dokumentacją systemu operacyjnego.
Istnieją trzy różne obiekty dziennika.
-**Pierwsza to dziennik błędów bazy danych**. Jest on używane tylko wtedy, gdy
-tworzy ssię plik o specyficznej nazwie `dbfail.out` w folderze głównym swojej
-witryny i pozwala się na zapisywanie w nim przez serwer WWW. Jeśli masz
-jakiekolwiek zapytania do bazy danych, które nie powiodły się, wszystkie są
-zgłaszane tutaj. Zwykle wskazują na literówki w naszych zapytaniach, ale występują
-również w przypadku rozłączenia serwera bazy danych lub uszkodzenia tabel.
-W rzadkich przypadkach zobaczymy tutaj warunki wyścigu, w których dwa procesy
-próbowały utworzyć wpis `xchan` lub `cache`z tym samym identyfikatorem. Należy
-zbadać wszelkie inne błędy (zwłaszcza błędy uporczywe).
-
-**Drugi to dziennik błędów PHP**. Jest tworzony przez procesor języka i zgłasza
-tylko problemy powstałe w środowisku językowym. Znowu mogą to być błędy składniowe
-lub błędy programistyczne, ale generalnie są one fatalne i skutkują "białym ekranem";
-na przykład PHP kończy działanie. Prawdopodobnie powinieneś zajrzeć do tego pliku
-też, jeśli coś pójdzie nie tak, co nie powoduje białego ekranu. Często zdarza się,
-że plik ten jest pusty przez wiele dni.
-
-Na dole dostarczonego pliku `.htconfig.php` znajduje się kilka linii, które,
-jeśli nie są zakomentowane, włączają dziennik PHP (niezwykle przydatny do
-znajdowania źródła błędów białego ekranu). Nie jest to robione domyślnie ze względu
-na potencjalne problemy z własnością pliku dziennika i uprawnieniami do zapisu
-oraz fakt, że domyślnie nie ma rotacji pliku dziennika.
-
-**Trzeci to "dziennik aplikacji"**. Jest to używane przez Hubzillę do zgłaszania
-tego, co dzieje się w programie i zwykle zapisywane są tu wszelkie trudności lub
-nieoczekiwane dane, które otrzymaliśmy. Czasami zgłasza się tu również komunikaty
-o stanie "pulsu", aby wskazać, że osiągnęliśmy określony punkt w skrypcie. Jest
-to dla nas najważniejszy plik dziennika, ponieważ tworzymy go samodzielnie
-wyłącznie w celu zgłaszania stanu zadań w tle i wszystkiego, co wydaje się dziwne
-lub nie na miejscu. To może nie być śmiertelne, ale może po prostu nieoczekiwane.
-Jeśli wykonujesz zadanie i występuje problem, daj nam znać, co znajduje się w tym
-pliku, gdy wystąpił problem. Proszę nie wysyłaj mi 100 milionów zrzutów, tylko
-mnie wkurzysz! Tylko kilka odpowiednich wierszy, abym mógł wykluczyć kilkaset
-tysięcy wierszy kodu i skoncentrować się na tym, gdzie zaczyna się pojawiać
-problem.
-
-To są dzienniki Twojej witryny, a nie moje. Zgłaszamy poważne problemy na każdym
-poziomie dziennika. Gorąco polecam poziom dziennika `DEBUG` dla większości witryn.
-Dostarcza on trochę dodatkowych informacji i nie tworzy dużych plików dziennika.
-Kiedy pojawia się problem, który uniemożliwia wszelkie próby śledzenia, możesz
-wtedy włączyć na krótki czas poziom `DATA`, aby uchwycić wszystkie szczegóły
-struktur, z którymi mieliśmy do czynienia w tym czasie. Ten poziom dziennika
-zajmuje dużo miejsca, więc jest zalecany tylko na krótkie okresy lub w przypadku
-witryn testowych dla programistów.
-
-Zalecam skonfigurowanie `logrotate` zarówno dla dziennika php, jak i dziennika
-aplikacji. Zazwyczaj co tydzień lub dwa zaglądam do `dbfail.out`, naprawiam
-zgłoszone problemy i zaczynam od nowego pliku. Podobnie jest z plikiem dziennika
-PHP. Odwołuję się do tego od czasu do czasu, aby sprawdzić, czy jest coś, co
-wymaga naprawy.
-
-Jeśli coś pójdzie nie tak i nie jest to błąd krytyczny, patrzę na plik dziennika
-aplikacji. Często robię to:
+**Pierwsza to dziennik błędów bazy danych**. Jest on używane tylko wtedy, gdy tworzy się plik o specyficznej nazwie *dbfail.out* w folderze głównym swojej witryny i pozwala na zapisywanie w nim przez serwer WWW. Jeśli masz jakiekolwiek zapytania do bazy danych, które nie powiodły się, wszystkie są zgłaszane tutaj. Zwykle wskazują na literówki w naszych zapytaniach, ale występują również w przypadku rozłączenia serwera bazy danych lub uszkodzenia tabel. W rzadkich przypadkach zobaczymy tutaj warunki wyścigu, w których dwa procesy próbowały utworzyć wpis *xchan* lub *cache* z tym samym identyfikatorem. Należy zbadać wszelkie inne błędy (zwłaszcza błędy uporczywe).
+
+**Drugi to dziennik błędów PHP**. Jest tworzony przez procesor języka i zgłasza tylko problemy powstałe w środowisku językowym. Znowu mogą to być błędy składniowe lub błędy programistyczne, ale generalnie są one fatalne i skutkują "białym ekranem";
+na przykład PHP kończy działanie. Prawdopodobnie powinieneś zajrzeć do tego pliku też, jeśli coś pójdzie nie tak, co nie powoduje białego ekranu. Często zdarza się, że plik ten jest pusty przez wiele dni.
+
+Na dole dostarczonego pliku *.htconfig.php* znajduje się kilka linii, które, jeśli nie są zakomentowane, włączają dziennik PHP (niezwykle przydatny do znajdowania źródła błędów białego ekranu). Nie jest to robione domyślnie ze względu na potencjalne problemy z własnością pliku dziennika i uprawnieniami do zapisu oraz fakt, że domyślnie nie ma rotacji pliku dziennika.
+
+**Trzeci to "dziennik aplikacji"**. Jest to używane przez Hubzillę do zgłaszania tego, co dzieje się w programie i zwykle zapisywane są tu wszelkie trudności lub nieoczekiwane dane, które otrzymaliśmy. Czasami zgłasza się tu również komunikaty
+o stanie "pulsu", aby wskazać, że osiągnęliśmy określony punkt w skrypcie. Jest to dla nas najważniejszy plik dziennika, ponieważ tworzymy go samodzielnie wyłącznie w celu zgłaszania stanu zadań w tle i wszystkiego, co wydaje się dziwne lub nie na miejscu. To może nie być śmiertelne, ale może po prostu nieoczekiwane. Jeśli wykonujesz zadanie i występuje problem, daj nam znać, co znajduje się w tym pliku, gdy wystąpił problem. Proszę nie wysyłaj mi 100 milionów zrzutów, tylko mnie wkurzysz! Tylko kilka odpowiednich wierszy, abym mógł wykluczyć kilkaset tysięcy wierszy kodu i skoncentrować się na tym, gdzie zaczyna się pojawiać problem.
+
+To są dzienniki Twojej witryny, a nie moje. Zgłaszamy poważne problemy na każdym poziomie dziennika. Gorąco polecam poziom dziennika *DEBUG* dla większości witryn. Dostarcza on trochę dodatkowych informacji i nie tworzy dużych plików dziennika. Kiedy pojawia się problem, który uniemożliwia wszelkie próby śledzenia, możesz wtedy włączyć na krótki czas poziom *DATA*, aby uchwycić wszystkie szczegóły struktur, z którymi mieliśmy do czynienia w tym czasie. Ten poziom dziennika zajmuje dużo miejsca, więc jest zalecany tylko na krótkie okresy lub w przypadku witryn testowych dla programistów.
+
+Zalecam skonfigurowanie *logrotate* zarówno dla dziennika php, jak i dziennika aplikacji. Zazwyczaj co tydzień lub dwa zaglądam do *dbfail.out*, naprawiam zgłoszone problemy i zaczynam od nowego pliku. Podobnie jest z plikiem dziennika PHP. Odwołuję się do tego od czasu do czasu, aby sprawdzić, czy jest coś, co wymaga naprawy.
+
+Jeśli coś pójdzie nie tak i nie jest to błąd krytyczny, patrzę na plik dziennika aplikacji. Często robię to:
```
tail -f logfile.out
```
-ponieważ powtarza operację, która ma problemy. Często wstawiam w kodzie dodatkowe
-instrukcje logowania, jeśli nie ma żadnej wskazówki, co się dzieje. Nawet coś tak
-prostego jak "got here" lub drukuję wartości zmiennej, która może być podejrzana.
-Ty też możesz to zrobić - wręcz zachęcam Cię do tego. Gdy już znajdziesz to, czego
-potrzebujesz, możesz wykonać:
+ponieważ powtarza operację, która ma problemy. Często wstawiam w kodzie dodatkowe instrukcje rejestracji, jeśli nie ma żadnej wskazówki, co się dzieje. Nawet coś tak prostego jak "got here" lub drukuję wartości zmiennej, która może być podejrzana. Ty też możesz to zrobić - wręcz zachęcam Cię do tego. Gdy już znajdziesz to, czego potrzebujesz, możesz wykonać:
```
git checkout file.php
```
-aby natychmiast wyczyścić wszystkie dodane elementy rejestrowania. Skorzystaj z
-informacji z tego dziennika i wszelkich szczegółów, które możesz podać podczas
-badania problemu, aby zgłosić błąd - chyba że analiza wskazuje na źródło problemu.
-W takim przypadku po prostu to napraw.
+aby natychmiast wyczyścić wszystkie dodane elementy rejestrowania. Skorzystaj z informacji z tego dziennika i wszelkich szczegółów, które możesz podać podczas badania problemu, aby zgłosić błąd - chyba że analiza wskazuje na źródło problemu. W takim przypadku po prostu to napraw.
##### Rotowanie plików dziennika
@@ -571,23 +376,10 @@ W takim przypadku po prostu to napraw.
#### Zgłaszanie problemów
-Zgłaszając problemy, staraj się podać jak najwięcej szczegółów, które mogą być
-potrzebne programistom do odtworzenia problemu i podać pełny tekst wszystkich
-komunikatów o błędach.
-
-Zachęcamy do dołożenia wszelkich starań, aby wykorzystać te dzienniki w połączeniu
-z posiadanym kodem źródłowym w celu rozwiązywania problemów i znajdowania ich
-przyczyn. Społeczność często jest w stanie pomóc, ale tylko Ty masz dostęp do
-plików dziennika swojej witryny i ich udostępnianie jest uważane za zagrożenie
-bezpieczeństwa.
-
-Jeśli problem z kodem został odkryty, zgłoś go w bugtrackerze projektu
-(https://framagit.org/hubzilla/core/issues). Ponownie podaj jak najwięcej szczegółów,
-aby uniknąć ciągłego zadawania pytań o konfigurację lub powielanie problemu,
-abyśmy mogli przejść od razu do problemu i dowiedzieć się, co z nim zrobić.
-Zapraszamy również do oferowania własnych rozwiązań i przesyłania poprawek.
-W rzeczywistości zachęcamy do tego, ponieważ wszyscy jesteśmy wolontariuszami i
-mamy mało wolnego czasu. Im więcej osób pomaga, tym łatwiejsze jest obciążenie
-pracą dla wszystkich. W porządku, jeśli Twoje rozwiązanie nie jest idealne.
-Wszystko pomaga i być może uda nam się to poprawić.
+Zgłaszając problemy, staraj się podać jak najwięcej szczegółów, które mogą być potrzebne programistom do odtworzenia problemu i podać pełny tekst wszystkich komunikatów o błędach.
+
+Zachęcamy do dołożenia wszelkich starań, aby wykorzystać te dzienniki w połączeniu z posiadanym kodem źródłowym w celu rozwiązywania problemów i znajdowania ich przyczyn. Społeczność często jest w stanie pomóc, ale tylko Ty masz dostęp do
+plików dziennika swojej witryny i ich udostępnianie jest uważane za zagrożenie bezpieczeństwa.
+
+Jeśli problem z kodem został odkryty, zgłoś go w bugtrackerze projektu (https://framagit.org/hubzilla/core/issues). Ponownie podaj jak najwięcej szczegółów, aby uniknąć ciągłego zadawania pytań o konfigurację lub powielanie problemu, abyśmy mogli przejść od razu do problemu i dowiedzieć się, co z nim zrobić. Zapraszamy również do oferowania własnych rozwiązań i przesyłania poprawek. W rzeczywistości zachęcamy do tego, ponieważ wszyscy jesteśmy wolontariuszami i mamy mało wolnego czasu. Im więcej osób pomaga, tym łatwiejsze jest obciążenie pracą dla wszystkich. W porządku, jeśli Twoje rozwiązanie nie jest idealne. Wszystko pomaga i być może uda nam się to poprawić.
diff --git a/doc/pl/admin/hub_snapshots.md b/doc/pl/admin/hub_snapshots.md
index 1a5bd2d4f..fa38be7f8 100644
--- a/doc/pl/admin/hub_snapshots.md
+++ b/doc/pl/admin/hub_snapshots.md
@@ -4,14 +4,14 @@ Programiści Hubzilli często muszą przełączać się między gałęziami, kt
mieć niekompatybilne schematy lub zawartość bazy danych. Poniższe dwa skrypty
tworzą i przywracają pełne migawki instancji Hubzilli, w tym zarówno główny
katalog sieciowy, jak i stan całej bazy danych. Każdy skrypt wymaga pliku
-konfiguracyjnego o nazwie `hub-snapshot.conf` znajdującego się w tym samym
+konfiguracyjnego o nazwie *hub-snapshot.conf* znajdującego się w tym samym
folderze i zawiera on określone katalogi i szczegóły bazy danych huba.
### Konfiguracja
Format pliku konfiguracyjnego jest bardzo ścisły. Między nazwą zmiennej a
wartością nie może być spacji. Zastąp tylko treść w cudzysłowach swoją
-konfiguracją. Zapisz ten plik jako `hub-snapshot.conf` obok skryptów.
+konfiguracją. Zapisz ten plik jako *hub-snapshot.conf* obok skryptów.
# Location of hub root. Typically this is the location of the Hubzilla repo clone.
HUBROOT="/var/www/"
diff --git a/doc/pl/checking_account_quota_usage.bb b/doc/pl/checking_account_quota_usage.bb
new file mode 100644
index 000000000..b2cc0075c
--- /dev/null
+++ b/doc/pl/checking_account_quota_usage.bb
@@ -0,0 +1,20 @@
+[b]Sprawdzanie wykorzystania limitu konta (wykorzystanie limitów usług)[/b]
+
+Na Twoim hubie mogą zostać zaimplementowane limity klas usług, przypisujące ograniczenia do całkowitego rozmiaru miejsca na plików i zdjęci, ilosci kanałów i postów najwyższego poziomu, jakie może utworzyć właściciel konta dla określonego poziomu usług i inne ograniczenia.
+
+Oto, jak możesz szybko sprawdzić, ile z przydzielonego limitu aktualnie używasz:
+
+[b]Sprawdenie poziom limitów przechowywania plików[/b]
+Odwiedź nastęþujący adres URL w przeglądarce:
+[observer=1][observer.baseurl]/filestorage/[observer.webname][/observer]
+[observer=0]example.com/filestorage/username[/observer]
+
+[b]Sprawdenie poziomu limitów miejsca na przesłane zdjęcia[/b]
+[observer=1][observer.baseurl]/photos/[observer.webname][/observer]
+[observer=0]example.com/photos/username[/observer]
+
+Przykład:
+[observer=1][observer.baseurl]/filestorage/[observer.webname][/observer]
+[observer=0]example.com/filestorage/username[/observer]
+
+#include doc/macros/main_footer.bb;
diff --git a/doc/pl/member/member_guide.bb b/doc/pl/member/member_guide.bb
index 5a80c6510..d7f559c9e 100644
--- a/doc/pl/member/member_guide.bb
+++ b/doc/pl/member/member_guide.bb
@@ -443,7 +443,7 @@ wytworzy taki HTML:
Istnieją dwie metody importowania elementów strony internetowej: przesyłanie pliku ZIP lub odwoływanie się do lokalnego folderu plików w chmurze. Obie metody wymagają określenia elementów strony sieci internetowej przy użyciu określonej struktury folderów. Narzędzie importu umożliwia zaimportowanie wszystkich elementów niezbędnych do zbudowania całej witryny lub zestawu witryn. Celem jest uwzględnienie zewnętrznego tworzenia stron internetowych, a także narzędzi upraszczających i automatyzujących wdrażanie w hubie.
-[h5] Struktura folderu [/h5]
+[h5][b] Struktura folderu [/b][/h5]
Definicje elementów muszą być przechowywane w katalogu głównym repozytorium w folderach o nazwie odpowiadającej typowi elementu:
[code]
/pages/
@@ -453,8 +453,8 @@ Definicje elementów muszą być przechowywane w katalogu głównym repozytorium
Każdy element tych typów musi być zdefiniowany w osobnym podfolderze przy użyciu dwóch plików: jednego w formacie JSON dla metadanych i drugiego w zwykłym formacie testowym dla zawartości elementu.
-[h5] Elementy strony [/h5]
-Page element metadata is specified in a JSON-formatted file called [code]page.json[/code] with the following properties:
+[h5][b] Elementy strony [/b][/h5]
+Metadane elementu strony są zdefiniowane w pliku w formacie JSON o nazwie [code]strona.json[/code] z następującymi właściwościami:
[list]
[*] title
[*] pagelink
@@ -462,14 +462,14 @@ Page element metadata is specified in a JSON-formatted file called [code]page.js
[*] layout
[*] contentfile
[/list]
-[b]Example[/b]
+[b]Przykład[/b]
-Files:
+Pliki:
[code]
/pages/my-page/page.json
/pages/my-page/my-page.bbcode
[/code]
-Content of [code]page.json[/code]:
+Treść [code]page.json[/code]:
[code]
{
"title": "My Page",
@@ -479,22 +479,22 @@ Content of [code]page.json[/code]:
"contentfile": "my-page.bbcode"
}
[/code]
-[h5] Layout elements [/h5]
+[h5][b] Elementy układu [/b][/h5]
-Layout element metadata is specified in a JSON-formatted file called [code]layout.json[/code] with the following properties:
+Metadane elementu układu są zdefiniowane w pliku w formacie JSON o nazwie [code]layout.json[/code] z następującymi właściwościami:
[list]
[*] name
[*] description
[*] contentfile
[/list]
-[b]Example[/b]
+[b]Przykład[/b]
-Files:
+Pliki:
[code]
/layouts/my-layout/layout.json
/layouts/my-layout/my-layout.bbcode
[/code]
-Content of [code]layout.json[/code]:
+Treść [code]layout.json[/code]:
[code]
{
"name": "my-layout",
@@ -503,23 +503,23 @@ Content of [code]layout.json[/code]:
}
[/code]
-[h5] Block elements [/h5]
+[h5][b] Elementy bloku [/b][/h5]
-Block element metadata is specified in a JSON-formatted file called [code]block.json[/code] with the following properties:
+Metadane elementu bloku są określone w pliku w formacie JSON o nazwie [code]block.json[/code] z następującymi właściwościami:
[list]
[*] name
[*] title
[*] mimetype
[*] contentfile
[/list]
-[b]Example[/b]
+[b]Przykład[/b]
-Files:
+Pliki:
[code]
/blocks/my-block/block.json
/blocks/my-block/my-block.html
[/code]
-Content of [code]block.json[/code]:
+Treść [code]block.json[/code]:
[code]
{
@@ -530,112 +530,110 @@ Content of [code]block.json[/code]:
}
[/code]
-[h3]Comanche Page Description Language[/h3]
+[h3]Język opisu stron Comanche[/h3]
-Comanche is a markup language similar to [url=[baseurl]/help/member/bbcode]BBcode[/url] with which to create elaborate and complex web pages by assembling them from a series of components - some of which are pre-built and others which can be defined on the fly. Comanche uses a Page Decription Language to create these pages.
+Comanche to język znaczników podobny do [url=[baseurl]/help/member/bbcode]BBcode[/url], za pomocą którego można tworzyć rozbudowane i złożone strony internetowe, łącząc je z szeregu komponentów - z których niektóre są już wstępnie zbudowane i inne, które można skonstruować w locie. Comanche używa własnego języka opisu strony do tworzenia tych stron.
-Comanche primarily chooses what content will appear in various regions of the page. The various regions have names and these names can change depending on what layout template you choose.
+Comanche przede wszystkim wybiera, jakie treści pojawią się w różnych [b]regionach[/b] strony. Regiony mają swoje nazwy, które mogą się zmieniać w zależności od wybranego szablonu układu.
-[h4]Page Templates[/h4]
-Currently there are five layout templates, unless your site provides additional layouts.
+[h4][b]Szablony strony[/b][/h4]
+Obecnie dostępnych jest pięć szablonów układów, ale w serwisie można udostępniać dodatkowe, własne układy.
[dl terms="b"]
[*= default]
-The default template defines a &quot;nav&quot; region across the top, &quot;aside&quot; as a fixed width sidebar,
-&quot;content&quot; for the main content region, and &quot;footer&quot; for a page footer.
+Domyślny szablon zawiera definicję regionu "nav" znajdującego się u góry, "aside" jako pasek boczny o stałej szerokości,
+"content" dla głównego regionu treści i "footer" dla stopki strony.
[*= full]
-The full template defines the same as the default template with the exception that there is no &quot;aside&quot; region.
+Pełny szablon definiuje to samo, co szablon "default", z tą różnicą, że nie ma regionu "aside".
[*= choklet]
-The choklet template provides a number of fluid layout styles which can be specified by flavour:
+Szablon "choklet" zapewnia kilka płynnych układów, które można wybierać według odmiany:
[list]
-[*] (default flavour) - a two column layout similar to the "default" template, but more fluid
-[*] bannertwo - a two column layout with a banner region, compatible with the "default" template on small displays
-[*] three - three column layout (adds a "right_aside" region to the default template)
-[*] edgestwo - two column layout with fixed side margins
-[*] edgesthree - three column layout with fixed side margins
-[*] full - three column layout with fixed side margins and adds a "header" region beneath the navigation bar
+[*] (domyślna odmiana) - układ dwukolumnowy, podobny do szaablonu "default", ale jest bardziej płynny
+[*] bannertwo - układ dwukolumnowy z regionem "banner", zgodny z szablonem "default" na małych wyświetlaczach
+[*] three - układ trzykolumnowy (dodany region "right_aside" do szablonu domyślnego)
+[*] edgestwo - układ dwukolumnowy ze stałymi marginesami bocznymi
+[*] edgesthree - układ trzykolumnowy ze stałymi marginesami bocznymi
+[*] full - układ trzykolumnowy ze stałymi marginesami bocznymi i dodanym obszarem "header" poniżej paska nawigacji
[/list]
[*= redable]
-A template for reading longer texts full screen (so without navigation bar). Three columns: aside, content and right_aside.
-For maximum readability it is advised to only use the middle content column.
+Szablon do czytania dłuższych tekstów na pełnym ekranie (czyli bez paska nawigacyjnego). Trzy kolumny: "aside", "content" i "right_aside".
+Aby zapewnić maksymalną czytelność, zaleca się używanie tylko środkowej kolumny treści.
[*= zen]
-Gives you the freedom to do everything yourself. Just a blank page with a content region.
+Daje swobodę robienia wszystkiego samemu. Tylko pusta strona z obszarem zawartości.
[/dl]
-To choose a layout template, use the 'template' tag.
+Aby wybrać szablon układu, trzeba użyć tagu "template".
[code]
[template]full[/template]
[/code]
-To choose the "choklet" template with the "three" flavour:
+Wybranie szablonu "choklet" z odmianą "three":
[code]
[template=three]choklet[/template]
[/code]
-The default template will be used if no other template is specified. The template can use any names it desires for content regions. You will be using 'region' tags to decide what content to place in the respective regions.
+Jeśli nie określono innego szablonu, zostanie użyty szablon domyślny. W szablonie można używać dowolnych nazw dla regionów zawartości. Używa sie też tagów "region", aby zdecydować, jakie treści umieścić w odpowiednich regionach.
-Three &quot;macros&quot; have been defined for your use.
+Zadefiniowane są też trzy "makra", które można użyć na stronie.
[code]
- $htmlhead - replaced with the site head content.
- $nav - replaced with the site navigation bar content.
- $content - replaced with the main page content.
+ $htmlhead - wstawia zawartość nagłówka strony.
+ $nav - wstawia zawartość paska nawigacji.
+ $content - wstawia główną treść strony.
[/code]
-By default, $nav is placed in the &quot;nav&quot; page region and $content is placed in the &quot;content&quot; region. You only need to use these macros if you wish to re-arrange where these items appear, either to change the order or to move them to other regions.
+Domyślnie, makro $nav jest umieszczane w regionie "nav" strony a $content w regionie "content". Tych makr potrzebujesz tylko wtedy, gdy chcesz zmienić rozmieszczenie tych elementów, aby zmienić kolejność lub przenieść je do innych regionów.
-
-To select a theme for your page, use the 'theme' tag.
+Aby wybrać motyw dla swojej strony, użyj tagu "theme".
[code]
[theme]suckerberg[/theme]
[/code]
-This will select the theme named &quot;suckerberg&quot;. By default your channel's preferred theme will be used.
+Spowoduje to wybranie motywu o nazwie "suckerberg". Domyślnie używany jest preferowany motyw Twojego kanału.
[code]
[theme=passion]suckerberg[/theme]
[/code]
-This will select the theme named &quot;suckerberg&quot; and select the &quot;passion&quot; schema (theme variant). Alternatively it may be possible to use a condensed theme notation for this.
+Spowoduje to wybranie motywu o nazwie "suckerberg" oraz wybór schematu "passion" (wariant motywu). Alternatywnie można użyć do tego zwięzłej notacji motywu.
[code]
[theme]suckerberg:passion[/theme]
[/code]
-The condensed notation isn't part of Comanche itself but is recognised by $Projectname platform as a theme specifier.
+Notacja zwięzła nie jest częścią samego Comanche, ale jest rozpoznawana przez platformę $Projectname jako specyfikator motywu.
-[h4]Navbar[/h4]
+[h4][b]Pasek nawigacji[/b][/h4]
[code]
[navbar]tucson[/navbar]
[/code]
-Use the 'tucson' navbar template and CSS rules. By default the 'default' navbar template will be used.
-
+Kod ten powoduje użycie szablonu paska nawigacyjnego "tucson" i reguł CSS. Domyślnie stosowany jest szablon domyślny szablon paska nawigacyjnego.
-[h4]Regions[/h4]
-Each region has a name, as noted above. You will specify the region of interest using a 'region' tag, which includes the name. Any content you wish placed in this region should be placed between the opening region tag and the closing tag.
+[h4][b]Regiony[/b][/h4]
+Tak jak wspomniano wyżej, każdy region swoją nazwę. Wybrany eegion określa używając tagu "region", który zawiera nazwę. Wszelkie treści, które chcesz umieścić w tym regionie, powinny być umieszczone między tagiem otwierającego a zamykającym.
[code]
- [region=htmlhead]....content goes here....[/region]
- [region=aside]....content goes here....[/region]
- [region=nav]....content goes here....[/region]
- [region=content]....content goes here....[/region]
+ [region=htmlhead]....tutaj jest treść....[/region]
+ [region=aside]....tutaj jest treść....[/region]
+ [region=nav]....tutaj jest treść....[/region]
+ [region=content]....tutaj jest treść....[/region]
[/code]
-[h4]CSS and Javascript[/h4]
-We have the possibility to include javascript and css libraries in the htmlhead region. At present we make use of jquery (js), bootstrap (css/js) and foundation (css/js).
-This will overwrite the selected themes htmlhead.
+[h4][b]CSS i Javascript[/b][/h4]
+Jest możliwość włączenia bibliotek JavaScript i CSS w regionie "htmlhead". Obecnie korzystamy z bibliotek jQuery (JS), Bootstrap (CSS i JS) oraz Foundation (CSS i JS).
+Ten kod spowoduje nadpisanie regionu htmlhead wybranego motywu.
[code]
[region=htmlhead]
@@ -646,116 +644,121 @@ This will overwrite the selected themes htmlhead.
[/code]
-[h4]Menus and Blocks[/h4]
-Your webpage creation tools allow you to create menus and blocks, in addition to page content. These provide a chunk of existing content to be placed in whatever regions and whatever order you specify. Each of these has a name which you define when the menu or block is created.
+[h4][b]Elementy menu i bloki[/b][/h4]
+Narzędzia do tworzenia stron internetowych umożliwiają również tworzenie eleentów menu i bloków. Dostarczają one fragment kodu, który można umieścić w dowolnych regionach i w dowolnej kolejności. Każdy z takich fragmentów ma nazwę, którą definiuje się podczas tworzenia elementów menu lub bloku.
+Ten kod:
[code]
[menu]mymenu[/menu]
[/code]
-This places the menu called &quot;mymenu&quot; at this location on the page, which must be inside a region.
+spowoduje umieszczenie w tym miejscu menu o nazwie "mymenu”, ale miejsce to musi się ono znajdować wewnątrz regionu.
+Kod:
[code]
[menu=horizontal]mymenu[/menu]
[/code]
-This places the menu called &quot;mymenu&quot; at this location on the page, which must be inside a region. Additionally it applies the "horizontal" class to the menu. "horizontal" is defined in the redbasic theme. It may or may not be available in other themes.
+spowoduje umieszczenie w tym miejscu menu o nazwie "mymenu", ale musi się ono znajdować które musi znajdować wewnątrz regionu. Dodatkowo zastosowano tu do menu klasę "horizontal". Klasa "horizontal" jest zdefiniowana w motwie "redbasic". Może być dostępna lub nie w innych motywach.
+W tym bloku:
[code]
[menu][var=wrap]none[/var]mymenu[/menu]
[/code]
-The variable [var=wrap]none[/var] in a block removes the wrapping div element from the menu.
+zmienna [code][var=wrap]none[/var][/code] usuwa z menu element [code]div[/code].
+Ten kod:
[code]
[block]contributors[/block]
[/code]
-This places a block named &quot;contributors&quot; in this region.
+umieszcza blok o nazwie &quot;contributors&quot; w regionie, w którym został wstawiony.
+Kod:
[code]
[block=someclass]contributors[/block]
[/code]
-This places a block named &quot;contributors&quot; in this region. Additionally it applies the &quot;someclass&quot; class to the block. This replaces the default block classes &quot;bblock widget&quot;.
+też umieszcza blok o nazwie &quot;contributors&quot; w tym regionie, ale dodatkowo stosuje dla tego bloku klasę &quot;someclass&quot;. Zamienia to domyślną klasę bloku &quot;bblock widget&quot;.
+W bloku:
[code]
[block][var=wrap]none[/var]contributors[/block]
[/code]
-The variable [var=wrap]none[/var] in a block removes the wrapping div element from the block.
-
-[h4]Widgets[/h4]
-Widgets are executable apps provided by the system which you can place on your page. Some widgets take arguments which allows you to tailor the widget to your purpose. System widgets are listed [url=help/Widgets]here[/url]. Widgets can also ve created by plugins, themes, or your site administrator to provide additional functionality.
+zmienna [code][var=wrap]none[/var][/code] usuwa z bloku opakowujący go element [code]div[/code].
+[h4][b]Widżety[/b][/h4]
+Widżety to wykonywalne aplikacje dostarczane przez system, które można umieścić na swojej stronie. Niektóre widżety przyjmują argumenty, które pozwalają dostosować widżet do własnych potrzeb. Widżety systemowe są wymienione [url=help/Widgets]tutaj[/url]. Widżety mogą być również tworzone w ramach wtyczek, motywów lub przez administratora witryny, aby zapewnić dodatkowe funkcje.
-Widgets and arguments are specified with the 'widget' and 'var' tags.
+Widżety i ich argumenty są określane za pomocą tagów "widget" i "var".
[code]
[widget=recent_visitors][var=count]24[/var][/widget]
[/code]
-This loads the &quot;recent_visitors&quot; widget and supplies it with the argument &quot;count&quot; set to &quot;24&quot;.
+Spowoduje to załadowanie widżetu &bdquo;latest_visitors&rdquo; i dostarcza mu argument "count" ustawiony na „24”.
-[h4]Comments[/h4]
-The 'comment' tag is used to delimit comments. These comments will not appear on the rendered page.
+[h4][b]Komentarze[/b][/h4]
+Tag "comment" jest używany do wydzielenia komentarzy. Komentarze te nie pojawią się na renderowanej stronie.
[code]
[comment]This is a comment[/comment]
[/code]
-[h4]Conditional Execution[/h4]
-You can use an 'if' construct to make decisions. These are currently based on system configuration variable or the current observer.
+[h4][b]Wykonanie warunkowe[/b][/h4]
+Można użyć konstrukcji [code]if[/code] warunkowego wykonania kodu. Jest to obecnie oparte na zmiennej konfiguracji systemu [code]$config.system[/code] lub zmiennej [code]$observer[/code].
[code]
[if $config.system.foo]
- ... the configuration variable system.foo evaluates to 'true'.
+ ... zmienna konfiguracyjna system.foo przyjmuje wartość 'true'.
[else]
- ... the configuration variable system.foo evaluates to 'false'.
+ ... zmienna konfiguracyjna system.foo przyjmuje wartość 'false'.
[/if]
[if $observer]
- ... this content will only be show to authenticated viewers
+ ... ta treść będzie pokazywana tylko uwierzytelnionym użytownikom
[/if]
[/code]
- The 'else' clause is optional.
+ Klauzula 'else' jest opcjonalna.
- Several tests are supported besides boolean evaluation.
+ Oprócz oceny logicznej obsługiwanych jest też kilka testów.
[code]
[if $config.system.foo == bar]
- ... the configuration variable system.foo is equal to the string 'bar'
+ ... zmienna konfiguracyjne system.foo jest równa łańcuchowi 'bar'
[/if]
[if $config.system.foo != bar]
- ... the configuration variable system.foo is not equal to the string 'bar'
+ ... zmienna konfiguracyjne system.foo nie jest równa łańcuchowi 'bar'
[/if]
[if $config.system.foo {} bar ]
- ... the configuration variable system.foo is a simple array containing a value 'bar'
+ ... zmienna konfiguracyjna system.foo jest prostą tablicą zawierającą zmienną 'bar'
[/if]
[if $config.system.foo {*} bar]
- ... the configuration variable system.foo is a simple array containing a key named 'bar'
+ ... zmienna konfiguracyjna system.foo jest prostą tablicą zawierającą klucz o nazwie 'bar'
[/if]
[/code]
-[h4]Complex Example[/h4]
+[h4][b]Złożony przykład[/b][/h4]
[code]
- [comment]use an existing page template which provides a banner region plus 3 columns beneath it[/comment]
+ [comment]użyj istniejący szablon strony, który zawiera obszar banera oraz 3 kolumny poniżej[/comment]
[template]3-column-with-header[/template]
- [comment]Use the &quot;darknight&quot; theme[/comment]
+ [comment]Użyj motyw &quot;darknight&quot;[/comment]
[theme]darkknight[/theme]
- [comment]Use the existing site navigation menu[/comment]
+ [comment]Użyj istniejące menu nawigacyjne strony[/comment]
[region=nav]$nav[/region]
[region=side]
- [comment]Use my chosen menu and a couple of widgets[/comment]
+ [comment]Użyj wybranego przeze mnie menu i kilku widżetów[/comment]
[menu]myfavouritemenu[/menu]
@@ -773,7 +776,7 @@ You can use an 'if' construct to make decisions. These are currently based on sy
[region=middle]
- [comment]Show the normal page content[/comment]
+ [comment]Pokaż normalną zawartość strony[/comment]
$content
@@ -783,7 +786,7 @@ You can use an 'if' construct to make decisions. These are currently based on sy
[region=right]
- [comment]Show my condensed channel &quot;wall&quot; feed and allow interaction if the observer is allowed to interact[/comment]
+ [comment]Pokaż mój skondensowany kanał RSS "wal" i zezwól na interakcję, jeśli obserwator ma możliwość interakcji[/comment]
[widget]channel[/widget]
@@ -792,237 +795,230 @@ You can use an 'if' construct to make decisions. These are currently based on sy
[/code]
-[h3]Personal Cloud Storage[/h3]
+[h3]Osobisty magazyn w chmurze[/h3]
-$Projectname provides an ability to store privately and/or share arbitrary files with friends.
+$Projectname umożliwia prywatne przechowywanie i udostępnianie znajomym dowolnych plików. Możesz przesłać pliki ze swojego komputera do obszaru przechowywania lub skopiować je bezpośrednio z systemu operacyjnego przy użyciu protokołu WebDAV.
-You may either upload files from your computer into your storage area, or copy them directly from the operating system using the WebDAV protocol.
+Funkcjonuje to podobnie do usług "chmurowych", takich jak [i]Dopbox[/i], [i]Dysk[/i] Google czy [i]One Drive[/i] Microsoftu.
-On many public servers there may be limits on disk usage.
+Na wielu serwerach publicznych mogą obowiązywać ograniczenia dotyczące przydzielonej powierzchni dyskowej.
-[h4]File Attachments[/h4]
+[h4][b]Załączniki plikowe[/b][/h4]
-The quickest and easiest way to share files is through file attachments. In the row of icons below the status post editor is a tool to upload attachments. Click the tool, select a file and submit. After the file is uploaded, you will see an attachment code placed inside the text region. Do not edit this line or it may break the ability for your friends to see the attachment. You can use the post permissions dialogue box or privacy hashtags to restrict the visibility of the file - which will be set to match the permissions of the post your are sending.
+Najszybszym i najłatwiejszym sposobem udostępniania plików są załączniki. W rzędzie ikon poniżej edytora statusu znajduje się narzędzie do przesyłania załączników. Kliknij narzędzie, wybierz plik i prześlij. Po załadowaniu pliku zobaczysz kod załącznika umieszczony w obszarze tekstowym. Nie edytuj tego kodu, ponieważ może to uniemożliwić Ci udostępnienie tego pliku znajomym. Możesz użyć okna dialogowego uprawnień do publikowania lub hasztagów prywatności, aby ograniczyć widoczność pliku - który zostanie ustawiony zgodnie z uprawnieniami wysyłanego postu.
-To delete attachments or change the permissions on the stored files, visit [observer=1][baseurl]/cloud/[observer.webname][/observer][observer=0][baseurl]/cloud/username replacing username with the nickname you provided during channel creation[/observer].
+Aby usunąć załączniki lub zmienić uprawnienia do przechowywanych plików, odwiedź [observer=1][baseurl]/cloud/[observer.webname][/observer][observer=0][baseurl]/cloud/username, zastępując [code]username[/code] pseudonimem, jaki podałeś podczas tworzenia kanału[/observer].
-[h4]Web Access[/h4]
+[h4][b]Dostęp internetowy[/b][/h4]
-Your files are visible on the web at the location [observer=1][baseurl]/cloud/[observer.webname][/observer][observer=0][baseurl]/cloud/username[/observer] to anybody who is allowed to view them. If the viewer has sufficient privileges, they may also have the ability to create new files and folders/directories. This should only be used for smaller files and photos (up to a few megabytes) as it uses internal memory. For larger files (videos, music, etc.), please upload using WebDAV. These files may still be retrieved via web access.
+Twoje pliki są widoczne w sieci pod adresem [observer=1][baseurl]/cloud/[observer.webname][/observer][observer=0][baseurl]/cloud/username[/observer] dla każdego, kto ma uprawnienia do ich przeglądania. Jeśli przeglądający ma wystarczające uprawnienia, może mieć również możliwość tworzenia nowych plików i folderów (katalogów) w interfejsie przeglądarki. Dostęp internetowy powinnien być używane tylko w przypadku mniejszych plików i zdjęć (do kilku megabajtów), ponieważ wykorzystuje pamięć wewnętrzną. W przypadku większych plików (filmy, muzyka itp.) przesyłaj je za pomocą protokołu WebDAV, cojest omówione w następnym rozdziale. Takie pliki będzie można nadal pobierać za pośrednictwem dostępu internetowego.
-[h4]WebDAV access[/h4]
+[h4][b]Dostęp WebDAV[/b][/h4]
-WebDAV provides a way to copy files directly to or from your computer's operating system, where your cloud files appear as a virtual disk drive. This should be used to upload large files such as video and audio; as it is not limited to available memory. See [zrl=help/member/member_guide#Cloud_Desktop_Clients]Cloud Desktop Clients[/zrl] below.
+WebDAV umożliwia kopiowanie plików bezpośrednio do lub z systemu operacyjnego komputera, gdzie Twój "magazyn chmurze" pojawia się jako wirtualny dysk. Dostęp ten powinien być używany do przesyłania dużych plików, takich jak wideo i audio, ponieważ nie jest ograniczony dostępną pamięcią wewnętrzna. Zobacz [zrl=help/member/member_guide#Cloud_Desktop_Clients]Cloud Desktop Clients[/zrl] poniżej.
-[h4]CalDAV and CardDAV access on Android[/h4]
+[h4][b]Dostęp CalDAV i CardDAV na Androidzie[/b][/h4]
-You can sync you calendar and contacts on Android with your Hub.
+Możesz zsynchronizować swój kalendarz i kontakty w systemie Android ze swoim hubem.
+
+Poniższe kroki zostały przetestowane pod kątem zasosowania [url=https://f-droid.org/en/packages/at.bitfire.davdroid/] DAVdroid [/url]:
-The following steps where tested for [url=https://f-droid.org/en/packages/at.bitfire.davdroid/]DAVdroid[/url]
[list]
-[*] install DAVdroid
-[*] add account
-[*] use "URL" and "user name" to login
+[*] zainstaluj DAVdroid
+[*] dodaj konto
+[*] użyj "URL" i "user name" do zalogowania się
[list]
-[*] base url is [baseurl]/cdav
-[*] user name is [observer=1][observer.webname][/observer][observer=0]username[/observer]
+[*] podstawowy URL to [baseurl]/cdav
+[*] Twoja nazwa użytkowka to [observer=1][observer.webname][/observer][observer=0]username[/observer]
[/list]
[/list]
-To share your calendar visit [observer.baseurl]/cdav/calendar
-
+Aby udostępnić kalendarz odwiedź [observer.baseurl]/cdav/calendar
-[h4]Permissions[/h4]
+[h4][b]Uprawnienia[/b][/h4]
-When using WebDAV, the file is created with your channel's default file permissions and this cannot be changed from within the operating system. It also may not be as restrictive as you would like. What we've found is that the preferred method of making files private is to first create folders or directories; then visit [observer=1][baseurl]/cloud/[observer.webname][/observer][observer=0][baseurl]/cloud/username[/observer] select the directory and change the permissions. Do this before you put anything into the directory. The directory permissions take precedence so you can then put files or other folders into that container and they will be protected from unwanted viewers by the directory permissions. It is common for folks to create a &quot;personal&quot; or &quot;private&quot; folder which is restricted to themselves. You can use this as a personal cloud to store anything from anywhere on the web or any computer and it is protected from others. You might also create folders for &quot;family&quot; and &quot;friends&quot; with permission granted to appropriate privacy groups.
+W przypadku korzystania z protokołu WebDAV plik jest tworzony z domyślnymi uprawnieniami do plików kanału, których nie można zmienić z poziomu systemu operacyjnego. Może też nie być to tak restrykcyjne, jak byś chciał. Najlepiej, utwórz foldery (katalogi), następnie odwiedź swoją "chmurę" pod aadresem [observer=1][baseurl]/cloud/[observer.webname][/observer][observer=0][baseurl]/cloud/username[/observer], wybierz katalog i zmień uprawnienia. Zrób to zanim umieścisz cokolwiek w katalogu. Uprawnienia do katalogu mają pierwszeństwo, więc możesz następnie umieścić pliki lub inne foldery w tym kontenerze i będą one chronione przed niechcianymi widzami przez ustawienie uprawnienia do katalogu. Często zdarza się, że użytkownicy tworzą folder "osobisty" lub "prywatny", który jest ograniczony do nich samych. Możesz używać tego jako osobistej chmury do przechowywania wszystkiego z dowolnego miejsca w Internecie lub dowolnego komputera i jest to chroniony przed innymi. Możesz także utworzyć foldery dla "rodziny" lub "przyjaciele" za zgodą udzieloną odpowiednim grupom prywatności.
-[h3]Cloud Desktop Clients[/h3]
+[h3]Klienty desktopowe dla chmury[/h3]
+[h4][b]Klienty dla Windows[/b][/h4]
-[h4]Cloud Desktop Clients - Windows[/h4]
+W Windows 7 połaczenie WebDAV można nawiązać przy użyciu kreatora z graficznym interfejsem:
+1. Kliknij lewym przyciskiem myszy na przycisk "Start", aby otworzyc menu "Start".
+2. Kliknij prawym przyciskiem myszy na ikone "Mój komputer", aby uzyskac dostęp do tego menu.
+3. Kliknij lewym przysiskiem myszy na link "Mapuj dysk sieciowy...", aby otworzyć okno dialogowe kreatora połączeń.
+4. Wpisz '[baseurl]/dav/nickname' w polu tekstowym (zamieniając 'nickname' na pseudonim swojego kanału) i kliknij przycisk "Gotowe".
+5. Wpisz pseudonim kanału $Projectname. WAŻNE - bez znaku @ lub nazwy domeny
+6. Wpisz swoje hasło $Projectname
-WebDAV using Windows 7 graphical user interface wizard:
-1. Left-click the Start-button to open the start menu.
-2. Right-click the My computer icon to access its menu.
-3. Left-click Map network drive... to open the connection dialog wizard.
-4. Type '[baseurl]/dav/nickname' in the textbox (replace nickname with your channel nickname) and click the Complete button.
-5. Type your $Projectname channel nickname. IMPORTANT - NO at-sign or domain name.
-6. Type your $Projectname password
+[h4][b]Klienty dla Linux[/b][/h4]
-[h4]Cloud Desktop Clients - Linux[/h4]
+[h5][b]Montowanie katalogu w systemie plików[/b][/h5]
-[h5]Mount as a filesystem[/h5]
+Aby zainstalować katalog w chmurze jako system plików, musisz najpierw zainstalować davfs2. Dla większości dystrybucji program ten jest dostępny w repozytoriach. Instalacja w Debianie:
-[b]Mounting As A Filesystem[/b]
+[code]sudo apt-get install davfs2[/code]
-To install your cloud directory as a filesystem, you first need davfs2 installed. 99% of the time, this will be included in your distributions repositories. In Debian
+Następnie skonfiguruj davfs2:
-[code]apt-get install davfs2[/code]
+[code]sudo dpkg-reconfigure davfs2[/code]
-If you want to let normal users mount the filesystem
+i wybierz &quot;yes&quot; przy zapytaniu.
-[code] dpkg-reconfigure davfs2[/code]
+Teraz musisz dodać użytkownika, który ma mieć możliwość montowania dav, do grupy davfs2:
-and select &quot;yes&quot; at the prompt.
+[code]sudo usermod -aG davfs2 &lt;DesktopUser&gt;[/code]
-Now you need to add any user you want to be able to mount dav to the davfs2 group
+[b]Note:[/b] w niektórych systemach grupa użytkowników może być inna,
+np. "network" w Arch Linux. W razie wątpliwości sprawdź dokumentację
+davfs dla swojego konkretnego systemu operacyjnego.
-[code]usermod -aG davfs2 &lt;DesktopUser&gt;[/code]
-
-[b]Note:[/b] on some systems the user group may be different, i.e. - "network"
-on Arch Linux. If in doubt, check the davfs documentation for your
-particular OS.
-
-Edit /etc/fstab
+Edytuj /etc/fstab:
[code]nano /etc/fstab[/code]
- to include your cloud directory by adding
+aby uwzględnić katalog w chmurze, dodając:
[code]
[baseurl]/dav/ /mount/point davfs user,noauto,uid=&lt;DesktopUser&gt;,file_mode=600,dir_mode=700 0 1
[/code]
-Where [baseurl] is the URL of your hub, /mount/point is the location you want to mount the cloud, and &lt;DesktopUser&gt; is the user you log in to one your computer. Note that if you are mounting as a normal user (not root) the mount point must be in your home directory.
+gdzie [baseurl] jest adresem URL huba, /mount/point to lokalizacja, w której chcesz zamontować chmurę, a &lt;DesktopUser&gt; to użytkownik, którego logujesz się na swoim komputerze. Miej na uwadze, że jeśli montujesz jako zwykły użytkownik (nie root), punkt montowania musi znajdować się w twoim katalogu domowym.
-For example, if I wanted to mount my cloud to a directory called 'cloud' in my home directory, and my username was bob, my fstab would be
+Na przykład, jeśli chciałbyś zamontować swoją chmurę w katalogu o nazwie 'cloud' w swoim katalogu domowym, a Twoja nazwa użytkownika to 'bob', zapis w fstab będzie następujący:
[code][baseurl]/dav/ /home/bob/cloud davfs user,noauto,uid=bob,file_mode=600,dir_mode=700 0 1[/code]
-Now, create the mount point.
+Teraz utówrz punkt montowania:
[code]mkdir /home/bob/cloud[/code]
-and also create a directory file to store your credentials
+oraz utwórz plik katalogu do przechowywania danych uwierzytelniania:
[code]mkdir /home/bob/.davfs2[/code]
-Create a file called 'secrets'
+Utwórz plik o nazwie 'secrets'
[code]nano /home/bob/.davfs2/secrets[/code]
-and add your cloud login credentials
+i dodaj tam swoje dane uwierzytelniania w chmurze
[code]
[baseurl]/dav &lt;username&gt; &lt;password&gt;
[/code]
-Where &lt;username&gt; and &lt;password&gt; are the username and password [i]for your hub[/i].
+gdzie &lt;username&gt; i &lt;password&gt; to nazwa użytkownika i hasło [i]na Twoim kanale w hubie[/i].
-Don't let this file be writeable by anyone who doesn't need it with
+Nie pozwól, aby ten plik mógł być zapisywany przez kogoś nieupoważnionego:
[code]chmod 600 /home/bob/.davfs2/secrets[/code]
-Finally, mount the drive.
+Na koniec, zamontuj dysk:
[code]mount [baseurl]/dav[/code]
-You can now find your cloud at /home/bob/cloud and use it as though it were part of your local filesystem - even if the applications you are using have no dav support themselves.
+Możesz teraz znaleźć swoją chmurę w /home/bob/cloud i używać jej tak, jakby była częścią lokalnego systemu plików - nawet jeśli aplikacje, których używasz, same nie obsługują dav.
-[b]Troubleshooting[/b]
+[b]Rozwiązywanie problemów[/b]
-With some webservers and certain configurations, you may find davfs2 creating files with 0 bytes file size where other clients work just fine. This is generally caused by cache and locks. If you are affected by this issue, you need to edit your davfs2 configuration.
+W przypadku niektórych serwerów WWW i pewnych konfiguracji może się okazać, że davfs2 tworzy pliki o rozmiarze pliku 0 bajtów, podczas gdy inni klienty działają dobrze. Zwykle jest to spowodowane pamięcią podręczną i blokadami. Jeśli występuje ten problem, musisz edytować konfigurację davfs2.
-[code]nano /etc/davfs2/davfs2.conf[/code]
+[code]sudo nano /etc/davfs2/davfs2.conf[/code]
-Your distribution will provide a sample configuration, and this file should already exist, however, most of it will be commented out with a # at the beginning of the line.
+Twoja dystrybucja dostarczy przykładową konfigurację i ten plik powinien już istnieć, jednak większość jego treści jest zakomentowana znakiem # na początku wiersza.
-First step is to remove locks.
+Pierwszym krokiem jest usunięcie blokad.
-Edit the use_locks line so it reads [code]use_locks 0[/code].
+Edytuj wiersz use_locks, tak aby odczytywał [code]use_locks 0[/code].
-Unmount your file system, remount your file system, and try copying over a file from the command line. Note you should copy a new file, and not overwrite an old one for this test. Leave it a minute or two then do [code]ls -l -h[/code] and check the file size of your new file is still greater than 0 bytes. If it is, stop there, and do nothing else.
+Odłącz system plików, podłącz go ponownie i spróbuj skopiować plik z wiersza poleceń. Zauważ, że powinieneś skopiować nowy plik a nie nadpisywać starego. który został utwozony na potrzeby tego testu. Poczekaj minutę lub dwie, a następnie wykonaj polecenie [code]ls -l -h[/code] i sprawdź, czy rozmiar nowego pliku jest nadal większy niż 0 bajtów. Jeśli tak, zatrzymaj się na tym i nie rób nic więcej.
-If that still doesn't work, disable the cache. Note that this has a performance impact so should only be done if disabling locks didn't solve your problem. Edit the cache_size and set it to [code]cache_size 0[/code] and also set file_refresh to [code]file_refresh 0[/code]. Unmount your filesystem, remount your file system, and test it again.
+Jeśli to nadal nie zadziała, wyłącz pamięć podręczną. Pamiętaj, że ma to wpływ na wydajność, więc należy to robić tylko wtedy, gdy wyłączenie blokad nie rozwiązało problemu. Edytuj cache_size i ustaw ją na [code]cache_size 0[/code], a także ustaw file_refresh na [code]file_refresh 0[/code]. Odmontuj system plików, ponownie go podłącz i przetestuj ponownie.
-If it [i]still[/i] doesn't work, there is one more thing you can try. (This one is caused by a bug in older versions of dav2fs itself, so updating to a new version may also help). Enable weak etag dropping by setting [code]drop_weak_etags 1[/code]. Unmount and remount your filesystem to apply the changes.
+Jeśli [i]nadal[/i] to nie działa, jest jeszcze jedna rzecz, której możesz spróbować. (Ten jest spowodowany błędem w starszych wersjach samego dav2fs, więc aktualizacja do nowej wersji może również pomóc). Włącz słabe usuwanie etagów, ustawiając [code]drop_weak_etags 1[]/code. Odmontuj i ponownie podłącz swój system plików, aby zastosować zmiany.
+[h5][b]Dolphin[/b][/h5]
+Dolphin Browser to przeglądarka internetowa dla Android i iOS. Odwiedź w niej [code]webdavs://example.com/dav[/code], gdzie [code]example.com[/code] to URL do Twojego huba.
-[h5]Dolphin[/h5]
-Visit webdavs://example.com/dav where &quot;example.com&quot; is the URL of your hub.
+Gdy zostaniesz poproszony o podanie nazwy użytkownika i hasła, wprowadź nazwę swojego kanału (pierwszą część swojej strony internetowej - bez znaku @ i nazwy domeny) i hasło do swojego normalnego konta.
-When prompted for a username and password, enter your channel name (the first part of your webbie - no @ or domain name) and password for your normal account.
+Pamiętaj, że jeśli jesteś już zalogowany do interfejsu WWW przez Konqueror, nie zostaniesz poproszony o dalsze uwierzytelnianie.
-Note, if you are already logged in to the web interface via Konqueror, you will not be prompted for further authentication.
+[h5][b]Konqueror[/b][/h5]
+Konqueror to przeglądarka internetowa, meadżer plików i przeglądarka dokumentów dla środowiska KDE. Wystarczy odwiedzić w niej serwis [code]webdavs://example.com/dav[/code] po zalogowaniu się do swojego huba, gdzie [code]example.com[/code] to adres URL huba.
-[h5]Konqueror[/h5]
+Jeśli jesteś zalogowany do swojego huba w normalny sposób, nie jest wymagane dalsze uwierzytelnianie.
-Simply visit webdavs://example.com/dav after logging in to your hub, where &quot;example.com&quot; is the URL of your hub.
+Ponadto, jeśli ktoś uwierzytelnił się w innym hubie podczas normalnej sesji przeglądarki, Twoja tożsamość zostanie również przekazana do chmury dla tych hubów - co oznacza, że możesz uzyskać dostęp do wszelkich prywatnych plików na dowolnym serwerze, o ile masz uprawnienia do ich przeglądania, pod warunkiem, że odwiedziłeś tę witrynę wcześniej podczas sesji.
-No further authentication is required if you are logged in to your hub in the normal manner.
+Ta funkcja jest zwykle ograniczona do interfejsu sieciowego i nie jest dostępna dla żadnego innego środowiska graficznego niż KDE.
-Additionally, if one has authenticated at a different hub during their normal browser session, your identity will be passed to the cloud for these hubs too - meaning you can access any private files on any server, as long as you have permissions to see them, as long as you have visited that site earlier in your session.
+[h5][b]Nautilus[/b][/h5]
-This functionality is normally restricted to the web interface, and is not available to any desktop software other than KDE.
+Nautilus to popularny menadżer plików dla środowiska GNOME. Jeśli sie nią posługujesz:
-[h5]Nautilus[/h5]
+1. Otwórz okno przeglądarki plików;
+2. Wybierz z menu opcję Plik &gt; Połącz z serwerem...;
+3. Wpisz davs://&lt;domain_name&gt;/dav/&lt;your_channelname&gt; i kliknij Połącz;
+4. Zostaniesz poproszony o podanie nazwy kanału (tak samo jak poprzednio) i hasło;
+5. Twój osobisty katalog DAV zostanie udostęþniony w oknie przeglądarki.
-1. Open a File browsing window (that's Nautilus)
-2. Select File &gt; Connect to server from the menu
-3. Type davs://&lt;domain_name&gt;/dav/&lt;your_channelname&gt; and click Connect
-4. You will be prompted for your channel name (same as above) and password
-5. Your personal DAV directory will be shown in the window
+[h5][b]Nemo[/b][/h5]
-[h5]Nemo[/h5]
+Pierwszy sposób:
-For (file browser) Nemo 1.8.2 under Linux Mint 15, Cinnamon 1.8.8. Nemo ist the standard file browser there.
+wpisz w pasku adresowym &quot;davs://&lt;domain_name&gt;/dav/&lt;your_channelname&gt;&quot;.
-1st way
-type &quot;davs://&lt;domain_name&gt;/dav/&lt;your_channelname&gt;&quot; in the address bar.
+Drugi sposób:
-2nd way
-Menu &gt; file &gt; connect to server
-Fill the dialog
-- Server: hubzilla_domain_name
-- Type: Secure WebDAV (https)
+1) Menu &gt; Plik &gt; Połącz z serwerem...
+2) Wypełnij okna w formatce dialogowej:
+- Sewer: hubzilla_domain_name
+- Typ: Secure WebDAV (https)
- Folder: /dav
-- Username: yourchannelname
-- Password: yourpassword
+- Nazwa użytkownika: twoja_nazwa_kanału
+- Hasło: twoje_hasło
-Once open you can set a bookmark.
+Po otwarciu możesz ustawić zakładkę.
-[h5]Server Notes[/h5]
+[h5][b]Uwagi dotyczące serwera[/b][/h5]
-Note: There have been reported issues with clients that use "chunked transfer encoding", which includes Apple iOS services, and also the "AnyClient" and "CyberDuck" tools. These work fine for downloads, but uploads often end up with files of zero size. This is caused by an incorrect implemention of chunked encoding in some current FCGI (fast-cgi) implementations. Apache running with PHP as a module does not have these issues, but when running under FCGI you may need to use alternative clients or use the web uploader. At the time of this writing the issue has been open and no updates provided for at least a year. If you encounter zero size files with other clients, please check the client notes; as there are occasional configuration issues which can also produce these symptoms.
+Zgłoszono problemy z klientami używającymi "chunked transfer encoding", które obejmuje usługi Apple iOS, a także narzędzia "AnyClient" i "CyberDuck". Działają one dobrze w przypadku pobierania, ale przesyłanie często kończy się plikami o zerowym rozmiarze. Jest to spowodowane nieprawidłową implementacją kodowania fragmentarycznego w niektórych obecnych implementacjach FCGI (fast-cgi). Apache działający z PHP jako modułem nie ma tych problemów, ale podczas pracy pod FCGI może być konieczne użycie alternatywnych klientów lub użycie programu do przesyłania internetowego. W chwili pisania tego artykułu problem był otwarty i nie udostępniono żadnych aktualizacji przez co najmniej rok. Jeśli napotkasz pliki o rozmiarze zerowym z innymi klientami, zapoznaj się z uwagami klienta; ponieważ czasami występują problemy z konfiguracją, które również mogą powodować te objawy.
-[h3]Saved Searches[/h3]
+[h3]Zapisane wyszukiwania[/h3]
-In order to quickly find information, the 'saved search' widget may be used. This widget may be presented as a sidebar tool on your network page and possibly from your channel page. It is differentiated from the 'navigation bar' search tool in that it does not search the entire site, but only the subset of information available to your channel.
+W celu szybkiego wyszukania informacji można skorzystać z widżetu "saved search". Ten widżet może być prezentowany jako narzędzie paska bocznego na Twojej stronie internetowej i prawdopodobnie na stronie Twojego kanału. Różni się od narzędzia wyszukiwania "paska nawigacji" tym, że nie przeszukuje całej witryny, a jedynie podzbiór informacji dostępnych na Twoim kanale.
-Additionally the search terms you provide may activate a one-time search or be saved in a list for re-use. Saving the search item also invokes the search in addition to adding it to the saved list (which is displayed below the search text entry box). Any item in the list may be discarded if it is no longer needed.
+Ponadto podane przez Ciebie frazy wyszukiwania mogą aktywować jednorazowe wyszukiwanie lub zostać zapisane na liście do ponownego wykorzystania. Zapisanie elementu wyszukiwania wywołuje również przeszukiwanie, oprócz dodania go do zapisanej listy (która jest wyświetlana poniżej pola wprowadzania tekstu wyszukiwania). Każdy element na liście może zostać odrzucony, jeśli nie jest już potrzebny.
-The saved search widget will provide autocompletion of channels (the results are prefixed with '@'), and hashtags (prefixed with '#'). You do not need to enter these tags; although entering the desired tag will reduce the autocomplete results to only hold the relevant information. The behaviour maps as follows:
+Zapisany widżet wyszukiwania zapewni automatyczne uzupełnianie kanałów (wyniki są poprzedzone znakiem @) i hashtagami (poprzedzonymi znakiem #). Nie trzeba wprowadzać tych tagów; chociaż wprowadzenie żądanego tagu zmniejszy wyniki autouzupełniania, aby zawierały tylko istotne informacje. Zachowanie odwzorowuje się następująco:
[list]
-[*]@name - search your network stream for posts or comments written by 'name'. This will also change the post editor permissions to include only 'name'; as if this was a privacy group.
-[*]#hashtag - search you network stream for posts containing #hashtag.
-[*]text - search your network stream for posts containing 'text'.
+[*]@name - przeszukuje strumienia sieci w poszukiwaniu postów lub komentarzy napisanych przez 'name'. Spowoduje to również zmianę uprawnień edytora postów, aby zawierały tylko 'name'; jakby to była grupa prywatności.
+[*]#hashtag - przeszukauje strumień sieci w poszukiwaniu postów zawierających #hashtag.
+[*]text - przeszukaj strumień sieci w poszukiwaniu postów zawierających 'text'.
[/list]
-[h3]Remove Channel or Account[/h3]
-
-[h4]Remove Channel[/h4]
-
-Select the 'Remove Channel' link on your channel settings page or visit the URL:
+[h3]Usunięcie kanału lub konta[/h3]
- [baseurl]/removeme
+[h4][b]Usuniecie kanału[/b][/h4]
-You will need to confirm your password and the channel you are currently logged into will be removed.
+Wybierz link 'Usuń kanał' na stronie ustawień kanału lub odwiedź URL [baseurl]/removeme.
-[hl][i][b]This is irreversible.[/b][/i][/hl]
+Będziesz musiał potwierdzić swoje hasło i kanał, na którym jesteś obecnie zalogowany, zostanie usunięty.
-If you have identity clones on other hubs this only removes by default the channel instance which exists on this hub.
+[hl][i][b]To jest nieodwracalne.[/b][/i][/hl]
-[h4]Remove Account[/h4]
+Jeśli masz klony tożsamości na innych hubach, nie zostaną one usuniete. Operacja ta spowoduje tylko usunięcie tej instancji kanału, która istnieje w hubie, na którym dokonujesz usunięcia kanału.
-Select 'Remove Account' from your account settings page or visit the URL:
+[h4][b]Usuniecie konta[/b][/h4]
- [baseurl]/removeaccount
+Wybierz link 'Usuń konto' widoczny na stronie ustawień konta lub odwiedź URL: [baseurl]/removeaccount
-You will need to confirm your password and the account you are currently logged into will be removed.
+Będziesz musiał potwierdzić swoje hasło i konto, na którym jesteś obecnie zalogowany, zostanie usunięte.
-[hl][i][b]This is irreversible.[/b][/i][/hl]
+[hl][i][b]To jest nieodwracalne.[/b][/i][/hl]
-All your channels will be deleted. If you have identity clones on other hubs this only removes by default the channels instances which exists on this hub.
+Wszystkie Twoje kanały zostaną usunięte. Jeśli masz klony tożsamości na innych hubach - nie zostaną one usuniete. Operacja ta powoduje tylko usunięcie instancji kanałów, które istnieją hubie, na którym dokonujesz tą operację.
diff --git a/doc/pl/tutorials/assets/0965ace945f0c95ae38aa5bfedd230d2a7233d3915ac15d629f9dd845854.png b/doc/pl/tutorials/assets/0965ace945f0c95ae38aa5bfedd230d2a7233d3915ac15d629f9dd845854.png
new file mode 100644
index 000000000..d5cf1093f
--- /dev/null
+++ b/doc/pl/tutorials/assets/0965ace945f0c95ae38aa5bfedd230d2a7233d3915ac15d629f9dd845854.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/1ebe02c205962dd25035c441631745d16acdb7a44e50d148256c8ad26a67.png b/doc/pl/tutorials/assets/1ebe02c205962dd25035c441631745d16acdb7a44e50d148256c8ad26a67.png
new file mode 100644
index 000000000..d613925aa
--- /dev/null
+++ b/doc/pl/tutorials/assets/1ebe02c205962dd25035c441631745d16acdb7a44e50d148256c8ad26a67.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/2243e48ccea25bd907cce3dbd6fc9f7cd832a4c91a4c5dd294b7b219e7d8.png b/doc/pl/tutorials/assets/2243e48ccea25bd907cce3dbd6fc9f7cd832a4c91a4c5dd294b7b219e7d8.png
new file mode 100644
index 000000000..c403bf806
--- /dev/null
+++ b/doc/pl/tutorials/assets/2243e48ccea25bd907cce3dbd6fc9f7cd832a4c91a4c5dd294b7b219e7d8.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/25eaad2435200f72a1dd3a00ba17a76ca6db4c246b3c4fa286b390cae7c8.png b/doc/pl/tutorials/assets/25eaad2435200f72a1dd3a00ba17a76ca6db4c246b3c4fa286b390cae7c8.png
new file mode 100644
index 000000000..ca8ba6fb9
--- /dev/null
+++ b/doc/pl/tutorials/assets/25eaad2435200f72a1dd3a00ba17a76ca6db4c246b3c4fa286b390cae7c8.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/2b539d5a8474d6ec6dc91155b628d9be5f99ab04a78108ec404f53ec7bb5.png b/doc/pl/tutorials/assets/2b539d5a8474d6ec6dc91155b628d9be5f99ab04a78108ec404f53ec7bb5.png
new file mode 100644
index 000000000..0da2d96e2
--- /dev/null
+++ b/doc/pl/tutorials/assets/2b539d5a8474d6ec6dc91155b628d9be5f99ab04a78108ec404f53ec7bb5.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/31f42a02bdbae095e0329db6c3814e2975979aff12f873f43d81724c5e61.png b/doc/pl/tutorials/assets/31f42a02bdbae095e0329db6c3814e2975979aff12f873f43d81724c5e61.png
new file mode 100644
index 000000000..2a209b2be
--- /dev/null
+++ b/doc/pl/tutorials/assets/31f42a02bdbae095e0329db6c3814e2975979aff12f873f43d81724c5e61.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/324247680b605fd214fd61aecd8f216fa8f5dfa0f16a04c8e968fdbc43d0.png b/doc/pl/tutorials/assets/324247680b605fd214fd61aecd8f216fa8f5dfa0f16a04c8e968fdbc43d0.png
new file mode 100644
index 000000000..f992672b0
--- /dev/null
+++ b/doc/pl/tutorials/assets/324247680b605fd214fd61aecd8f216fa8f5dfa0f16a04c8e968fdbc43d0.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/3656a67dce40a1fc2515e9089217f2e136d4fcf8babe77bac00ecaad43ce.png b/doc/pl/tutorials/assets/3656a67dce40a1fc2515e9089217f2e136d4fcf8babe77bac00ecaad43ce.png
new file mode 100644
index 000000000..b656192dc
--- /dev/null
+++ b/doc/pl/tutorials/assets/3656a67dce40a1fc2515e9089217f2e136d4fcf8babe77bac00ecaad43ce.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/458a842c2ea0fbe3b7869bb14dfffe1e5be098d1cd6e590bbead25b4cc05.png b/doc/pl/tutorials/assets/458a842c2ea0fbe3b7869bb14dfffe1e5be098d1cd6e590bbead25b4cc05.png
new file mode 100644
index 000000000..6129195b6
--- /dev/null
+++ b/doc/pl/tutorials/assets/458a842c2ea0fbe3b7869bb14dfffe1e5be098d1cd6e590bbead25b4cc05.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/4aaaf1e124514c8d6999a5fe1d07be5af460cda4ba6cde9106ebc1564bb0.png b/doc/pl/tutorials/assets/4aaaf1e124514c8d6999a5fe1d07be5af460cda4ba6cde9106ebc1564bb0.png
new file mode 100644
index 000000000..923403fe9
--- /dev/null
+++ b/doc/pl/tutorials/assets/4aaaf1e124514c8d6999a5fe1d07be5af460cda4ba6cde9106ebc1564bb0.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/4cf326152797a8ecdf5630e921756f825ee00f8ee464d3ef9fed971d2852.png b/doc/pl/tutorials/assets/4cf326152797a8ecdf5630e921756f825ee00f8ee464d3ef9fed971d2852.png
new file mode 100644
index 000000000..f158ad5d9
--- /dev/null
+++ b/doc/pl/tutorials/assets/4cf326152797a8ecdf5630e921756f825ee00f8ee464d3ef9fed971d2852.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/75d2927b7ad0d2043d4d3b6ba1364fac8ead173edd39340adaf78be11c9d.png b/doc/pl/tutorials/assets/75d2927b7ad0d2043d4d3b6ba1364fac8ead173edd39340adaf78be11c9d.png
new file mode 100644
index 000000000..edc8b01cc
--- /dev/null
+++ b/doc/pl/tutorials/assets/75d2927b7ad0d2043d4d3b6ba1364fac8ead173edd39340adaf78be11c9d.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/7c976a06662a1357b3da8ed0680d1a721c85f2ae2bdd5739a8def466010e.png b/doc/pl/tutorials/assets/7c976a06662a1357b3da8ed0680d1a721c85f2ae2bdd5739a8def466010e.png
new file mode 100644
index 000000000..5b259058b
--- /dev/null
+++ b/doc/pl/tutorials/assets/7c976a06662a1357b3da8ed0680d1a721c85f2ae2bdd5739a8def466010e.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/99a6efda4df631dfb2d2a849412044cc6a0f8aebeac289d28786f2649d24.png b/doc/pl/tutorials/assets/99a6efda4df631dfb2d2a849412044cc6a0f8aebeac289d28786f2649d24.png
new file mode 100644
index 000000000..c03ffd18d
--- /dev/null
+++ b/doc/pl/tutorials/assets/99a6efda4df631dfb2d2a849412044cc6a0f8aebeac289d28786f2649d24.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/9eae9fad774a4cd29e665961d35affbd053368056f562c58200fb41027b0.png b/doc/pl/tutorials/assets/9eae9fad774a4cd29e665961d35affbd053368056f562c58200fb41027b0.png
new file mode 100644
index 000000000..65d4c5f0a
--- /dev/null
+++ b/doc/pl/tutorials/assets/9eae9fad774a4cd29e665961d35affbd053368056f562c58200fb41027b0.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/b0bfdf02aef3710a37bb6092c3240b291eca8afa73133b3ac03b86f3302d.png b/doc/pl/tutorials/assets/b0bfdf02aef3710a37bb6092c3240b291eca8afa73133b3ac03b86f3302d.png
new file mode 100644
index 000000000..45609a7bb
--- /dev/null
+++ b/doc/pl/tutorials/assets/b0bfdf02aef3710a37bb6092c3240b291eca8afa73133b3ac03b86f3302d.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/b334915c03a665493915598c69c17a87c910a39db2cd3b5292e4623ea4c4.png b/doc/pl/tutorials/assets/b334915c03a665493915598c69c17a87c910a39db2cd3b5292e4623ea4c4.png
new file mode 100644
index 000000000..d239d6965
--- /dev/null
+++ b/doc/pl/tutorials/assets/b334915c03a665493915598c69c17a87c910a39db2cd3b5292e4623ea4c4.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/b3eece28e8db67f1024af42055f0f24ed5e81ba622aca8cac576ccf5930e.png b/doc/pl/tutorials/assets/b3eece28e8db67f1024af42055f0f24ed5e81ba622aca8cac576ccf5930e.png
new file mode 100644
index 000000000..45ed64d00
--- /dev/null
+++ b/doc/pl/tutorials/assets/b3eece28e8db67f1024af42055f0f24ed5e81ba622aca8cac576ccf5930e.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/bdbcf0ffd9004657237f6b7b7863da5a8e39a5bc17d2c67fa160efef2056.png b/doc/pl/tutorials/assets/bdbcf0ffd9004657237f6b7b7863da5a8e39a5bc17d2c67fa160efef2056.png
new file mode 100644
index 000000000..fcaed8bef
--- /dev/null
+++ b/doc/pl/tutorials/assets/bdbcf0ffd9004657237f6b7b7863da5a8e39a5bc17d2c67fa160efef2056.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/c4cad3e4c356dd2a227df79bd4dc6d47edf1b66ea243f005b6b452ec366b.png b/doc/pl/tutorials/assets/c4cad3e4c356dd2a227df79bd4dc6d47edf1b66ea243f005b6b452ec366b.png
new file mode 100644
index 000000000..0ccfc8995
--- /dev/null
+++ b/doc/pl/tutorials/assets/c4cad3e4c356dd2a227df79bd4dc6d47edf1b66ea243f005b6b452ec366b.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/c9a880cc82ffa1f7c2f460397bb083bf7dc2a2b8f065e64da598b45b4a2b.png b/doc/pl/tutorials/assets/c9a880cc82ffa1f7c2f460397bb083bf7dc2a2b8f065e64da598b45b4a2b.png
new file mode 100644
index 000000000..1cb4d2d22
--- /dev/null
+++ b/doc/pl/tutorials/assets/c9a880cc82ffa1f7c2f460397bb083bf7dc2a2b8f065e64da598b45b4a2b.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/d080e92d797af5e863fa39b2084c16a8410de1f7a6559633435817444aef.png b/doc/pl/tutorials/assets/d080e92d797af5e863fa39b2084c16a8410de1f7a6559633435817444aef.png
new file mode 100644
index 000000000..22e4cb5d5
--- /dev/null
+++ b/doc/pl/tutorials/assets/d080e92d797af5e863fa39b2084c16a8410de1f7a6559633435817444aef.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/e05248fdc5688d6d24bde52432fdc7b39692a094559aa504de99352940b1.png b/doc/pl/tutorials/assets/e05248fdc5688d6d24bde52432fdc7b39692a094559aa504de99352940b1.png
new file mode 100644
index 000000000..5674f5207
--- /dev/null
+++ b/doc/pl/tutorials/assets/e05248fdc5688d6d24bde52432fdc7b39692a094559aa504de99352940b1.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/e5d5674a34e848e2cce90a60fc416415271d9c51b81ad2a950fb0157222a.png b/doc/pl/tutorials/assets/e5d5674a34e848e2cce90a60fc416415271d9c51b81ad2a950fb0157222a.png
new file mode 100644
index 000000000..e6b4a9974
--- /dev/null
+++ b/doc/pl/tutorials/assets/e5d5674a34e848e2cce90a60fc416415271d9c51b81ad2a950fb0157222a.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/ef78bc6aa3fafebd46f353514c907b3fdfe019918fc5553bb3f31388a36f.png b/doc/pl/tutorials/assets/ef78bc6aa3fafebd46f353514c907b3fdfe019918fc5553bb3f31388a36f.png
new file mode 100644
index 000000000..8de042ae4
--- /dev/null
+++ b/doc/pl/tutorials/assets/ef78bc6aa3fafebd46f353514c907b3fdfe019918fc5553bb3f31388a36f.png
Binary files differ
diff --git a/doc/pl/tutorials/assets/facb0bdfdecb4c779de9048cd14b417c0d76de17af476be5f296b78d70e9.png b/doc/pl/tutorials/assets/facb0bdfdecb4c779de9048cd14b417c0d76de17af476be5f296b78d70e9.png
new file mode 100644
index 000000000..cec391fb4
--- /dev/null
+++ b/doc/pl/tutorials/assets/facb0bdfdecb4c779de9048cd14b417c0d76de17af476be5f296b78d70e9.png
Binary files differ
diff --git a/doc/pl/tutorials/personal_channel.md b/doc/pl/tutorials/personal_channel.md
new file mode 100644
index 000000000..6b96cf14a
--- /dev/null
+++ b/doc/pl/tutorials/personal_channel.md
@@ -0,0 +1,116 @@
+
+Ten poradnik trzeba wykonać w kolejności, tak jakbyś konfigurował plik kanału po raz pierwszy. Przedstawia w naturalny sposób niektóre narzędzia i funkcje związane z kanałem osobistym.
+
+### Tworzenie nowego kanału
+
+Kiedy logujesz się po raz pierwszy po rejestracji, musisz utworzyć kanał albo odwiedzić później stronę *https://your_website/new_channel*.
+
+![](assets/c9a880cc82ffa1f7c2f460397bb083bf7dc2a2b8f065e64da598b45b4a2b.png)
+
+Wprowadź swoje imię i nazwisko oraz pseudonim dla adresu kanału, a następnie wybierz "rolę". Zazwyczaj, jeśli reprezentuje Cię osobisty kanał, wybierz *Społeczność* z domyślnym poziomem prywatności, który Ci odpowiada. Jeśli nie masz pewności, wybierz opcję *Społecznościowe - głównie publiczne*, co umożliwia łatwą interakcję i zapewnia prywatność, gdy jej potrzebujesz. Alternatywnie, ustawienie *Społecznościowe - ograniczone* jest bardzo popularne wśród obrońców prywatności, chociaż poznanie ludzi może wymagać nieco więcej wysiłku. Niezależnie od tego, które ustawienie wybierzesz, możesz zmienić je później, jeśli zajdzie taka potrzeba.
+
+### Dodanie zdjęcia profilowego
+
+Po utworzeniu nowego kanału zostaniesz przekierowany na stronę określoną przez administratora witryny. Domyślnie jest to strona * Edytuj profil *.
+
+Z poziomu rozwijanego menu *Narzędzia profili* wybierz opcję *Zmień zdjęcie profilowe* (lub po prostu kliknij zdjęcie profilowe).
+
+![](assets/31f42a02bdbae095e0329db6c3814e2975979aff12f873f43d81724c5e61.png)
+
+Prześlij swoje zdjęcie i jeśli to konieczne, zmień rozmiar za pomocą edytora obrazów.
+
+![](assets/458a842c2ea0fbe3b7869bb14dfffe1e5be098d1cd6e590bbead25b4cc05.png)
+
+Po naciśnięciu *Edycja zakończona* nastąpi przekierowanie z powrotem do edytora profili.
+
+> Jeśli masz problemy z wyświetleniem nowego zdjęcia, może być konieczne
+> wyczyszczenie pamięci podręcznej przeglądarki.
+
+![](assets/d080e92d797af5e863fa39b2084c16a8410de1f7a6559633435817444aef.png)
+
+Po powrocie na stronę główną kanału zobaczysz, że wpis powiadamiający innych o Twoim nowym zdjęciu profilowym, który został automatycznie opublikowany.
+
+![](assets/1ebe02c205962dd25035c441631745d16acdb7a44e50d148256c8ad26a67.png)
+
+
+### Tworzenie wpisów
+
+Przejdź do strony głównej swojego kanału i otwórz edytor wpisów, naciskając pole tekstowe *Udostępnij* u góry "ściany" kanału. Wprowadź wiadomość, a następnie przeciągnij i upuść plik obrazu do do obszaru tekstowego edytora postów. Ewentualnie możesz użyć narzędzie *Załącz plik*, widoczne u dołu.
+
+![](assets/b0bfdf02aef3710a37bb6092c3240b291eca8afa73133b3ac03b86f3302d.png)
+
+Plik obrazu zostanie automatycznie przesłany i zapisany w plikach w chmurze, a łącze pojawi się w oknie wpisu. Naciśnięcie przycisku podglądu wpisu umożliwia podgląd wpisu przed opublikowaniem.
+
+![](assets/7c976a06662a1357b3da8ed0680d1a721c85f2ae2bdd5739a8def466010e.png)
+
+Naciśnij przycisk kłódki obok przycisku *Prześlij*. SPowoduje to otworzenie się *Listę kontroli dostępu*, gdzie możesz dokładnie określić, kto ma dostęp do tego wpisu.
+
+![](assets/2b539d5a8474d6ec6dc91155b628d9be5f99ab04a78108ec404f53ec7bb5.png)
+
+
+### Użycie przesłanego obrazu jako zdjęcia na okładkę kanału
+
+Jednym ze sposobów uatrakcyjnienia wyglądu kanału jest dodanie zdjęcia na okładkę, które będą widzieć użytkownicy po załadowaniu strony kanału. Zintegrowany system plików w chmurze pozwala wybrać w tym celu istniejące zdjęcie.
+
+Odwiedź swoje zdjęcia w aplikacji *Photos*.
+
+![](assets/0965ace945f0c95ae38aa5bfedd230d2a7233d3915ac15d629f9dd845854.png)
+
+Wybierz zdjęcie, którego chcesz użyć i wybierz *Użyj jako zdjęcia na okładkę* z rozwijanego menu *Narzędzia do zdjęć*.
+
+![](assets/9eae9fad774a4cd29e665961d35affbd053368056f562c58200fb41027b0.png)
+
+Przytnij obraz za pomocą edytora zdjęć i zapisz zmiany.
+
+![](assets/b3eece28e8db67f1024af42055f0f24ed5e81ba622aca8cac576ccf5930e.png)
+
+Gdy załadujesz stronę główną swojego kanału, najpierw zobaczysz zdjęcie okładkowe a strona kanału będzie się pojawiać w miarę przewijania w dół.
+
+![](assets/4cf326152797a8ecdf5630e921756f825ee00f8ee464d3ef9fed971d2852.png)
+
+
+### Wykonywanie połączeń
+
+Tworzenie połączeń między kanałami i udostępnianie treści, to istosta komunikacji społecznej. Nawiązanie połączenia jest proste. Jeśli jeszcze nie wiesz, jak dotrzeć do strony domowej kanału, możesz spróbować przeszukać katalog, otwierając łącze *Katalog* z menu po prawej stronie z boku górnego paska nawigacyjnego.
+
+![](assets/ef78bc6aa3fafebd46f353514c907b3fdfe019918fc5553bb3f31388a36f.png)
+
+Możesz połączyć się bezpośrednio z poziomu katalogu za pomocą przycisku *Połącz* lub możesz najpierw otworzyć stronę kanału i nacisnąć przycisk *Połącz* widoczny poniżej zdjęcia profilowego.
+
+![](assets/75d2927b7ad0d2043d4d3b6ba1364fac8ead173edd39340adaf78be11c9d.png)
+
+Po nawiązaniu połączenia zostaniesz natychmiast przeniesiony do strony edytora połączeń, gdzie podejmujesz ważne decyzje dotyczące tego, co planujesz udostępniać na tym kanale.
+
+![](assets/b334915c03a665493915598c69c17a87c910a39db2cd3b5292e4623ea4c4.png)
+
+Dwa ważne ustawienia to
+
+* Indywidualne uprawnienia dla nowo podłączonego kanału
+* Grupy prywatności, do których należy połączenie
+
+Indywidualne uprawnienia są w większości łatwe do zrozumienia, ale mogą być na początku niejasne. Na przykład *Można wyświetlać mój magazyn plików i zdjęć* nie oznacza, że na podłączonym kanale każdy będzie mógł przeglądać wszystkie Twoje zdjęcia i pliki! Oznacza to, że będziesz mieć możliwość udostępniania zdjęć i plików za pomocą tego kanału. Jest całkiem możliwe, że pozwolisz komuś czytać swoje wpisy, ale nie zezwolisz na oglądanie zdjęć w tym wpisie.
+
+Grupy prywatności umożliwiają wygodnie udostępniać elementy grupom osób. Można utworzyć dowolne grupy odpowiadające swoim potrzebom, otwierając link *Dodaj grupę prywatności*.
+
+![](assets/facb0bdfdecb4c779de9048cd14b417c0d76de17af476be5f296b78d70e9.png)
+
+W tym edytorze można przełączać się między istniejącymi grupami prywatności i od razu sprawdzić, jakie kanały są, a jakie nie są członkami grupy. Wybranie ikony kanału w dowolnym polu spowoduje przeniesienie kanału do tej grupy.
+
+![](assets/25eaad2435200f72a1dd3a00ba17a76ca6db4c246b3c4fa286b390cae7c8.png)
+
+Podczas edycji ustawień pojedynczego kanału można ustawić jego członkostwo w grupach prywatności za pomocą widżetu po lewej stronie:
+
+![](assets/bdbcf0ffd9004657237f6b7b7863da5a8e39a5bc17d2c67fa160efef2056.png)
+
+Połączenia to wzajemne zaangażowanie. Kanał, z którym się łączysz, może mieć ustawioną opcję zatwierdzenia połączenia z innym kanałem. Zostanie wówczas wysłane do niego powiadomienie o proonowanym połączeniu:
+
+![](assets/324247680b605fd214fd61aecd8f216fa8f5dfa0f16a04c8e968fdbc43d0.png)
+
+w którym znajduje się link do strony edytora [*Połączenia*](https://grid.reticu.li/connections), gdzie można zdecydować, czy zezwolić na połączenie, czy nie.
+
+![](assets/e05248fdc5688d6d24bde52432fdc7b39692a094559aa504de99352940b1.png)
+
+Po zatwierdzeniu połączenia dobrze jest otworzyć edytor połączeń indywidualnych, naciskając przycisk edycji obok przycisku *Usuń*.
+
+![](assets/c4cad3e4c356dd2a227df79bd4dc6d47edf1b66ea243f005b6b452ec366b.png)
+
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 057711f1e..87b1d96fe 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -64,15 +64,23 @@ function photo_factory($data, $type = null) {
*
* @param string $filename
* Image filename
- * @param string $headers (optional)
- * Headers to check for Content-Type (from curl request)
+ * @param string $data (optional)
+ * Data array fetched from cURL with z_fetch_url
* @return null|string Guessed mimetype
*/
-function guess_image_type($filename, $headers = '') {
-// logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG);
+function guess_image_type($filename, $data = '') {
+
+ if($data)
+ $headers = (is_array($data) ? $data['header'] : $data);
+
+ // logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG);
+
$type = null;
$m = null;
+ $ph = photo_factory('');
+ $types = $ph->supportedTypes();
+
if($headers) {
$hdrs = [];
$h = explode("\n", $headers);
@@ -81,19 +89,14 @@ function guess_image_type($filename, $headers = '') {
$hdrs[strtolower($k)] = $v;
}
logger('Curl headers: ' .var_export($hdrs, true), LOGGER_DEBUG);
- if(array_key_exists('content-type', $hdrs)) {
- $ph = photo_factory('');
- $types = $ph->supportedTypes();
-
- if(array_key_exists($hdrs['content-type'], $types))
- $type = $hdrs['content-type'];
- }
+ if(array_key_exists('content-type', $hdrs) && array_key_exists($hdrs['content-type'], $types))
+ $type = $hdrs['content-type'];
}
if(is_null($type)){
$ignore_imagick = get_config('system', 'ignore_imagick');
// Guessing from extension? Isn't that... dangerous?
- if(class_exists('Imagick') && file_exists($filename) && is_readable($filename) && !$ignore_imagick) {
+ if(class_exists('Imagick') && ! $ignore_imagick) {
$v = Imagick::getVersion();
preg_match('/ImageMagick ([0-9]+\.[0-9]+\.[0-9]+)/', $v['versionString'], $m);
if(version_compare($m[1], '6.6.7') >= 0) {
@@ -102,8 +105,18 @@ function guess_image_type($filename, $headers = '') {
* but at least it comes from the data inside the image,
* we won't be tricked by a manipulated extension
*/
- $image = new Imagick($filename);
- $type = $image->getImageMimeType();
+ $body = false;
+ if (strpos($filename, 'http') === false && file_exists($filename) && is_readable($filename))
+ $body == file_get_contents($filename);
+ elseif (is_array($data) && array_key_exists('body', $data))
+ $body = $data['body'];
+ if ($body) {
+ $image = new Imagick($filename);
+ $image->readImageBlob($body);
+ $r = $image->identifyImage();
+ if ($r && is_array($r) && array_key_exists($r['mimetype'], $types))
+ $type = $r['mimetype'];
+ }
}
else {
// earlier imagick versions have issues with scaling png's
@@ -115,8 +128,6 @@ function guess_image_type($filename, $headers = '') {
if(is_null($type)) {
$ext = pathinfo($filename, PATHINFO_EXTENSION);
- $ph = photo_factory('');
- $types = $ph->supportedTypes();
foreach($types as $m => $e) {
if($ext === $e) {
$type = $m;
@@ -124,12 +135,12 @@ function guess_image_type($filename, $headers = '') {
}
}
- if(is_null($type) && (strpos($filename, 'http') === false)) {
+ if(is_null($type) && strpos($filename, 'http') === 0) {
$size = getimagesize($filename);
- $ph = photo_factory('');
- $types = $ph->supportedTypes();
- $type = ((array_key_exists($size['mime'], $types)) ? $size['mime'] : 'image/jpeg');
+ if (array_key_exists($size['mime'], $types))
+ $type = $size['mime'];
}
+
if(is_null($type)) {
if(strpos(strtolower($filename),'jpg') !== false)
$type = 'image/jpeg';
@@ -139,8 +150,8 @@ function guess_image_type($filename, $headers = '') {
$type = 'image/gif';
elseif(strpos(strtolower($filename),'png') !== false)
$type = 'image/png';
- elseif(strpos(strtolower($filename),'webp') !== false)
- $type = 'image/webp';
+ elseif(strpos(strtolower($filename),'webp') !== false)
+ $type = 'image/webp';
}
}
@@ -224,7 +235,7 @@ function import_xchan_photo($photo, $xchan, $thing = false, $force = false) {
$photo_failure = false;
$img_str = '';
- if($photo) {
+ if($photo && strpos($photo, z_root() . '/' . get_default_profile_photo()) === false) {
if($force || empty($modified))
$result = z_fetch_url($photo, true);
@@ -264,7 +275,7 @@ function import_xchan_photo($photo, $xchan, $thing = false, $force = false) {
if($result['success']) {
$img_str = $result['body'];
- $type = guess_image_type($photo, $result['header']);
+ $type = guess_image_type($photo, $result);
if(is_null($type))
$photo_failure = true;
}
@@ -377,8 +388,7 @@ function import_channel_photo_from_url($photo, $aid, $uid) {
if($result['success']) {
$img_str = $result['body'];
- $type = guess_image_type($photo, $result['header']);
-
+ $type = guess_image_type($photo, $result);
import_channel_photo($img_str, $type, $aid, $uid);
}
}
diff --git a/view/pl/hmessages.mo b/view/pl/hmessages.mo
deleted file mode 100644
index cbf6f399c..000000000
--- a/view/pl/hmessages.mo
+++ /dev/null
Binary files differ
diff --git a/view/pl/hmessages.po b/view/pl/hmessages.po
index 10dfc3b0b..5ef34eb5e 100644
--- a/view/pl/hmessages.po
+++ b/view/pl/hmessages.po
@@ -10,8 +10,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 "
-"|| n%100>14) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2));\n"
"X-Generator: Poedit 2.3\n"
#: ../../Zotlabs/Access/Permissions.php:56
@@ -74,7 +73,7 @@ msgstr "Może polubiać/dezaprobować profile i rzeczy w profilach"
msgid "Can forward to all my channel connections via ! mentions in posts"
msgstr ""
"Może przekazywać informacje do wszystkich moich połączeń kanałowych za "
-"pośrednictwem! wzmianki w postach"
+"pośrednictwem !wzmianki w postach"
#: ../../Zotlabs/Access/Permissions.php:71
msgid "Can chat with me"
@@ -5095,7 +5094,7 @@ msgstr "Bezpieczeństwo"
#: ../../Zotlabs/Module/Admin/Security.php:101
msgid "Block public"
-msgstr "Zablokuj publiczny dstęp"
+msgstr "Zablokuj publiczny dostęp"
#: ../../Zotlabs/Module/Admin/Security.php:101
msgid ""
@@ -5325,7 +5324,7 @@ msgstr "On"
#: ../../Zotlabs/Module/Admin/Features.php:56
#, php-format
msgid "Lock feature %s"
-msgstr "Funkcja blokady %s"
+msgstr "Blokuj funkcję %s"
#: ../../Zotlabs/Module/Admin/Features.php:64
msgid "Manage Additional Features"
@@ -9984,7 +9983,7 @@ msgstr "Przykłady: bob@example.com, https://example.com/barbara"
#: ../../Zotlabs/Widget/Suggestions.php:53
msgid "Suggestions"
-msgstr "Prpozycje"
+msgstr "Propozycje"
#: ../../Zotlabs/Widget/Suggestions.php:54
msgid "See more..."
@@ -10943,7 +10942,7 @@ msgstr "Film/taniec/kultura/rozrywka:"
#: ../../include/channel.php:1861
msgid "Love/Romance:"
-msgstr "Miłość/romans:"
+msgstr "Miłość/Romans:"
#: ../../include/channel.php:1863
msgid "Work/employment:"
diff --git a/view/pl/hstrings.php b/view/pl/hstrings.php
index e80645bdb..7a58ab97f 100644
--- a/view/pl/hstrings.php
+++ b/view/pl/hstrings.php
@@ -2,11 +2,10 @@
if(! function_exists("string_plural_select_pl")) {
function string_plural_select_pl($n){
- return ($n==1 ? 0 : $n%10>=2 && $n%10<=4 && ($n%100<12))
-;
+ return ($n==1 ? 0 : ($n%10>=2 && $n%10<=4 && ($n%100<12 || $n%100>14) ? 1 : 2));
}}
App::$rtl = 0;
-App::$strings["plural_function_code"] = "(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12))";
+App::$strings["plural_function_code"] = "(n==1 ? 0 : (n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2))";
App::$strings["Can view my channel stream and posts"] = "Może wyświetlać strumień i posty z mojego kanału";
App::$strings["Can send me their channel stream and posts"] = "Może przesyłać mi strumień swojego kanału i posty";
App::$strings["Can view my default channel profile"] = "Może wyświetlać mój domyślny profil kanału";
@@ -21,7 +20,7 @@ App::$strings["Can post on my channel (wall) page"] = "Może publikować na stro
App::$strings["Can comment on or like my posts"] = "Może komentować lub polubić moje posty";
App::$strings["Can send me private mail messages"] = "Może wysyłać mi prywatne wiadomości e-mail";
App::$strings["Can like/dislike profiles and profile things"] = "Może polubiać/dezaprobować profile i rzeczy w profilach";
-App::$strings["Can forward to all my channel connections via ! mentions in posts"] = "Może przekazywać informacje do wszystkich moich połączeń kanałowych za pośrednictwem! wzmianki w postach";
+App::$strings["Can forward to all my channel connections via ! mentions in posts"] = "Może przekazywać informacje do wszystkich moich połączeń kanałowych za pośrednictwem !wzmianki w postach";
App::$strings["Can chat with me"] = "Może ze mną rozmawiać";
App::$strings["Can source my public posts in derived channels"] = "Może pozyskiwać moje publiczne posty w kanałach pochodnych";
App::$strings["Can administer my channel"] = "Może zarządzać moim kanałem";
@@ -987,7 +986,7 @@ App::$strings["The recommended setting is to only allow unfiltered HTML from the
App::$strings["https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />"] = "https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />";
App::$strings["All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked."] = "Wszystkie inne osadzone treści będą filtrowane, <strong>chyba że</strong> osadzone treści z tego serwisu są jawnie zablokowane.";
App::$strings["Security"] = "Bezpieczeństwo";
-App::$strings["Block public"] = "Zablokuj publiczny dstęp";
+App::$strings["Block public"] = "Zablokuj publiczny dostęp";
App::$strings["Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated."] = "Zaznacz, aby zablokować publiczny dostęp do wszystkich innych publicznych stron osobistych w tej witrynie, chyba że jesteś obecnie uwierzytelniony.";
App::$strings["Provide a cloud root directory"] = "Podaj katalog główny w chmurze";
App::$strings["The cloud root directory lists all channel names which provide public files"] = "Katalog główny w chmurze zawiera listę wszystkich nazw kanałów, które udostępniają pliki publiczne";
@@ -1039,7 +1038,7 @@ App::$strings["Selected accounts will be deleted!\\n\\nEverything these accounts
App::$strings["The account {0} will be deleted!\\n\\nEverything this account has posted on this site will be permanently deleted!\\n\\nAre you sure?"] = "Konto {0} zostanie usuniete!\\n\\nWszystko co opublikowano z tego konta na tym serwisie zostanie bezpowrotnie usunięte!\\n\\nCzy na pewno usunąć?";
App::$strings["Off"] = "Off";
App::$strings["On"] = "On";
-App::$strings["Lock feature %s"] = "Funkcja blokady %s";
+App::$strings["Lock feature %s"] = "Blokuj funkcję %s";
App::$strings["Manage Additional Features"] = "Zarządzaj dodatkowymi funkcjami";
App::$strings["Queue Statistics"] = "Statystyki kolejki";
App::$strings["Total Entries"] = "Ogółem postów";
@@ -2057,7 +2056,7 @@ App::$strings["You have %1$.0f of %2$.0f allowed connections."] = "Masz %1$.0f z
App::$strings["Add New Connection"] = "Dodaj nowe połączenie";
App::$strings["Enter channel address"] = "Wprowadź adres kanału";
App::$strings["Examples: bob@example.com, https://example.com/barbara"] = "Przykłady: bob@example.com, https://example.com/barbara";
-App::$strings["Suggestions"] = "Prpozycje";
+App::$strings["Suggestions"] = "Propozycje";
App::$strings["See more..."] = "Zobacz więcej...";
App::$strings["Tasks"] = "Zadania";
App::$strings["Member registrations waiting for confirmation"] = "Rejestracja członków czeka na potwierdzenie";
@@ -2314,7 +2313,7 @@ App::$strings["Musical interests:"] = "Zainteresowania muzyczne:";
App::$strings["Books, literature:"] = "Książki, literatura:";
App::$strings["Television:"] = "Telewizja:";
App::$strings["Film/dance/culture/entertainment:"] = "Film/taniec/kultura/rozrywka:";
-App::$strings["Love/Romance:"] = "Miłość/romans:";
+App::$strings["Love/Romance:"] = "Miłość/Romans:";
App::$strings["Work/employment:"] = "Praca/zatrudnienie:";
App::$strings["School/education:"] = "Szkoła/edukacja:";
App::$strings["Like this thing"] = "Jak ta rzecz";